The line chart draws additional Y values - chart.js

My values are ranging from 0 to -6000... However, chart.js line chart is drawing the y-axis starting from 0 down up to -25000... The lines therefore almost overlap each other. How can I prevent the y-axis from drawing those excess values so my chart will look bigger.
Config is as follows:
type: 'line',
data: {
labels: ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'],
datasets: [
{
label: 'Sample',
data: [0, -2000, -1500, -1300, -4000, -4800, -4950]
}
]
}

Related

Chart.JS 2 automatic horizontal scroll upon changes on xAxis range not working anymore on Chart.JS 3?

I previously had a scatter graph in Chart.js 2 with the zoom plugin, in which I just had to add data and change the xAxis ticks' min/max to see a nice animated horizontal scroll from my old xAxis range to my new xAxis range.
For some reason I now use Chart.js 3.24 and the zoom plugin 1.1.1. Now the same graph with nearly the same options became quite ugly when animated:
newly added points e.g. at position (X,Y) have an animation going from (X,0) to (X,Y), instead of appearing directly at (X,Y).
when a point from a dataset is at the same position than a line from another dataset, they move at a different speed.
if many points and line are added, sometimes the lines are only shown after the "scrolling animation" ended.
sometimes a point appear at its correct final position before the "scrolling animation" even started.
The only solution I found was to disable animation when updating my graph, then use window.requestAnimationFrame to manually pan the graph myself with the zoom plugin.
Are you aware of a better/simpler recommended way to achieve this ?
Thanks in advance,
My old Chart.js options:
let zoom_options = {
pan: {
enabled: true,
mode: 'x',
rangeMin: { x: 0, y: null},
rangeMax: { x: null, y: null}
},
zoom: {
enabled: true,
drag: false,
mode: 'x',
rangeMin: { x: 0, y: null },
rangeMax: { x: null, y: null },
speed: 0.1
}
};
var ctx = graph.getContext('2d');
this._chartjs = new Chart(ctx, {
type: 'scatter',
data: {
datasets: []
},
options: {
legend: {
//display: false
},
scales: {
xAxes: [{
type: 'linear',
position: 'bottom',
}]
},
plugins: {
zoom: zoom_options // https://github.com/chartjs/chartjs-plugin-zoom
}
}
});
My old line options :
{
label: name,
showLine: false,
fill:false,
spanGaps: false, // I have some NaN values in my datasets.
backgroundColor: color.points_borders,
borderColor: color.line,
borderWidth:5,
pointRadius:5,
pointBorderWidth:2,
pointBorderColor: color.points_borders,
pointBackgroundColor: color.points,
data: []
}
My old update function:
this._chartjs.options.scales.xAxes[0].ticks.min = min;
this._chartjs.options.scales.xAxes[0].ticks.max = length;
this._chartjs.update();

Chart.js v3: how to allow tick label overflow?

I recently upgraded from Chart.js v2 to v3. I am drawing realtime line charts with a time-based x-axis that scrolls right as time passes.
In Chart.js v3, as my x-axis tick labels begins to approach the left edge of the chart, it resizes the graph to fit the full label. As shown in the attached image, this creates an empty gap on the left-side of my chart. In Chart.js v2, it would not resize the graph, and would instead allow the label to overflow the canvas.
My x-axis options are:
{
type: 'time',
axis: 'x',
min: minDate.getTime(),
max: maxDate.getTime()
time: {},
ticks: {
minRotation: 45,
maxRotation: 45,
source: 'labels'
}
};
Is there any option to restore the old behavior and allow the tick labels to overflow?
You could format the first tick to be empty string, using ticks.callback
{
type: 'time',
ticks: {
callback: (value, index) => index === 0 ? '' : value
}
}
example in codepen
I was eventually able to get the desired behavior using the afterFit callback.
{
type: 'time',
afterFit: (scaleInstance) => {
scaleInstance.paddingLeft = 0;
scaleInstance.paddingRight = 0;
}
}

Chart.js - add 1 more tick step to an axis

