I made a line chart using Chart.js version 2.1.3.
JavaScript
x
43
43
1
var canvas = $('#gold_chart').get(0);
2
var ctx = canvas.getContext('2d');
3
var fillPatternGold = ctx.createLinearGradient(0, 0, 0, canvas.height);
4
fillPatternGold.addColorStop(0, '#fdca55');
5
fillPatternGold.addColorStop(1, '#ffffff');
6
7
var goldChart = new Chart(ctx, {
8
type: 'line',
9
animation: false,
10
data: {
11
labels: dates,
12
datasets: [{
13
label: '',
14
data: prices,
15
pointRadius: 0,
16
borderWidth: 1,
17
borderColor: '#a97f35',
18
backgroundColor: fillPatternGold
19
}]
20
},
21
title: {
22
position: 'bottom',
23
text: 'u7F8Eu5143 / u76CEu53F8'
24
},
25
options: {
26
legend: {
27
display: false
28
},
29
tooltips: {
30
callback: function(tooltipItem) {
31
return tooltipItem.yLabel;
32
}
33
},
34
scales: {
35
xAxes: [{
36
ticks: {
37
maxTicksLimit: 8
38
}
39
}]
40
}
41
}
42
});
43
The output is as follow:
As you can see, I limited the maximum count of ticks to 8 via maxTicksLimit
. However, the distribution is not even. How can I make the ticks distribute evenly?
p.s. there are always 289 records in the dataset, and the data is recorded every 5 minutes. Sample values of prices
variable are:
JavaScript
1
6
1
[
2
{"14:10", 1280.3},
3
{"14:15", 1280.25},
4
{"14:20", 1282.85}
5
]
6
I tried different values of maxTicksLimit
, and the results are still not distributed evenly.
Advertisement
Answer
Chart.js uses an integral skipRatio
(to figure out how many labels to skip). With Chart.js v2.1.x, you can write your own plugin to use a fractional skipRatio
Preview
Script
JavaScript
1
91
91
1
Chart.pluginService.register({
2
afterUpdate: function (chart) {
3
var xScale = chart.scales['x-axis-0'];
4
if (xScale.options.ticks.maxTicksLimit) {
5
// store the original maxTicksLimit
6
xScale.options.ticks._maxTicksLimit = xScale.options.ticks.maxTicksLimit;
7
// let chart.js draw the first and last label
8
xScale.options.ticks.maxTicksLimit = (xScale.ticks.length % xScale.options.ticks._maxTicksLimit === 0) ? 1 : 2;
9
10
var originalXScaleDraw = xScale.draw
11
xScale.draw = function () {
12
originalXScaleDraw.apply(this, arguments);
13
14
var xScale = chart.scales['x-axis-0'];
15
if (xScale.options.ticks.maxTicksLimit) {
16
var helpers = Chart.helpers;
17
18
var tickFontColor = helpers.getValueOrDefault(xScale.options.ticks.fontColor, Chart.defaults.global.defaultFontColor);
19
var tickFontSize = helpers.getValueOrDefault(xScale.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
20
var tickFontStyle = helpers.getValueOrDefault(xScale.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
21
var tickFontFamily = helpers.getValueOrDefault(xScale.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
22
var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
23
var tl = xScale.options.gridLines.tickMarkLength;
24
25
var isRotated = xScale.labelRotation !== 0;
26
var yTickStart = xScale.top;
27
var yTickEnd = xScale.top + tl;
28
var chartArea = chart.chartArea;
29
30
// use the saved ticks
31
var maxTicks = xScale.options.ticks._maxTicksLimit - 1;
32
var ticksPerVisibleTick = xScale.ticks.length / maxTicks;
33
34
// chart.js uses an integral skipRatio - this causes all the fractional ticks to be accounted for between the last 2 labels
35
// we use a fractional skipRatio
36
var ticksCovered = 0;
37
helpers.each(xScale.ticks, function (label, index) {
38
if (index < ticksCovered)
39
return;
40
41
ticksCovered += ticksPerVisibleTick;
42
43
// chart.js has already drawn these 2
44
if (index === 0 || index === (xScale.ticks.length - 1))
45
return;
46
47
// copy of chart.js code
48
var xLineValue = this.getPixelForTick(index);
49
var xLabelValue = this.getPixelForTick(index, this.options.gridLines.offsetGridLines);
50
51
if (this.options.gridLines.display) {
52
this.ctx.lineWidth = this.options.gridLines.lineWidth;
53
this.ctx.strokeStyle = this.options.gridLines.color;
54
55
xLineValue += helpers.aliasPixel(this.ctx.lineWidth);
56
57
// Draw the label area
58
this.ctx.beginPath();
59
60
if (this.options.gridLines.drawTicks) {
61
this.ctx.moveTo(xLineValue, yTickStart);
62
this.ctx.lineTo(xLineValue, yTickEnd);
63
}
64
65
// Draw the chart area
66
if (this.options.gridLines.drawOnChartArea) {
67
this.ctx.moveTo(xLineValue, chartArea.top);
68
this.ctx.lineTo(xLineValue, chartArea.bottom);
69
}
70
71
// Need to stroke in the loop because we are potentially changing line widths & colours
72
this.ctx.stroke();
73
}
74
75
if (this.options.ticks.display) {
76
this.ctx.save();
77
this.ctx.translate(xLabelValue + this.options.ticks.labelOffset, (isRotated) ? this.top + 12 : this.options.position === "top" ? this.bottom - tl : this.top + tl);
78
this.ctx.rotate(helpers.toRadians(this.labelRotation) * -1);
79
this.ctx.font = tickLabelFont;
80
this.ctx.textAlign = (isRotated) ? "right" : "center";
81
this.ctx.textBaseline = (isRotated) ? "middle" : this.options.position === "top" ? "bottom" : "top";
82
this.ctx.fillText(label, 0, 0);
83
this.ctx.restore();
84
}
85
}, xScale);
86
}
87
};
88
}
89
},
90
});
91
Fiddle – http://jsfiddle.net/bh63pe1v/