我想使用chartjs折线图来可视化我的数据点。Chartjs似乎默认情况下会为图形添加动画效果,但它不会对x轴上的值进行动画处理。 x轴只会以离散步长移动。
是否有办法在轴上也启用动画效果?
谢谢!
我想使用chartjs折线图来可视化我的数据点。Chartjs似乎默认情况下会为图形添加动画效果,但它不会对x轴上的值进行动画处理。 x轴只会以离散步长移动。
是否有办法在轴上也启用动画效果?
谢谢!
draw()
函数来绘制数据。不同类型的图表有不同的draw()
函数,线性图表的函数为Chart.controllers.line.prototype.draw
。 draw()
函数接受一个参数(我将其称为animationFraction
),该参数表示动画完成的百分比。例如,如果动画完成了5%,animationFraction
将为0.05,如果动画完成了100%(即图表处于最终形式),则animationFraction=1
。每个动画步骤都会调用draw()
函数以更新数据显示。draw()
函数实现水平方向上的画布平移。var hShift = (1-animationFraction)*ctx.canvas.width;
hShift
是图表的水平像素偏移量。如上所述,数据将从右侧滑入;如果要从左侧滑入,则可以将上述值设为负。然后保存画布上下文状态,使用hShift
转换画布,绘制图表数据,然后将画布恢复到其原始状态,以便在下一个动画帧中轴线将在正确位置绘制:
ctx.save();
ctx.setTransform(1, 0, 0, 1, hShift, 0);
ctx.oldDraw.call(this, animationFraction);
ctx.restore();
this
指的是图表对象,oldDraw
是之前保存的原始线图绘制函数。var oldDraw = Chart.controllers.line.prototype.draw;
您可以进一步设置新的draw()
函数,以读取新的动画选项,从而设置x轴和y轴是否进行动画处理:
var oldDraw = Chart.controllers.line.prototype.draw;
Chart.controllers.line.prototype.draw = function(animationFraction) {
var animationConfig = this.chart.options.animation;
if (animationConfig.xAxis === true) {
var ctx = this.chart.chart.ctx;
var hShift = (1-animationFraction)*ctx.canvas.width;
ctx.save();
ctx.setTransform(1, 0, 0, 1, hShift,0);
if (animationConfig.yAxis === true) {
oldDraw.call(this, animationFraction);
} else {
oldDraw.call(this, 1);
}
ctx.restore();
} else if (animationConfig.yAxis === true) {
oldDraw.call(this, animationFraction);
} else {
oldDraw.call(this, 1);
}
}
您可以使用以下代码创建同时拥有动画效果的两个轴线的折线图:
var lineChart = new Chart(ctx, {
type: 'line',
data: data,
options: {
animation: {
duration: 5000,
xAxis: true,
yAxis: true,
}
}
});
var DATA_POINT_NUM = 58;
var data = {
labels: [],
datasets: [
{
data: [],
},
]
}
for (var i=0; i<DATA_POINT_NUM; i++) {
data.datasets[0].data.push({ x: i,
y: Math.random()*10
});
data.labels.push(String.fromCharCode(65+i));
}
接下来,您需要编写一个函数,将数据点的分配x值和数据点标签(即图表x轴上的类别)之间进行转换:
function getXAxisLabel(value) {
try {
var xMin = lineChart.options.scales.xAxes[0].ticks.min;
} catch(e) {
var xMin = undefined;
}
if (xMin === value) {
return '';
} else {
return data.labels[value];
}
}
其中 lineChart 是我们的 Chart 对象,稍后会进行定义。请注意,如果 x 轴最小值处有标签,ChartJS 会稍微不同地绘制图表,因此您需要编写此函数以在 value==x 轴最小值时返回空字符串。然后,您可以定义 Chart 对象:
var lineChart = new Chart(ctx, {
type: 'line',
data: data,
options: {
animation: false,
scales: {
xAxes: [{
type: 'linear',
position: 'bottom',
ticks: {
min: 0,
max: 10,
callback: getXAxisLabel, // function(value) { return data.labels[value]; },
autoSkip: false,
maxRotation: 0,
},
}]
}
}
});
var xMin = 0; // Starting minimum value for the x-axis
var xLength = 10; // Length of the x-axis
var animationDuration = 5000; // Duration of animation in ms
// Calculate animation properties
var framesPerSec = 100;
var frameTime = 1000/framesPerSec;
var xStep = (DATA_POINT_NUM-xMin+xLength)/(animationDuration/1000*framesPerSec);
function nextFrame() {
var xMax = xMin+xLength;
if (xMax < DATA_POINT_NUM-1) {
if (xMax+xStep > DATA_POINT_NUM-1) {
xMax = DATA_POINT_NUM-1;
xMin = xMax-xLength;
}
lineChart.options.scales.xAxes[0].ticks.min = xMin;
lineChart.options.scales.xAxes[0].ticks.max = xMax;
lineChart.update();
setTimeout(nextFrame, frameTime);
xMin += 0.1;
}
}
nextFrame();
removeData()
和addData()
函数。 - Dakkaron