chart.js remove lower grid from mixed chart - javascript

I have a mixed chart (scatter and line), hence I need 2 xAxis.
There's an extra grid that appears on the bottom of the chart, because that's where the other x axis normally has its labels (I removed them because I don't need them)
I'm trying to get rid of that extra grid, but I can't find how to do it. I've tried to specify the ticks color as white but the grid's still there.
Look at the image, it's that solitary extra grid at the bottom (marked with an horizontal bracket):
This is my code:
const ctx = document.getElementById('myChart');
const labels1 = ['A','R','Fyo','A-MAC','HR','Do','Rs','Dpr','GM','GF','EPK','EPS','Is1','Is2','Is3','FP','INVAR','INVER'];
const lasIs = (ctx, value) => ctx.p0DataIndex > 11 ? value: undefined;
const markedIdxs = [0,5,10,15,20,25,30,35,44, //... and many more];
const markedVals = [0,5,10,15,20,25,30,35,10,// ... and many more];
const data1 = {
labels: labels1,
datasets: [
{
type: 'line',
label: 'Line Dataset',
data: [65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65],
pointRadius: 0,
borderWidth: 1,
borderColor: '#0070C5',
xAxisID: 'x2'
},
{
type: 'line',
label: 'Line Dataset',
data: [50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50],
pointRadius: 0,
borderWidth: 1,
borderColor: '#0070C5',
xAxisID: 'x2'
},
{
type: 'line',
label: 'Line Dataset',
data: [102, 38, 54, 56, 102, 38, 54, 56, 102, 38, 54, 56, 102, 38, 54, 87, 62, 91],
pointStyle: 'circle',
pointRadius: 5,
borderWidth: 2,
borderColor: 'rgba(0, 120, 161,0.5)',
backgroundColor: 'rgba(0, 120, 161,0.5)',
fill: true,
segment: {
borderColor: ctx => lasIs (ctx, 'rgba(0, 168, 172, 0.5'),
backgroundColor: ctx => lasIs (ctx, 'rgba(0, 168, 172, 0.5'),
},
xAxisID: 'x2'
},
{
type: 'scatter',
pointStyle: 'dash',
pointRadius: 6,
borderColor: 'rgba(0, 0, 255,0.2)',
xAxisID: 'x',
data: [{x:1, y:36}, {x:1, y:37}, {x:1, y:39}, {x:1, y:40}, {x:1, y:42}... //and many more]
},
],
};
const multiplos5 = {
id: 'multiplos5',
afterDatasetsDraw(chart, args, options) {
const {ctx} = chart;
ctx.save();
ctx.font = "8px Verdana";
ctx.fillStyle = "#0070C5";
yaSeDibujo=84;
paddLeft = 0;
for (i=0; i < markedIdxs.length; i++) {
if (markedVals[i] < 10)
paddLeft=8;
else
paddLeft=12;
ctx.fillText(markedVals[i], chart.getDatasetMeta(3).data[markedIdxs[i]].x - paddLeft, chart.getDatasetMeta(3).data[markedIdxs[i]].y + 3);
}
}
};
Chart.register(multiplos5);
const myChart = new Chart(ctx, {
data: data1,
options: {
scales: {
x2: { // add extra axes
min: 0,
max: 18,
position: 'bottom',
type: 'category',
ticks: {color: '#0070C5'},
offset: true
},
x: {
min: 1,
max: 18,
ticks: {stepSize: 1, display: false},
offset: true
},
y: {
min: 20,
max: 120,
ticks: {stepSize: 10, color: '#555555', crossAlign: 'start'},
grid:{color:'#f1f1f1', display:true},
},
y2: {
position: 'right',
min: 20,
max: 120,
ticks: {stepSize: 10, color: '#555555'},
grid:{display:false}
},
},
plugins: {
multiplos5,
legend: false,
tooltip: {
displayColors: false,
filter: function (tooltipItem) {
return tooltipItem.datasetIndex == 2;
},
callbacks: {
//title: "el título",
label: function(context) {
let label = labels2[context.dataIndex] + ': ' + context.parsed.y;
return label;
}
}
}
},
},
});
Chart.js version is 3.6.2
Any help/workaround will be really appreciated.
Regards!!
Forgot to mention that the axis I'm talking about is 'x' (xAxisID: 'x')

In your config for the X axis where you set the ticks to display false, if you instead do this in the root of the X scale config it will hide that line so you will get:
scales:{
x: {
display: false,
min: 1,
max: 18,
offset: true
}
}

Related

Chart.js - Multiple JSON data object array [{x: Date, y: count}....] representing each dataset of the chart

I've been trying to implement a Stacked Area Line Chart using Chart.js, which in turn uses multiple datasets as an input for each line graph.
Although I'am able to view the final stacked chart with the associated dataset, I can clearly notice that y-axis data is falsely represented(hover on data-point) w.r.t x-axis for each dataset, which is a major issue.
Major issues are:
x-axis and y-axis mapping issue for 2nd dataset chart onwards
x-axis values (dates) are repetitive and not in order - causes an abrupt display of chart
To be more clear, I need dataset1[ {x: "2030*08-03", y: 8},{}...] to precisely map keys x and y to the respective x-axis and y-axis of chart1, similary, dataset2[ {x: "2030*08-10", y: 8},{}...] mapping to the 2nd chart respectively and so on.
This is the sample codepen implementation replicating the issue.
Also, I'm adding the complete code snippet for a clear understanding.
var ctx = document.getElementById("myChart").getContext("2d");
const colors = {
green: {
fill: 'rgb(0,128,0,0.2)',
stroke: 'green',
},
grey: {
fill: 'rgb(128,128,128, 0.2)',
stroke: 'grey',
},
red: {
fill: 'rgba(255, 0, 0, 0.2)',
stroke: 'red',
}
};
const data1 = [
{x: "2030*08-03", y: 8},
{x: "2030-08-04", y: 1},
{x: "2030-08-08", y: 2},
{x: "2030-08-09", y: 10},
{x: "2030-08-10", y: 2},
{x: "2030-08-12", y: 34} ];
const data2 = [
{x: "2030-08-09", y: 1},
{x: "2030-08-12", y: 12},
{x: "2030-08-13", y: 3},
{x: "2030-08-15", y: 3}
];
const data3 = [
{x: "2030-08-06", y: 1},
{x: "2030-08-09", y: 12},
{x: "2030-08-10", y: 3},
{x: "2030-08-12", y: 3} , ];
const myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [
{
label: "Data1",
fill: true,
backgroundColor: colors.green.fill,
pointBackgroundColor: colors.green.stroke,
borderColor: colors.green.stroke,
pointHighlightStroke: colors.green.stroke,
borderCapStyle: 'butt',
data: data1,
},
{
label: "Data2",
fill: true,
backgroundColor: colors.grey.fill,
pointBackgroundColor: colors.grey.stroke,
borderColor: colors.grey.stroke,
pointHighlightStroke: colors.grey.stroke,
data: data2,
},
{
label: "Data3",
fill: true,
backgroundColor: colors.red.fill,
pointBackgroundColor: colors.red.stroke,
borderColor: colors.red.stroke,
pointHighlightStroke: colors.red.stroke,
data: data3,
}
]
},
options: {
plugins: {
responsive: true,
legend: {
display: true,
position: 'bottom',
},
title: {
display: true,
text: 'Status',
padding: {
top: 20,
bottom: 15
},
font: {
weight: "bold",
size: 25
}
}
},
layout: {
padding: {
left: 20,
right: 0,
top: 0,
bottom: 25
}
},
scales: {
x: {
ticks: {
align: "center"
}
},
y: {
stacked: true,
title: {
display: true,
text: "Count",
font: {
weight: "bold",
size: 20
}
}
},
},
parsing: {
xAxisKey: 'x',
yAxisKey: 'y'
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.min.js"></script>
<canvas id="myChart" width="400" height="200"></canvas>
Any help will be greatly appreciated. Thanks in advance.
This behaviour is happening because chart.js automatically adds the labels if they are not there and doesnt care about ordering, you have 2 ways of fixing it, providing a labels array with all the labels in correct order already:
var ctx = document.getElementById("myChart").getContext("2d");
const colors = {
green: {
fill: 'rgb(0,128,0,0.2)',
stroke: 'green',
},
grey: {
fill: 'rgb(128,128,128, 0.2)',
stroke: 'grey',
},
red: {
fill: 'rgba(255, 0, 0, 0.2)',
stroke: 'red',
}
};
const data1 = [{
x: "2030-08-03",
y: 8
},
{
x: "2030-08-04",
y: 1
},
{
x: "2030-08-08",
y: 2
},
{
x: "2030-08-09",
y: 10
},
{
x: "2030-08-10",
y: 2
},
{
x: "2030-08-12",
y: 34
}
];
const data2 = [{
x: "2030-08-09",
y: 1
},
{
x: "2030-08-12",
y: 12
},
{
x: "2030-08-13",
y: 3
},
{
x: "2030-08-15",
y: 3
}
];
const data3 = [{
x: "2030-08-06",
y: 1
},
{
x: "2030-08-09",
y: 12
},
{
x: "2030-08-10",
y: 3
},
{
x: "2030-08-12",
y: 3
},
];
const myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["2030-08-03", "2030-08-04", "2030-08-06", "2030-08-08", "2030-08-09", "2030-08-10", "2030-08-12", "2030-08-13", "2030-08-15"],
datasets: [{
label: "Data1",
fill: true,
backgroundColor: colors.green.fill,
pointBackgroundColor: colors.green.stroke,
borderColor: colors.green.stroke,
pointHighlightStroke: colors.green.stroke,
borderCapStyle: 'butt',
data: data1,
},
{
label: "Data2",
fill: true,
backgroundColor: colors.grey.fill,
pointBackgroundColor: colors.grey.stroke,
borderColor: colors.grey.stroke,
pointHighlightStroke: colors.grey.stroke,
data: data2,
},
{
label: "Data3",
fill: true,
backgroundColor: colors.red.fill,
pointBackgroundColor: colors.red.stroke,
borderColor: colors.red.stroke,
pointHighlightStroke: colors.red.stroke,
data: data3,
}
]
},
options: {
plugins: {
responsive: true,
legend: {
display: true,
position: 'bottom',
},
title: {
display: true,
text: 'Status',
padding: {
top: 20,
bottom: 15
},
font: {
weight: "bold",
size: 25
}
}
},
layout: {
padding: {
left: 20,
right: 0,
top: 0,
bottom: 25
}
},
scales: {
x: {
ticks: {
align: "center"
}
},
y: {
stacked: true,
title: {
display: true,
text: "Count",
font: {
weight: "bold",
size: 20
}
}
},
},
parsing: {
xAxisKey: 'x',
yAxisKey: 'y'
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.min.js"></script>
<canvas id="myChart" width="400" height="100"></canvas>
Codepen: https://codepen.io/leelenaleee/pen/gOWNXKm?editors=1010
Or you can use a time axis:
var ctx = document.getElementById("myChart").getContext("2d");
const colors = {
green: {
fill: 'rgb(0,128,0,0.2)',
stroke: 'green',
},
grey: {
fill: 'rgb(128,128,128, 0.2)',
stroke: 'grey',
},
red: {
fill: 'rgba(255, 0, 0, 0.2)',
stroke: 'red',
}
};
const data1 = [{
x: "2030-08-03",
y: 8
},
{
x: "2030-08-04",
y: 1
},
{
x: "2030-08-08",
y: 2
},
{
x: "2030-08-09",
y: 10
},
{
x: "2030-08-10",
y: 2
},
{
x: "2030-08-12",
y: 34
}
];
const data2 = [{
x: "2030-08-09",
y: 1
},
{
x: "2030-08-12",
y: 12
},
{
x: "2030-08-13",
y: 3
},
{
x: "2030-08-15",
y: 3
}
];
const data3 = [{
x: "2030-08-06",
y: 1
},
{
x: "2030-08-09",
y: 12
},
{
x: "2030-08-10",
y: 3
},
{
x: "2030-08-12",
y: 3
},
];
const myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: "Data1",
fill: true,
backgroundColor: colors.green.fill,
pointBackgroundColor: colors.green.stroke,
borderColor: colors.green.stroke,
pointHighlightStroke: colors.green.stroke,
borderCapStyle: 'butt',
data: data1,
},
{
label: "Data2",
fill: true,
backgroundColor: colors.grey.fill,
pointBackgroundColor: colors.grey.stroke,
borderColor: colors.grey.stroke,
pointHighlightStroke: colors.grey.stroke,
data: data2,
},
{
label: "Data3",
fill: true,
backgroundColor: colors.red.fill,
pointBackgroundColor: colors.red.stroke,
borderColor: colors.red.stroke,
pointHighlightStroke: colors.red.stroke,
data: data3,
}
]
},
options: {
plugins: {
responsive: true,
legend: {
display: true,
position: 'bottom',
},
title: {
display: true,
text: 'Status',
padding: {
top: 20,
bottom: 15
},
font: {
weight: "bold",
size: 25
}
}
},
layout: {
padding: {
left: 20,
right: 0,
top: 0,
bottom: 25
}
},
scales: {
x: {
type: 'time',
ticks: {
align: "center"
}
},
y: {
stacked: true,
title: {
display: true,
text: "Count",
font: {
weight: "bold",
size: 20
}
}
},
},
parsing: {
xAxisKey: 'x',
yAxisKey: 'y'
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<canvas id="myChart" width="400" height="100"></canvas>
Codepen: https://codepen.io/leelenaleee/pen/GRmbOxN?editors=1010

How can I build a vertical line without going through my dots on my line graph? (charts.js)

Hey guys I have created a line chart that is almost done. The only thing that annoys me is the fact that there is some white space on the right-hand side of the graph. I would like to create a vertical line that does not go through the dots. It should be a smooth line without affecting the dots at the end of the line chart
enter image description here
[<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
<canvas id="mychart2" width="500" height="500"></canvas>
<script>
var canvas = document.getElementById("mychart2");
var ctx = canvas.getContext('2d');
const decimals = 0;var originalLineDraw = Chart.controllers.line.prototype.draw;
Chart.helpers.extend(Chart.controllers.line.prototype, {
draw: function() {
originalLineDraw.apply(this, arguments);
var chart = this.chart;
var ctx = chart.chart.ctx;
var index = chart.config.data.lineAtIndex;
if (index) {
var xaxis = chart.scales\['x-axis-0'\];
var yaxis = chart.scales\['y-axis-0'\];
ctx.save();
ctx.beginPath();
ctx.moveTo(xaxis.getPixelForValue(undefined, index), yaxis.top);
ctx.strokeStyle = '#F6F6F6';
ctx.lineWidth = 1;
ctx.borderDashOffset = 0.0;
ctx.color = 'rgba(0, 0, 0, 1)';
ctx.zeroLineColor = "rgba(0, 0, 0, 0.25)";
ctx.tickMarkLength = 10;
ctx.lineTo(xaxis.getPixelForValue(undefined, index), yaxis.bottom);
ctx.stroke();
ctx.restore();
}
}
});
var config = { //configure the chart
type: 'line',
data: {
labels: \['0', '1', '2', '3', '4', '5', '6', '7', '8', '9+'\],
datasets: \[{
label: "25th Percentile",
showInLegend: false,
backgroundColor: '#c4c1ff',
pointBackgroundColor: "#645bff",
borderColor: '#645bff',
fill: 4,
pointRadius: 0,
pointBorderWidth: 3,
pointHoverRadius: 3,
pointHitRadius: 3, //no fill here
data: \[28, 35, 40, 45, 50, 55, 62, 66, 70, 78\]
}, {
label: "90th Percentile",
backgroundColor: '#c4c1ff',
pointBackgroundColor: "#c4c1ff",
borderColor: '#c4c1ff',
pointHoverBackgroundColor: "#c4c1ff",
pointHoverBorderColor: "#c4c1ff",
borderWidth: 1,
pointRadius: 0,
pointBorderWidth: 3,
pointHoverRadius: 3,
pointHitRadius: 3,
fill: 3,
//no fill here
data: \[40, 65, 63, 64, 72, 79, 83, 87, 100, 108\]
}, {
label: "Median",
backgroundColor: '#0d0e25',
pointBackgroundColor: "#0d0e25",
borderColor: '#0d0e25',
borderWidth: 1,
pointRadius: 2,
pointBorderWidth: 3,
pointHoverRadius: 3,
pointHitRadius: 3,
fill: false, //no fill here
data: \[30, 40, 45, 50, 56, 60, 66, 73, 78, 85\]
},
{
label: "25th - 75th Percentile",
showInLegend: false,
backgroundColor: '#645bff',
pointBackgroundColor: "#645bff",
borderColor: '#645bff',
pointRadius: 0,
lineTension: 0.5,
pointBorderWidth: 3,
pointHoverRadius: 3,
pointHitRadius: 3,
borderCapStyle: 'butt',
borderDash: \[\],
borderDashOffset: 0.1,
borderJoinStyle: 'miter',
fill: 0,
//fill until previous dataset
data: \[35, 50, 51, 55, 63, 69, 73, 80, 85, 94\]
}, {
label: "10th Percentile",
backgroundColor: "#c4c1ff",
pointBackgroundColor: "#c4c1ff",
pointHoverBackgroundColor: "#c4c1ff",
pointHoverBorderColor: "#c4c1ff",
borderColor: "#c4c1ff",
pointStyle: "circle",
borderWidth: 1,
lineWidth: 1,
hoverRadius: 9,
pointRadius: 0,
pointBorderWidth: 3,
pointHoverRadius: 3,
pointHitRadius: 3,
lineTension: 0.3,
fill: '0', //fill until previous dataset
data: \[25, 30, 36, 39, 45, 49, 53, 56, 60, 68\]
}
\], lineAtIndex: 9
},
options: {
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var label = data.datasets\[tooltipItem.datasetIndex\].label || '';
if (label) {
label += ': ';
}
if (label === "25th - 75th Percentile: ") {
label = "75th Percentile: "
}
label += tooltipItem.yLabel
return label;
}
}
},
title: {
display: true,
text: 'Frontend Engineer salaries (753 datapoints)',
fontSize: 20
},
maintainAspectRatio: false,
legend: {
onClick: (e) => e.stopPropagation(),
display: true,
labels: {
filter: function(item,
mychart2) {
return !item.text.includes("25th Percentile" & "10th Percentile")
}
}
},
spanGaps: false,
elements: {
line: {
tension: 0.1
}
},
plugins: {
filler: {
propagate: false
}
},
scales: {
yAxes: \[{
gridLines: {drawOnChartArea:false
},
scaleLabel: {
display: true,
labelString: 'Salary',
fontSize: 20
},
ticks: {
beginAtZero: true,
stepSize: 20,
callback: function(value, index, values) {
return '$' + value.toFixed(decimals)
}
}
}\],
xAxes: \[{
gridLines: {drawOnChartArea:false
},
ticks: {
beginAtZero: true,
stepSize: 20,
},
scaleLabel: {
display: true,
labelString: 'Years of relevant experience',
fontSize: 20
}
}\]
}
}
};
var chart = new Chart(ctx, config)
</script>][1]
how should the vertical line look like?
do you mean the median line?
it would be helpful, if you can show us what kind of vertical line you mean, or at least tell us a function, so we know how the line should look like
EDIT:
You can add a 2nd yAxis to the right side.
Replace this for yAxes:
yAxes: [{
id: 'a',
type: 'linear',
position: 'left',
gridLines: {
drawOnChartArea:false
},
scaleLabel: {
display: true,
labelString: 'Salary',
fontSize: 20
},
ticks: {
beginAtZero: true,
stepSize: 20,
callback: function(value, index, values) {
return '$' + value.toFixed(decimals)
}
}
}, {
id: 'b',
type: 'linear',
position: 'right',
gridLines: {
drawOnChartArea:false
},
scaleLabel: {
display: false
},
ticks: {
display: false,
beginAtZero: true,
stepSize: 1
}
}]

how can i use chart.js to create a chart that has one time series line and one linear line on it at the same time?

I want to draw a reference line in the time series chart. I tried to use two x axis and two y axis so I have like two graphs in one. the one would show time scale line and the other one would show linear line (reference line).
image example of what I want it to look like :
I tried in fiddle but its like the two X axis are connected and not scaling separately:
var data = {
labels: [],
datasets: [{
fill: 'none',
label: 'signal1',
backgroundColor: 'rgba(75,192,192,0.4)',
pointRadius: 5,
pointHoverRadius: 7,
borderColor: 'rgba(75,192,192,1)',
borderWidth: 1,
lineTension: 0,
xAxisID: 'xAxis1',
yAxisID: 'yAxis1',
data: [{
x: '2016-07-17',
y: 44
},
{
x: '2016-07-19',
y: 50
},
{
x: '2016-07-22',
y: 84
},
],
}, {
fill: 'none',
label: 'signal2',
lineTension: 0,
xAxisID: 'xAxis2',
yAxisID: 'yAxis2',
data: [{
x: 0,
y: 55
},
{
x: 1,
y: 55
},
]
}],
};
var option = {
scales: {
yAxes: [{
id: 'yAxis1',
offset: true,
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
display: true,
zeroLineColor: '#979797',
zeroLineWidth: 1,
tickMarkLength: 15,
drawBorder: true,
},
ticks: {
beginAtZero: false,
padding: 5,
fontSize: 12,
fontColor: '#222222',
},
}, {
id: 'yAxis2',
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
display: false,
drawBorder: false,
},
ticks: {
beginAtZero: false,
},
}],
xAxes: [{
id: 'xAxis1',
offset: true,
bounds: 'data',
type: 'time',
distribution: 'linear',
time: {
unit: 'day',
displayFormats: {
day: 'D.M.YYYY',
},
},
gridLines: {
display: true,
color: 'rgba(151, 151, 151, 0.2)',
zeroLineColor: '#979797',
zeroLineWidth: 1,
tickMarkLength: 5,
drawBorder: true,
},
ticks: {
source: 'auto',
autoSkip: true,
autoSkipPadding: 30,
maxRotation: 0,
padding: 2,
fontSize: 12,
fontColor: '#222222',
},
}, {
id: 'xAxis2',
type:"linear",
gridLines: {
display: false,
drawBorder: false,
},
}]
}
};
https://jsfiddle.net/2gyk9v5e/15/
This can be done with the Plugin Core API. The API offers different hooks that may be used for executing custom code. In your case, you can use the afterDraw hook to draw the desired lines directly on the canvas using CanvasRenderingContext2D.
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
ctx.save();
chart.data.datasets[0].refLines.forEach(r => {
var y = yAxis.getPixelForValue(r.y);
ctx.strokeStyle = r.color;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
});
ctx.restore();
}
}],
Above code assumes that the reference lines are defined inside your dataset through the following definition.
refLines: [
{ y: 45, color: '#0be059' },
{ y: 49, color: '#fc3503' }
]
Please take a look at your amended code and see how it works.
new Chart('canvas', {
type: 'line',
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
ctx.save();
chart.data.datasets[0].refLines.forEach(r => {
var y = yAxis.getPixelForValue(r.y);
ctx.strokeStyle = r.color;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
});
ctx.restore();
}
}],
data: {
datasets: [{
fill: false,
label: 'signal1',
backgroundColor: 'rgba(75,192,192,0.4)',
pointRadius: 5,
pointHoverRadius: 7,
borderColor: 'rgba(75,192,192,1)',
borderWidth: 1,
lineTension: 0,
data: [
{ x: '2016-07-14', y: 44 },
{ x: '2016-07-15', y: 52 },
{ x: '2016-07-16', y: 45 },
{ x: '2016-07-17', y: 47 },
{ x: '2016-07-18', y: 35 },
{ x: '2016-07-19', y: 46 },
{ x: '2016-07-20', y: 50 },
{ x: '2016-07-21', y: 44 }
],
refLines: [
{ y: 45, color: '#0be059' },
{ y: 49, color: '#fc3503' }
]
}]
},
options: {
scales: {
yAxes: [{
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
display: false,
drawBorder: false
}
}],
xAxes: [{
offset: true,
bounds: 'data',
type: 'time',
time: {
unit: 'day',
displayFormats: {
day: 'D.M.YYYY',
}
},
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
zeroLineColor: '#979797',
zeroLineWidth: 1,
tickMarkLength: 5,
drawBorder: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js"></script>
<canvas id="canvas" height="80"></canvas>

Displaying line chart for multiple datasets using chart.js

I have to display a line chart with two different datasets in one single chart. After execution of query I got the plan_plan and actual_plan of the following form.
plan_plan = 0: {week: "46", planned_del: "20"}
1: {week: "53", planned_del: "94"}
actual_plan = 0: {week: "8", actual_del: "1"}
javascript part:
function show_Graph()
{
{
var plandata = <?php echo json_encode($plan_plan); ?>;
var actualdata = <?php echo json_encode($actual_plan); ?>;
console.log(plandata);
var labels = [];
var plandel = [];
var actualdel = [];
for (var i in plandata) {
labels.push(plandata[i].week);
plandel.push(plandata[i]);
}
for (var j in actualdata) {
labels.push(actualdata[j].week);
actualdel.push(actualdata[j]);
}
var chartdata = {
labels: labels,
datasets: [
{
label: "Planned Deliverables",
fill: false,
borderColor: "rgba(255, 0, 0, 1)",
pointHoverBackgroundColor: "rgba(255, 0, 0, 1)",
data: plandel
},
{
label: "Actual Deliverables",
fill: false,
backgroundColor: "rgba(0, 255, 0, 0.75)",
borderColor: "rgba(0, 255, 0, 1)",
pointHoverBackgroundColor: "rgba(0, 255, 0, 1)",
pointHoverBorderColor: "rgba(0, 255, 0, 1)",
data: actualdel
}
]
};
var graphTarget = $("#scurve_chart");
var barGraph = new Chart(graphTarget, {
type: 'line',
data: chartdata,
options: {
elements: {
point:{
radius: 1,
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
barValueSpacing: 2,
barPercentage: 0.2
}]
}
}
});
}}
I want to get the week in x axis and then planned_del and actual_del data in y axis which can be shown as line chart. And also should show a single point entry even when there is no data points to be connected.
One way for achieving this, would be to defined data.labels as an array of numbers from 0 to 53.
labels: [0, 1, 2, ... 53]
The data inside the two datasets would then only contain the definitions of individual points.
data: [{ x: 46, y: 20 }, { x: 53, y: 94 }] // plandata
...
data: [{ x: 8, y: 1}] // actualdata
Here's the JavaScript part that illustrates how the desired result can be obtained.
var plandata = [{ week: "46", planned_del: "20" }, { week: "53", planned_del: "94" }];
var actualdata = [{ week: "8", actual_del: "1" }];
new Chart("scurve_chart", {
type: 'line',
data: {
labels: Array.from(new Array(54), (x, i) => i),
datasets: [{
label: "Planned Deliverables",
fill: false,
borderColor: "rgba(255, 0, 0, 1)",
pointHoverBackgroundColor: "rgba(255, 0, 0, 1)",
data: plandata.map(o => ({ x: Number(o.week), y: Number(o.planned_del)}))
},
{
label: "Actual Deliverables",
fill: false,
backgroundColor: "rgba(0, 255, 0, 0.75)",
borderColor: "rgba(0, 255, 0, 1)",
pointHoverBackgroundColor: "rgba(0, 255, 0, 1)",
pointHoverBorderColor: "rgba(0, 255, 0, 1)",
data: actualdata.map(o => ({x: Number(o.week), y: Number(o.actual_del)}))
}
]
},
options: {
tooltips: {
callbacks: {
title: (tooltipItem, data) => "Week " + data.datasets[tooltipItem[0].datasetIndex].data[tooltipItem[0].index].x
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
ticks: {
min: 0,
max: 53,
stepSize: 1
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
<canvas id="scurve_chart" height="90"></canvas>

ChartJS Tooltip Customization

I'm running ChartJS 2.7.something, and have https://codepen.io/anon/pen/YBJWKX this graph. Code below:
var ctx = document.getElementById("chart");
Chart.controllers.LineWithLine = Chart.controllers.line.extend({
draw: function(ease) { Chart.controllers.line.prototype.draw.call(this, ease);
if (this.chart.tooltip._active && this.chart.tooltip._active.length) {
let activePoint = this.chart.tooltip._active[0],
ctx = this.chart.ctx,
x = activePoint.tooltipPosition().x,
topY = this.chart.scales['y-axis-a'].top,
bottomY = this.chart.scales['y-axis-a'].bottom;
// draw line
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 1;
ctx.strokeStyle = 'rgba(52,58,64,1)';
ctx.stroke();
ctx.restore();
}
}
});
var dashboard = new Chart(ctx, {
type: 'bar',
data: {
responsive: true,
labels: ["1", "2", "3", "4", "5", "6", "7"],
datasets: [{
label: 'No Data',
yAxisID: 'y-axis-a',
data: [null,null,4000, null, null, 4000, null],
backgroundColor: 'rgba(229,229,229,1)',
borderWidth: '0',
borderSkipped: 'bottom',
hoverBackgroundColor: 'rgba(229,229,229,1)',
hoverBorderWidth: '0',
showTooltip: false,
},
{
type: 'LineWithLine',
label: 'Dummy 1',
fill: false,
yAxisID: 'y-axis-a',
data: [2586, 2343, 2380, 2439, 3316, 1570, 3439],
borderColor: 'rgba(220,53,69,1)',
backgroundColor: 'rgba(220,53,69,1)',
borderWidth: 3,
borderCapStyle: 'butt',
pointRadius: 2,
pointBorderWidth: 0,
pointHoverRadius: 1,
pointHitRadius: 10,
lineTension: 0.1, // Removes Bezier on Line
},
{
type: 'LineWithLine',
label: 'Dummy 2',
fill: false,
yAxisID: 'y-axis-a',
data: [3466, 1295, 3015, 2351, 3305, 1167, 1350],
borderColor: 'rgba(40, 167, 69,1)',
backgroundColor: 'rgba(40, 167, 69,1)',
borderWidth: 3,
borderCapStyle: 'butt',
pointRadius: 2,
pointBorderWidth: 0,
pointHoverRadius: 1,
pointHitRadius: 10,
lineTension: 0.1, // Removes Bezier on Line
},
{
type: 'LineWithLine',
label: 'Dummy 3',
fill: false,
yAxisID: 'y-axis-b',
data: [1, 8, 17, 6, 12, 4, 7],
borderColor: 'rgba(0, 123, 255,1)',
backgroundColor: 'rgba(0, 123, 255,1)',
borderWidth: 3,
borderCapStyle: 'butt',
pointRadius: 2,
pointBorderWidth: 0,
pointHoverRadius: 1,
pointHitRadius: 10,
lineTension: 0.1, // Removes Bezier on Line
},
]
},
options: {
bezierCurve: false,
maintainAspectRatio:false,
legend: {
labels: {
filter: function(item, dashboard) {
// Logic to remove a particular legend item goes here
return !item.text.includes('No Data');
}
}
},
tooltips: {
mode: 'index',
intersect: false,
//enabled: false,
},
scales: {
yAxes: [{
position: "left",
id: "y-axis-a",
ticks: {
suggestedMax: 3600,
}
},
{
position: "left",
id: "y-axis-b",
max: 25,
display: false,
gridLines: {
display:false
}
}],
},
xAxes: [{ }]
}
});
It's almost perfect for what i need it for, however:
In this particular case I would like to remove the "No Data" grey bars from the tooltip where it's values are NULL.
At the same time, i would also like to remove the tooltip entirely where it's value is not NULL, ie disabled.
I'm using the tooltip in index mode with intersect turned to false so that the black line that is on the graph works, the black line came from this question.
I've tried a range of things from stackoverflow, but I have a feeling that none of the things i've tried have worked because of how the tooltip is set up.
Is it at all possible to do what I need here?
Just change your options parameter a little bit.
tooltips: {
mode: 'index',
intersect: false,
callbacks: {
//returns a empty string if the label is "No Data"
label: function(items, data){
let dataset = data.datasets[items.datasetIndex];
if(dataset.label !== "No Data") {
return `${dataset.label}: ${items.yLabel}`
} else {
return ""
}
},
//only returns something when at least one dataset yLabel is a valid number.
title: function(t, e) {
let shouldDisplay = false;
t.forEach((it) => {
if(!isNaN(it.yLabel)) shouldDisplay = true;
});
if(shouldDisplay) {
return t[0].xLabel;
}
}
}
},
There is probably a better way to optimize this, but I hope it helps

Categories