Is it possible to add drag and zoom on ChartJS? I would like to do something similar like here.
Here is how I draw my line chart:
<canvas class="square_margin_less" id="myChart" width="100" height="30" > </canvas>
<script>
new Chart(document.getElementById("myChart").getContext('2d'),
{
type: 'line',
data: {
labels: {{ data.labels|safe }},
datasets:
[{
label: 'x',
data: {{ data.x }},
borderColor: 'rgba(233,105,118,1)',
},
{
label: 'y',
data: {{ data.y }},
borderColor: 'rgba(96,143,239,1)'
},
{
label: 'z',
data: {{ data.z }},
borderColor: 'rgba(144,247,136,1)'
}]
},
});
</script>
There is some way of personalizing this?
I didn't find "drag and zoom" functionality for Chart.js as well as simple example with "pan and zoom" version so I've decided to implement demo version own my own.
List of external scripts is very important: hammer-js, then Chart.bundle.js and chartjs-plugin-zoom.js.
const config = {
type: 'line',
data: {
labels: [new Date('2019-08-20'), new Date('2019-08-25'), new Date('2019-08-30')],
datasets: [{
label: 'Line',
data: [2, 5, 3],
borderColor: '#D4213D',
fill: false,
}, ],
},
options: {
scales: {
xAxes: [{
type: 'time',
}, ],
},
pan: {
enabled: true,
mode: 'xy',
},
zoom: {
enabled: true,
mode: 'xy', // or 'x' for "drag" version
},
},
};
window.onload = function() {
new Chart(document.getElementById('chart'), config);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/0.6.6/chartjs-plugin-zoom.js"></script>
<html>
<body>
<div style="width:380px;">
<canvas id="chart"></canvas>
</div>
</body>
</html>
If someone is interesting in other libraries, I found one interesting solution on Vicotry website with "brush and zoom" functionality for line charts: https://formidable.com/open-source/victory/guides/brush-and-zoom/.
EDIT: In the "drag" version you will have to use for zoom:
drag: {
borderColor: 'hsl(35, 100%, 60%)',
borderWidth: '3',
backgroundColor: 'hsl(35, 100%, 60%)',
},
Related
I am using v 3.8 of Chart.js library and the below is the code:
function createLineGraph(chartObject,chartId,data,labels,xLabel,yLabel) {
// Create a new Chart.js instance
var ctx = document.getElementById(chartId).getContext('2d');
chartObject = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: data
},
options: {
responsive: true,
scales: {
x: {
ticks:{
display: true,
autoSkip: true,
maxTicksLimit: 10,
},
title: {
display: true,
text: xLabel
},
grid: {
display: false,
text: xLabel
}
},
y: {
beginAtZero: true,
min: 0,
max: 200,
ticks: {
tickSpacing: 50,
autoSkip:true,
},
title: {
display: true,
text: yLabel
},
grid: {
display: false,
}
}
}
}
});
chartObject.update();
}
HTML
<canvas id="chart"></canvas>
Right now it displays like the below:
And Ideally, I am looking something like this:
You can make the visual area of the graph bigger, increasing the size of the Chart with CSS if possible. if that is not possible, you could:
move the legend to the side,
plugins: {
legend: {
position: 'right',
}
},
Make the labels for the x-Axis shorter, since it is a datetime the best way would be setting the x-axis to type time (but you would have to add some libraies, checkout the documentation )
Here a demo, how I would do this:
const data = {
labels: ['2023-01-01 00:00:00','2023-01-01 01:00:00','2023-01-01 02:00:00','2023-01-01 03:00:00','2023-01-01 05:00:00'],
datasets: [{
label: 'Dataset 1',
borderColor: '#36A2EB',
backgroundColor: '#36A2EB',
data: [50, 150, 180, 160, 10],
},{
label: 'Dataset 2',
borderColor: '#FF6384',
backgroundColor: '#FF6384',
data: [20, 110, 80, 190, 20],
}
,{
label: 'Dataset 3',
borderColor: '#4BC0C0',
backgroundColor: '#4BC0C0',
data: [190, 190, 160, 150, 130],
}
,{
label: 'Dataset 4',
borderColor: '#FF9F40',
backgroundColor: '#FF9F40',
data: [100, 100, 150, 100, 100],
}],
};
const config = {
type: 'line',
data: data,
options: {
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right',
},
},
scales: {
x: {
type: 'time',
}
}
}
};
const config1 = {
type: 'line',
data: data,
options: {
maintainAspectRatio: false,
}
};
new Chart(
document.getElementById('chart1'),
config1
);
new Chart(
document.getElementById('chart'),
config
);
new Chart(
document.getElementById('chart2'),
config1
);
<script src="//cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.js"></script>
<script src="//cdn.jsdelivr.net/npm/moment#^2"></script>
<script src="//cdn.jsdelivr.net/npm/chartjs-adapter-moment#^1"></script>
<h2>Before</h2>
<div class="chart" style="height:184px; width:350px;">
<canvas id="chart1" ></canvas>
</div>
<h2>After<h2>
<div class="chart" style="height:184px; width:350px;">
<canvas id="chart" ></canvas>
</div>
<h2>Only changing the CSS height<h2>
<div class="chart" style="height:300px; width:350px;">
<canvas id="chart2" ></canvas>
</div>
I haven't worked with chart.js for some time but as far as I can see the height of the two charts is different, so because of that the line gap is so narrow there. Try experimenting with styling so that you can increase the height and I think that the gap will increase as well.
I'm new to chart.js, and I have a question about making x-axis labels position to the top.
This is the result that I expected: x-axis labels are on the top.
And this is my attempt:
const ctx = document.getElementById('weather_chart');
const myChart = new Chart(ctx, {
data: {
datasets: [{
type: 'bar',
label: 'rainfall probability',
data: [10, 20, 30, 40],
}, {
type: 'line',
label: 'temperature',
data: [50, 50, 50, 50],
borderColor: '#EB6E4B',
backgroundColor: '#EB6E4B',
}],
labels: ['now', '9am', '10am', '11am', '12pm'],
},
options: {
plugins: {
legend: {
display: false,
},
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div id="chart">
<canvas id="weather_chart"></canvas>
</div>
If it is possible, would you take your time to write the answer?
Thanks in advance, and if my question is insufficient, I would appreciate it if you could tell me.
You can configure all scale related things like position in this namepsaces: options.scales[scaleId]. For more config options of the scales you can read the documentation: https://www.chartjs.org/docs/master/axes/
const ctx = document.getElementById('weather_chart');
const myChart = new Chart(ctx, {
data: {
datasets: [{
type: 'bar',
label: 'rainfall probability',
data: [10, 20, 30, 40],
}, {
type: 'line',
label: 'temperature',
data: [50, 50, 50, 50],
borderColor: '#EB6E4B',
backgroundColor: '#EB6E4B',
}],
labels: ['now', '9am', '10am', '11am', '12pm'],
},
options: {
scales: {
x: {
position: 'top'
}
},
plugins: {
legend: {
display: false,
},
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div id="chart">
<canvas id="weather_chart"></canvas>
</div>
inside options > scales > xAxes the xAxes is an array, so we can define multiple axis and there configuration like this:
options:{
scales: {
xAxes: [
{
position: 'top',
ticks: {
maxRotation: 90,
minRotation: 80
}
}
]
}
}
Checkout the example here
https://codepen.io/ganeshbkdm/pen/oNeaOwm
I am generating charts with ChartJS v3.3.2. I don't want to show the legends. So I've set legend: { display: false } but the legends are still showing.
How can I fix this ?
here's my options object:
const config = {
type: 'bar',
data,
options: {
legend: {
display: false,
},
tooltips: {
enabled: false,
},
responsive: true,
},
};
As descripbed in the migration docs and the namespace in the legend config page in the docs it states that to configure the legend you need to put it in the plugins part of the config since its an internal plugin.
Migration docs: https://www.chartjs.org/docs/master/getting-started/v3-migration.html#specific-changes
Legend docs: https://www.chartjs.org/docs/master/configuration/legend.html#configuration-options
Working Example:
let config01 = {
type: 'doughnut',
data: {
labels: [
'Part 01',
'Part 02',
'Part 03'
],
datasets: [{
data: [2000, 1000, 600],
backgroundColor: [
'rgb(0, 76, 138)',
'rgb(50, 151, 230)',
'rgb(250, 202, 55)',
],
hoverOffset: 10
}]
},
options: {
plugins: {
legend: {
display: false
},
},
}
};
var ctx = document.getElementById('myChart-01').getContext('2d');
new Chart(ctx, config01);
<div>
<canvas id="myChart-01" width="200px" height="200px"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.3.2/dist/chart.min.js"></script>
</div>
I'm using a chartJS Horizontal Bar to visualize some data & the annotation plugin to add vertical lines in the plot area.
What I want to accomplish: showing annotation values/color-box in the tooltip.
What I've done thus far: I've added in bar charts to get the values in the tooltip. (see images & code below).
Where I'm stuck: I would like to hide/offset aBar 1 & aBar 2; in other words, I don't want these bars to appear at all, but I do want the entries to appear in the tooltip. (please see second image).
Current Output
Desired Output
Code
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: false, // RANGE
datasets: [
{
type: 'horizontalBar',
label: 'Bar 1',
backgroundColor: 'rgba(121,185,29,0.85)',
stack: 'Stack 0',
data: [
16 ],
borderColor: 'white',
borderWidth: 0.5
},
{
type: 'horizontalBar',
label: 'Bar 2',
backgroundColor: 'rgba(246,171,0,0.3125)',
stack: 'Stack 0',
data: [
24 ]
},
{
type: 'horizontalBar',
label: 'Bar 3',
backgroundColor: 'rgba(226,33,27,0.5)',
stack: 'Stack 0',
data: [
80 ]
},
{
type: 'horizontalBar',
label: 'aBar 1',
backgroundColor: '#20C5CB',
stack: 'Stack 1',
data: [
6 ]
},
{
type: 'horizontalBar',
label: 'aBar 2',
backgroundColor: '#7f3391',
stack: 'Stack 2',
data: [
120 ]
},
]
},
options: {
responsive: true,
legend:false,
responsive: true,
maintainAspectRatio: false,
title: false,
tooltips: {
mode: 'index',
intersect: true,
bodyFontSize:10,
titleFontSize:0,
titleMarginBottom:0,
},
plugins: {
labels:false,
},
scales: {
xAxes: [{
ticks: {
max: 124,
min: 0,
stepSize: 10
}
}]
},
annotation: {
annotations: [
{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: 6,
borderColor: '#20C5CB',
borderWidth: 3,
borderDash: [6,3],
label: {
enabled: false,
content: 'Annotation 2',
fontSize: 8,
fontStyle: 'normal',
rotation: 0,
xPadding: 2,
yPadding: 2,
cornerRadius: 1,
}
},
{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: 120,
borderColor: '#7f3391',
borderWidth: 3,
label: {
enabled: false,
content: 'Annotation 1',
fontSize: 8,
fontStyle: 'normal',
rotation: 0,
xPadding: 2,
yPadding: 2,
cornerRadius: 1,
}
}
]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/0.5.7/chartjs-plugin-annotation.min.js"></script>
<canvas id="myChart"></canvas>
Add the hidden tag to datasets of the series you want to hide like this:
type: 'horizontalBar',
label: 'aBar 1',
backgroundColor: '#20C5CB',
stack: 'Stack 1',
hidden: true,
data: [6],
and use a callback to the label tooltip like this:
tooltips: {
mode: 'index',
intersect: true,
bodyFontSize:10,
titleFontSize:0,
titleMarginBottom:0,
callbacks: {
label: function(tooltipItem, data) {
return data.datasets.map(ds => ds.label + ': ' + ds.data[tooltipItem.index])
}
}
},
Found solution here: Chartjs show hidden data on tooltip
I am trying to implement Stacked Horizontal Floating Bars using ChartJS but there is an unusual behaviour that I am facing. Can someone please help why is this happening. The code that I am using is :
<html>
<head>
<title>Floating Bars</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<style>
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
</style>
</head>
<body>
<div>
<canvas id="canvas" height="100"></canvas>
</div>
<script>
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'horizontalBar',
data:{
labels:[1],
datasets:[
{
label:'data',
data:[[-3, 5]],
backgroundColor: 'lightblue'
},
{
label:'data',
data:[[6,8]],
backgroundColor: 'lightblue'
},
{
label:'data',
data:[[10, 11]],
backgroundColor: 'lightblue'
}
]
},
options: {
responsive: true,
scales: {
xAxes: [{
stacked : true,
}],
yAxes: [{
stacked : true,
}]
},
legend: {
position: 'top',
},
title: {
display: true,
text: 'Horizontal Floating Bars'
}
}
});
};
</script>
</body>
</html>
The output of the following code is :
Now if we compare the code with the plotted data we see that the first and the second data set i.e. [-3,5] and [6,8] gets plotted correctly, but the third data set instead of getting plotted at [10,11] gets plotted at [16,17] i.e by adding 10 to the previous 6. Can someone please explain the cause for this?
The reason is that you're stacking the values on the xAxis.
Simply define xAxis as follows and you get the result you're expecting.
xAxes: [{
stacked: false,
}]
window.myBar = new Chart(document.getElementById('canvas'), {
type: 'horizontalBar',
data: {
labels: [1],
datasets: [{
label: 'data 1',
data: [[-3, 5], [6, 8], [10, 11]],
backgroundColor: 'lightblue'
},
{
label: 'data 2',
data: [[6, 8]],
backgroundColor: 'lightblue'
},
{
label: 'data 3',
data: [[10, 11]],
backgroundColor: 'lightblue'
}
]
},
options: {
responsive: true,
scales: {
xAxes: [{
stacked: false,
}],
yAxes: [{
stacked: true,
}]
},
legend: {
position: 'top',
},
title: {
display: true,
text: 'Horizontal Floating Bars'
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas" height="80"></canvas>