I am drawing a bubble plot with Chart.js. Sometimes the big bubbles happen to be near the edge of the plot and get truncated. Therefore I've tried to extend the axis limit beyond the data range. The idea is like this
min_x_axis = min_x_data - (max_x_data - min_x_data) * 0.1
max_x_axis = max_x_data + (max_x_data - min_x_data) * 0.1
I do the same for the y axis. In general it works but by extending the axis 10% in each direction, the plot looks ugly. For example, before the ticks of x axis are 1,2,3. After I extend the axis, the ticks are something like this 0.87, 1, 2, 3, 3.12 which makes the plot look kind of ugly due to unevenly spaced gridline. Is there any way I can extend the tick of an axis 1 step in each direction, in this case the ticks will be 0,1,2,3,4.
The range of this plot's data changes dramatically depending on the user input so there is no way to know the tick step beforehand.
You can make use of the grace option like so:
var options = {
type: 'bubble',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [{
x: 0,
y: 3,
r: 4
}, {
x: -3,
y: 1,
r: 38
}, {
x: 16,
y: -4,
r: 18
}],
backgroundColor: 'pink'
}]
},
options: {
scales: {
x: {
grace: 1
},
y: {
grace: 1
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.4.0/chart.js"></script>
</body>
Grace documentation: https://www.chartjs.org/docs/master/axes/cartesian/linear.html#grace

Put tooltip on the middle of two bars

I'm trying to position a custom Chart.js tooltip on the middle of two bars. I made a research on the chart.js docs and different posts but didn't found any different approach than position it using the following snippet (I'm using jquery and doing a toggle class to hide/show the tooltip, please focus on the values I'm using to position the tooltip):
function setupTooltipPosition(config) {
const { tooltipElement, tooltipModel } = config;
const leftOffset = this._chart.canvas.offsetLeft;
const topOffset = this._chart.canvas.offsetTop;
tooltipElement.removeClass(tooltipSelectors.hide);
tooltipElement.css('left', `${tooltipModel.caretX - leftOffset}px`);
tooltipElement.css('top', `${tooltipModel.carteY - topOffset}px`);
}
Using this approach on this particular case I got this result:
[
I also tried using the x and y values of the tooltipModel , however , it doesn't add more sense of how to put the tooltip in the middle. If you tried to add a custom offset to put it on the middle , it works for just this case, but when you add more data it doesn't work. I can have at most 2 datasets, however, the user can add at most 10 data values that means 10 groups of bars.
The question is: There is a way to put the tooltip in the middle of the group of bars (or a single bar in case the user has just 1 dataset) using the values that Chart.js provide for tooltips? Or in other case, do you know any custom approach to have this tooltip centered?
Thanks!!
You don't specify if 'middle' means on the x- and/or y-axis. But since you wrote:
...on the middle of two bars...
I assume you mean on the x-axis. In this case you need to set the options.tooltips.mode property to index. Below is a working example.
let myChart = new Chart(document.getElementById('myChart'), {
type: 'bar',
data: {
labels: ['x', 'y', 'z'],
datasets: [{
label: '1993',
data: [50, 30, 65],
backgroundColor: '#503291'
}, {
label: '1994',
data: [60, 15, 65],
backgroundColor: '#1bbecd'
}]
},
options: {
tooltips: {
mode: 'index'
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
barPercentage: 1
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="myChart"></canvas>
For future questions please provide a MCVE as that makes it much quicker and easier to help you.

Set maxValue on Google Material Bar Chart with Multiple Series

I'm enjoying the great Material chart lib from Google. I'm wondering if there is a way to set a max value on one of the series when using two independent x-axis?
var options7 = {
bars: 'horizontal',
series: {
0: {axis: 'percent', maxValue: 100}, // Bind series 0 to an axis named 'percent'.
1: {axis: 'total'} // Bind series 1 to an axis named 'total'.
},
axes: {
x: {
percent: {label: 'Percent Answered', maxValue: 100}, // Bottom x-axis.
total: {side: 'top', label: 'Total Questions'} // Top x-axis.
}
},
hAxis: {title: 'Questions Answered for the Division', maxValue: 100}
};
data7.sort({column: 2});
chart7 = new google.charts.Bar(document.getElementById("deptQuestionsAnswered"));
chart7.draw(data7, options7);
I've added the maxValue field in all the places I thought it might help one at a time, as well as combined (as in above code), but I can't find any documentation on how to do this for multi-series.
Any thoughts?