I would like to make my hAxis scrollable and show all my hAxis label values. On the hAxis, the IDs of certain stores are displayed. I have written the following code for the graph:
let array = [[
'Store', 'Amount',
]];
for (let item of response){
array.push([item.store_id.toString(), item.count]);
}
console.log(array);
let data = google.visualization.arrayToDataTable(array);
let options = {
chartArea: {
top: 20,
height: '65%',
width: '75%'
},
hAxis: {
title: 'Store ID',
slantedText: true,
slantedTextAngle: 90,
},
bar: {
groupWidth: 1
},
legend: {
position: 'none'
}
};
let chart = new google.visualization.ColumnChart(document.getElementById('chart-canvas-3'));
chart.draw(data, options);
And the .scss code:
.card-image {
display: block;
box-sizing: border-box;
position: relative;
overflow-x: scroll;
margin-bottom: sz(10pt);
padding-left: 10px;
padding-top: 10px;
padding-right: 10px;
.card-image-inner {
width: 100%;
}
}
So my question is, how can I display all 53 store ID labels on the hAxis (with scroll functionality)?
Thanks!
Current graph
Related
Hej,
I know this has been answered in one way or the other many times, but I really can't get it work in my context with flex-boxes.
I have fixed elements, such as headers and footers on my page, and a chart that shall take up all the remaining space in between. While it appears to be working on first glance, you can see that the text and numbers are blurred and not properly scaled when the window is resized.
How can I fix this, or have chart.js redraw the canvas upon resize?
Check out my fiddle
https://jsfiddle.net/fg9pd1b3/
<body>
<div class="container">
<div class="fixed">
header
</div>
<div id="chartcontainer">
<canvas id="chartJSContainer"></canvas>
</div>
<div class="fixed">
footer
</div>
</div>
</body>
CSS:
html,
body {
height: 100vh;
min-height: 100vh;
max-height: 100vh;
margin: 0;
padding: 0;
}
.container {
width: 80%;
height: 100%;
margin: 0 auto;
display: flex;
flex-direction: column;
flex-basis: 100%;
flex-grow: 1;
background: #CCC;
}
.p {
text-align: center;
font-size: 14px;
padding-top: 140px;
}
.fixed {
background: black;
height: 100px;
min-height: 100px;
color: white;
text-align: center;
}
#chartcontainer {
position: relative;
min-height: 200px;
display: flex;
flex-grow: 1;
}
canvas {
width: 100% !important;
height: 100% !important;
}
JS:
Chart.defaults.global.responsive = true;
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
reverse: false
}
}]
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
You have given fixed min-height to the canvas div which restricts the chart to further change it's dimensions. So, the following code has auto height and width automates to 100% which gives flexible chart.
#chartcontainer {
position:relative;
min-height:auto;
width:100%;
display: flex;
flex-grow:1;
}
Following this Mapbox example (Show and hide layers: https://docs.mapbox.com/mapbox-gl-js/example/toggle-layers/), I have been able to toggle between several layers on a map. But what I would like to achieve is when Layer 1 is visible, the visibility of Layer 2 and Layer 3 is none, when Layer 2 is visible, the visibility of Layer 1 and Layer 3 is none, etc.
Here's a fiddle example with the code I've written so far:
https://jsfiddle.net/reL53uo1/
Here's the logic for the toggle part:
// enumerate ids of the layers
var toggleableLayerIds = ['contours', 'museums', 'contours2'];
// set up the corresponding toggle button for each layer
for (var i = 0; i < toggleableLayerIds.length; i++) {
var id = toggleableLayerIds[i];
var link = document.createElement('a');
link.href = '#';
link.className = 'active';
link.textContent = id;
link.onclick = function(e) {
var clickedLayer = this.textContent;
e.preventDefault();
e.stopPropagation();
var visibility = map.getLayoutProperty(clickedLayer, 'visibility');
// toggle layer visibility by changing the layout object's visibility property
if (visibility === 'visible') {
map.setLayoutProperty(clickedLayer, 'visibility', 'none');
this.className = '';
} else {
this.className = 'active';
map.setLayoutProperty(clickedLayer, 'visibility', 'visible');
}
};
var layers = document.getElementById('menu');
layers.appendChild(link);
What would it be the most efficient approach to achieve this? Thanks.
You could change your onClick function so that instead of toggling individual layers off-and-on it activates the one you want and hides the others. You could do this with a for loop:
link.onclick = function(e) {
var clickedLayer = this.textContent;
e.preventDefault();
e.stopPropagation();
for (var j = 0; j < toggleableLayerIds.length; j++) {
if (clickedLayer === toggleableLayerIds[j]) {
layers.children[j].className = 'active';
map.setLayoutProperty(toggleableLayerIds[j], 'visibility', 'visible');
}
else {
layers.children[j].className = '';
map.setLayoutProperty(toggleableLayerIds[j], 'visibility', 'none');
}
}
};
Additionally, you should set the 'visibility' property of each layer to 'none' in your addLayer() function so that they are hidden until selected.
'layout': {
// make layer invisible by default
'visibility': 'none',
'line-join': 'round',
'line-cap': 'round'
},
I made these changes to your JSFiddle code and pasted below:
mapboxgl.accessToken = 'pk.eyJ1Ijoid2FzaGluZ3RvbnBvc3QiLCJhIjoibWJkTGx1SSJ9.6cMdwgs-AYrRtQsEkXlHqg';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
zoom: 15,
center: [-71.97722138410576, -13.517379300798098]
});
map.on('load', function() {
// add source and layer for museums
map.addSource('museums', {
type: 'vector',
url: 'mapbox://mapbox.2opop9hr'
});
map.addLayer({
'id': 'Layer 1',
'type': 'circle',
'source': 'museums',
'layout': {
// make layer invisible by default
'visibility': 'none'
},
'paint': {
'circle-radius': 8,
'circle-color': 'rgba(55,148,179,1)'
},
'source-layer': 'museum-cusco'
});
// add source and layer for contours
map.addSource('contours', {
type: 'vector',
url: 'mapbox://mapbox.mapbox-terrain-v2'
});
map.addLayer({
'id': 'Layer 2',
'type': 'line',
'source': 'contours',
'source-layer': 'contour',
'layout': {
// make layer invisible by default
'visibility': 'none',
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': '#877b59',
'line-width': 5
}
});
map.addLayer({
'id': 'Layer 3',
'type': 'line',
'source': 'contours',
'source-layer': 'contour',
'layout': {
// make layer invisible by default
'visibility': 'none',
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': 'yellow',
'line-width': 2
}
});
});
// enumerate ids of the layers
var toggleableLayerIds = ['Layer 1', 'Layer 2', 'Layer 3'];
// set up the corresponding toggle button for each layer
for (var i = 0; i < toggleableLayerIds.length; i++) {
var id = toggleableLayerIds[i];
var link = document.createElement('a');
link.href = '#';
link.className = '';
link.textContent = id;
link.onclick = function(e) {
var clickedLayer = this.textContent;
e.preventDefault();
e.stopPropagation();
for (var j = 0; j < toggleableLayerIds.length; j++) {
if (clickedLayer === toggleableLayerIds[j]) {
layers.children[j].className = 'active';
map.setLayoutProperty(toggleableLayerIds[j], 'visibility', 'visible');
}
else {
layers.children[j].className = '';
map.setLayoutProperty(toggleableLayerIds[j], 'visibility', 'none');
}
}
};
var layers = document.getElementById('menu');
layers.appendChild(link);
}
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
#menu {
background: #fff;
position: absolute;
z-index: 1;
top: 10px;
right: 10px;
border-radius: 3px;
width: 120px;
border: 1px solid rgba(0, 0, 0, 0.4);
font-family: 'Open Sans', sans-serif;
}
#menu a {
font-size: 13px;
color: #404040;
display: block;
margin: 0;
padding: 0;
padding: 10px;
text-decoration: none;
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
text-align: center;
}
#menu a:last-child {
border: none;
}
#menu a:hover {
background-color: #f8f8f8;
color: #404040;
}
#menu a.active {
background-color: #3887be;
color: #ffffff;
}
#menu a.active:hover {
background: #3074a4;
}
<link href="https://api.mapbox.com/mapbox-gl-js/v1.10.0/mapbox-gl.css" rel="stylesheet"/>
<script src="https://api.mapbox.com/mapbox-gl-js/v1.10.0/mapbox-gl.js"></script>
<nav id="menu"></nav>
<div id="map"></div>
I am using echarts library for bar charts. I want scrollbar to display outside the canvas. Is there any way I can accomplish this?
Unfortunately, Echarts don't support scrollbar option.
However you can simply achieve this use a wrap DOM.
check this demo:
let echartsObj = echarts.init(document.querySelector('#canvas1'));
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar'
}]
};
echartsObj.setOption(option)
echartsObj = echarts.init(document.querySelector('#canvas2'));
option = {
xAxis: {},
yAxis: {},
series: [{
symbolSize: 20,
data: [
[10.0, 8.04],
[8.0, 6.95],
[13.0, 7.58],
[9.0, 8.81],
[11.0, 8.33],
[14.0, 9.96],
[6.0, 7.24],
[4.0, 4.26],
[12.0, 10.84],
[7.0, 4.82],
[5.0, 5.68]
],
type: 'scatter'
}]
};
echartsObj.setOption(option)
.echart-wrap {
display: inline-block;
width: 300px;
height: 300px;
overflow: scroll;
border: 1px solid black;
}
<html>
<header>
<script src="https://cdn.bootcss.com/echarts/4.1.0.rc2/echarts-en.min.js"></script>
</header>
<body>
<div class="echart-wrap">
<div id="canvas1" style="width: 500px; height: 500px">
</div>
</div>
<div class="echart-wrap">
<div id="canvas2" style="width: 500px; height: 500px">
</div>
</div>
</body>
</html>
I wanted to create a rating alert feature using Ionic alert. This is how it looks.
Go through the answer for detailed codes.
This works properly in all browsers and platforms(as much as I have tested on).
The JS/TS part to create alert -
showRatingAlert() {
const alert = this.alertCtrl.create({
title: 'Rate this app',
cssClass: 'rating_alert',
buttons: [
{ text: '1',
handler: data => { return false; }, // prevents from closing the alert
cssClass: 'rate-icon-button'
},
{ text: '2',
handler: data => { return false; }, // prevents from closing the alert
cssClass: 'rate-icon-button'
},
{ text: '3',
handler: data => { return false; }, // prevents from closing the alert
cssClass: 'rate-icon-button'
},
{ text: '4',
handler: data => { return false; }, // prevents from closing the alert
cssClass: 'rate-icon-button'
},
{ text: '5',
handler: data => { return false; }, // prevents from closing the alert
cssClass: 'rate-icon-button'
},
{ text: 'Later', handler: data => { }, cssClass: 'rate-action-button rate-later' },
{ text: 'Submit', handler: data => { }, cssClass: 'rate-action-button rate-now' },
],
});
// add event listener for icon buttons in ask rating alert popup
setTimeout(()=>{
const buttonElms: NodeList = document.querySelectorAll('.rating_alert .alert-button-group .rate-icon-button');
for(let index = 0; index < buttonElms.length; index++) {
buttonElms[index].addEventListener('click', this.selectedRatingHandler);
}
}, 500);
}
selectedRatingHandler = (event: MouseEvent)=>{
// handler for clicked rating icon button
let target: any = event.target; // target element
let siblings: HTMLCollection = target.parentElement.children; // list of all siblings
for(let index = 0; index < siblings.length; index++){
siblings[index].classList.remove('selected-rating'); // remove selected class from all siblings
}
target.classList.add('selected-rating'); // add selected class to currently selected item
};
The CSS/SCSS part to style elements/buttons -
.rating_alert{
border-radius: 8px;
.alert-wrapper{ border-radius: 8px; }
.alert-button-group{
padding:0;
margin-top: 10px;
flex-direction: row;
justify-content: space-around;
// flex-direction: row; justify-content: space-around;
display: flex;
flex-wrap: wrap;
}
button{
flex: 1 1 20%;
&.rate-icon-button{
width: 40px;
max-width: 20%;
min-width: auto;
height: 40px;
margin: 0 !important;
background-image:url('../assets/img/emotions.png');
background-repeat: no-repeat;
background-position: center;
border: none;
.button-inner{
visibility: hidden;
}
&:nth-child(1){ background-position-y: 3px; }
&:nth-child(2){ background-position-y: -36px; }
&:nth-child(3){ background-position-y: -76px; }
&:nth-child(4){ background-position-y: -114px; }
&:nth-child(5){ background-position-y: -153px; }
&.selected-rating{
position: relative;
overflow: visible;
&:after{
content: '';
position: absolute;
bottom: -4px;
height: 4px;
background-color: #2E6DFF;
width: 80%;
left: 10%;
}
}
}
&.rate-action-button{
text-align: center;
margin-top: 20px;
margin-right: 0;
border-top: 1px solid #c3c3c3;
.button-inner{
justify-content: center;
}
&.rate-later{
border-right: 1px solid #c3c3c3;
}
&.rate-now{
border-left: 1px solid #c3c3c3;
}
}
}
}
The image file used in this example.
I am trying ChartJS line chart with a set of data.I have multiple lines in it. I want to show the tooltip for the data. but I am not able to.
My code is
new Chart(canvas).Line(data,{
responsive : true,
animation: true,
barValueSpacing : 5,
barDatasetSpacing : 1,
tooltipFillColor: "rgba(0,0,0,0.8)",
multiTooltipTemplate: "<%= datasetLabel %> - <%= value %>",
showTooltips:true
});
currently my view of line chart is
What I want is like enter image description here
You can use the custom tooltips option. The below code is adapted from the example at https://github.com/nnnick/Chart.js/blob/master/samples/line-customTooltips.html
Preview
CSS
#canvas-holder {
width: 500px;
height: 300px;
}
#chartjs-tooltip {
opacity: 0;
position: absolute;
background: rgba(0, 0, 0, .7);
font-size: 12px;
color: white;
padding: 5px;
border-radius: 3px;
-webkit-transition: all .1s ease;
transition: all .1s ease;
pointer-events: none;
}
.chartjs-tooltip-section{
padding: 1px;
}
HTML
<div id="canvas-holder">
<canvas id="chart" />
</div>
<div id="chartjs-tooltip"></div>
Script
function CustomLabel(short, long) {
this.short = short;
this.long = long;
}
CustomLabel.prototype.toString = function () {
return this.short;
}
var data = {
labels: [
new CustomLabel("January", "January 11"),
new CustomLabel("February", "February 12"),
new CustomLabel("March", "March 13"),
new CustomLabel("April", "April 14"),
new CustomLabel("May", "May 15"),
new CustomLabel("June", "June 16"),
new CustomLabel("July", "July 17")],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
},
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}
]
};
var ctx = document.getElementById("chart").getContext("2d");
new Chart(ctx).Line(data, {
responsive: true,
customTooltips: function (tooltip) {
var tooltipEl = $('#chartjs-tooltip');
if (!tooltip) {
tooltipEl.css({
opacity: 0
});
return;
}
tooltipEl.removeClass('above below');
tooltipEl.addClass(tooltip.yAlign);
var innerHtml = ['<div class="chartjs-tooltip-section">',
' <span>' + tooltip.title.long + '</span>',
'</div>'
].join('');
for (var i = tooltip.labels.length - 1; i >= 0; i--) {
innerHtml += [
'<div class="chartjs-tooltip-section">',
' <span style="color:' + tooltip.legendColors[i].fill + '">' + data.datasets[i].label + ': ' + tooltip.labels[i] + '</span>',
'</div>'
].join('');
}
tooltipEl.html(innerHtml);
tooltipEl.css({
opacity: 1,
left: tooltip.chart.canvas.offsetLeft + tooltip.x + 'px',
top: tooltip.chart.canvas.offsetTop + tooltip.y + 'px',
fontFamily: tooltip.fontFamily,
fontStyle: tooltip.fontStyle,
});
}
});
Fiddle - http://jsfiddle.net/fLm8c5ee/