Change maxTicksLimit based on window size - javascript

So I have a dataset with about 300 points and I can display it just fine using chart.js. However, when I change the size of the window, I notice that the ticks get all mushed up together as the canvas resizes with the window.
scales: {
x: {
type: "linear",
grid: {
display: false,
},
ticks: {
autoSkip: true,
maxRotation: 0,
maxTicksLimit: 3, // How do I make bigger windows show more ticks?
// vs Smaller windows show fewer ticks?
stepSize: 15,
callback: function (value) {
return `${value}`;
},
},
},
So this is what I have so far. I looked into the docs and found that maxTicksLimit limits the number of ticks displayed. But I don't know how to make it dynamic based on the window size. I'm sure it's something simple that I'm missing, but I can't seem to find the answer.
Thanks.

Related

Chart.js - mixed chart types (line/bar) on time scale causing offset problems after migration to v3

I'm using chart.js in my project where I'm having a daily-ticked time scale on the X axis and two linear scales on the Y axis. On one linear scale I'm rendering an usual line chart representing a chronological trend while rendering multiple stacked bar charts on the other linear scale, representing average stats for each day. Pre-v3 versions of chart.js were dictating to use a general chart type bar for this to work, and in my case it did even on a time scale. Only workaround I had to use to was to set the bar chart data to 12:00pm to have it centered on the day while also setting the barThickness manually, as it will default to 0 (?) on a time scale otherwise.
Now I've recently updated to v3.2.0 and adjusted my options and datasets according to the migration documentation. Rendering the charts I noticed that the scale ticks were offset by half a day, thus both charts being off. After some research I found out that it was due to the offset option for the scale being enabled as I was using a bar chart.
Manually turning off the offset option is to no avail either though. Besides the time scale not using up another day anymore, the ticks are still off by half a day.
Cutting out the bar chart dataset resets the ticks back to normal. Unfortunately there doesn't seem to be a way to apply the offset only to the bar charts. Does anyone have an idea how to deal with this?
I have now created a Codepen example for this.
scales: {
x: { // time scale
type: 'time',
offset: false,
time: {
unit: 'day',
displayFormats: {
day: 'iii, dd.MM'
}
},
bounds: 'ticks',
grid: {
color: "#444",
zeroLineColor: "#888",
zeroLineWidth: 2
},
title: {
display: true,
text: 'Date'
}
},
yT: { // line chart scale
position: 'right',
beginAtZero: false,
grid: {
color: "#444",
zeroLineColor: "#888",
zeroLineWidth: 2
},
ticks: {
maxTicksLimit: 24,
stepSize: 9000,
callback: (duration) => String(duration / 3600) + 'h'
}
},
yR: { // bar chart scale
position: 'right',
beginAtZero: false,
grid: {
color: "#444",
zeroLineColor: "#888",
zeroLineWidth: 2
},
ticks: {
maxTicksLimit: 48,
stepSize: 10800,
callback: (duration) => String(duration / 3600) + 'h'
},
title: {
display: true,
text: 'Duration'
},
stacked: true
}
}
I opened an issue on GitHub where I was told that I also had to explicitly set the grid.offset option to false, and this fixed it for me.

How do I implement the 'autoskip' feature in chartjs?

Example
I am trying to use the autoSkip feature found here in the chart.js documentation:
https://www.chartjs.org/docs/latest/axes/cartesian/?h=autoskip
The issue I am having is my x-axes labels are overlapping (see above example).
Everything I have read says this autoSkip feature should automatically skip overlapping labels. However, when setting this to both true or false, nothing seems to change in my chart.
<Line
data={this.state.chartData}
options={{
elements: {
point: {
radius: 2
}
},
tooltips: {
mode: 'nearest',
intersect: false
},
scales: {
yAxes: [{
ticks: {
stepSize: 1, //sets the interval that our y axis counts by
beginAtZero: false, //starts our graph at 0 if true
},
gridLines: {
drawOnChartArea: false
}
}],
xAxes: [{
ticks: {
minRotation: 88,
autoskip: true,
autoSkipPadding: 50
},
gridLines: {
drawOnChartArea: false
},
type: 'time',
distribution: 'series',
time: {
unit: 'day',
displayFormats: {
day: 'MMM D',
},
tooltipFormat: 'MMM D h:mm a',
},
},
]
},
responsive: true, //lets us resize our chart
maintainAspectRatio: true, //lets us resize our chart
}
}
/>
In case anyone is wondering, please update to 2.9. Confirmed that the issue is resolved there.
https://github.com/chartjs/Chart.js/issues/6591
I noticed your autoskip is in lower case where in the documentation its in camlcase (ie. autoSkip) - from my experience with Chartjs, I've found that it might make a difference to try and fix that and see if that does the trick
You could try changing
distribution: series
to
distribution: linear
It looks to me like its trying to space the data evenly, despite the fact that you're missing data for 3 days (the weekend maybe?). It really shouldn't break your labels... but I bet the labels know there's enough space for n labels on the graph, but they don't realize that three of the labels are being squished together.
The default distribution is linear, so you could also just remove it. (https://www.chartjs.org/docs/latest/axes/cartesian/time.html#scale-distribution)
For anyone wondering, a chartjs dev has replied to my post here: https://github.com/chartjs/Chart.js/issues/6591
Looks like there are some issues in the current Chart.js version. Should be fixed in 2.9.

Chart.js automatic scaling

I've been testing out chart.js for maybe including it in a project. I just have one smallish issue with it. It doesn't scale some datasets properly. I found somewhat similar questions here in SO, but nothing really that would solve my issue.
So this is what my chart looks like with some datasets:
For some reason, the max values (2.2) look ugly as hell. The reason is, that the dataset has a set of three duplicate values in this case (2.2, 2.2, 2.2). I would like there to be some room on top of this series, so that it would look a bit more reasonable.
How do you properly add "padding" on top the the series line? I would like a solution where I could rely on chart.js to find out the max value, and then maybe update that with some padding on the scale(like x + 10). Issue is, that I cant just hard code the min max values, because I can have over 200 different values that can be selected, and they can vary A LOT in scale.
Here is how I render the chart for now:
return new Chart(context, {
type: 'line',
data: {
labels: labels.data,
datasets: dataSets
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
ticks: {
beginAtZero: false
},
yAxes: [{
ticks: {
beginAtZero: false
},
id: 'A',
type: 'linear',
position: 'left',
}, {
ticks: {
beginAtZero: false
},
display: displayBAxis,
id: 'B',
type: 'linear',
position: 'right',
}]
}
}
});
This may not be the cleanest way but you can play with it as you see fit.
In short, you need to create a function that finds the max value out of all your dataSets arrays and in yAxes.ticks set max to that functions return value.
More details below
Referencing here first:
data:{
labels: labels.data,
datasets: dataSets //talking about this first
}
Create a function that will go through these arrays and get the max of all arrays. I did it using this but you can do it better I'm sure:
function getMax(){
var max = 0;
dataSets.forEach(function(x, i){
max = Math.max(max, Math.max.apply(null, x.data));
});
return max + 2;
}
Then in your return in yAxes you should be able to have:
ticks: {
beginAtZero: false,
max: getMax()
},
You can find the min and max of your dataset, then add/subtract a percentage of the difference (range).
For example, say you use 1% of the range.
[0.1, 0.2, 0.5] gives (1%)x(0.5-0.1)=0.004, so [min,max]=[0.096,0.504].
[1500, 1800, 3500, 3600] gives (1%)x(3600-1500)=21, so [min,max]=[1479,3621].

Chart js Backgroundimage Scaling

Hi i'm quite new to JS and looking for an easy way to show a custom map with my own backgroundimage and several points with x-y-coordinates on it.
At first it worked quite well using the "line"-chart-type of chart.js (v2.5) with disabled showScale()-option and fixed axes-max/min-values.
My problem is that the backgroundimage is not rescaling properly when i change the window-size or show/hide the legend of the chart.
Here is my JS-code for creating the chart:
function initMap() {
scatterChart = new Chart(document.getElementById("scatterChart"), {
responsive: true,
type: 'line',
data: {
/*datasets: [
{
}
]
*/
},
showScale: false,
options: {
scales: {
yAxes: [{
display: false,
ticks: {
max: y_max,
min: 0,
stepSize: 0.1
}
}],
xAxes: [{
display: false,
type: 'linear',
position: 'bottom',
ticks: {
max: x_max,
min: 0,
stepSize: 0.1
}
}]
},
onClick: function (evt) {
var activePoint = scatterChart.getElementAtEvent(evt);
},
legend: {
position: 'right',
labels: {
fontSize: 15
}
},
}
});
}
HTML:
<canvas id="scatterChart" style="width: 1920px; height: 1080px; background-image:url('media/map_background.jpg'); background-size: 100% 100%;"></canvas>
Here are two images showing the effect:
https://1drv.ms/i/s!As59C5Mmd0nahr1zP4rjwI5KobaM3Q
https://1drv.ms/i/s!As59C5Mmd0nahr10KwUCJ4wpvfn4_g
What can i do to get a proper rescaling (points should always be shown on the same position on the map regardless of windowsize or enabled/disabled legend)?
Have you tried using the maintainAspectRatio property and setting it to true? That should hopefully fix your window resize issue.
The only way to fix the legend issue is to use a legend that is external to the canvas because the legend takes up space in the canvas so the chart is squished horizontally (there is no layering concept in a canvas). See this example for how to generate an external legend.
You must use the legendCallback property and the .generateLegend() prototype method.

Possible to hide zero-height bars in a bar chart?

For values of 0, Flot likes to draw a flat line where the bar would be. Is it possible to configure it to draw nothing?
In my application I solved this issue by setting yaxis min to a value greater than 0 and less than the resolution I was working with. Borders visible, flat line hidden.
var options = {
series: {
stack: 0,
lines: { show: false, fill: true, steps: false },
bars: { show: true, barWidth: 0.6 }
},
xaxis: {
mode: "time",
timeformat: "%H:%M"
},
yaxis: {
min: 0.5
},
selection: { mode: "x" },
grid: { hoverable: true }
};
You can set the value to null when it's zero and that will prevent it from showing and allow you to keep borders around other bars.
One solution: set the lineWidth of the bars to 0. This eliminates the border around the bars.
This comes at the cost of the nice visibility for small values Flot has. With borders, even when your chart has large values, 1 and 2 for example are distinct. Without borders, the small numbers can be hard to see, but this effect can be offset by sticking to darker fillColor values for your bars.

Categories

Resources