Javascript 为x轴设置动画

Javascript 为x轴设置动画,javascript,animation,graph,charts,Javascript,Animation,Graph,Charts,我想使用chartjs折线图来可视化我的数据点。默认情况下似乎会设置图形的动画,但不会设置x轴上的值的动画。x轴仅以离散步骤移动 是否有任何方法也可以启用轴上的动画 谢谢 我不是javascript方面的专家,但我发现了一个Chartjs示例,当插入一个新的数据点时,它会通过动画更新x轴,这可能对您有所帮助: 示例来源:据我所知,ChartJS不支持开箱即用的x轴动画。所以你必须破解它。有几种方法可以做到这一点,但以下方法似乎有效 如果要在X轴上设置数据动画 更新图表时,将执行以下步骤:1)绘制

我想使用chartjs折线图来可视化我的数据点。默认情况下似乎会设置图形的动画,但不会设置x轴上的值的动画。x轴仅以离散步骤移动

是否有任何方法也可以启用轴上的动画


谢谢

我不是javascript方面的专家,但我发现了一个Chartjs示例,当插入一个新的数据点时,它会通过动画更新x轴,这可能对您有所帮助:<代码>


示例来源:

据我所知,ChartJS不支持开箱即用的x轴动画。所以你必须破解它。有几种方法可以做到这一点,但以下方法似乎有效

如果要在X轴上设置数据动画

更新图表时,将执行以下步骤:1)绘制轴,然后2)调用
draw()
函数绘制数据。对于不同的图表类型,有不同的
draw()
函数,而折线图的函数是
chart.controllers.line.prototype.draw
draw()
函数使用一个参数,我将其称为
animationFraction
,它指示动画作为分数的完整程度。例如,如果动画完成5%,则
animationFraction
将为0.05;如果动画完成100%(即图表处于最终形式),则
animationFraction=1
。在动画的每个步骤中调用
draw()
函数来更新数据显示

然后,制作x轴动画的一种方法是,在每个绘制步骤中,用猴子修补折线图
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();
在上面,
指的是图表对象,
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,
        }
    }
});
请参见演示

如果要设置X轴限制的动画

如果要设置x轴限制的动画,即移动数据、轴标记和标记标签,则可以使用以下策略。这有点奇怪,所以可能需要一些努力来解决任何给定用例的问题,但我相信它通常会起作用。首先,需要将线图转换为散点图。折线图具有分类的x轴,它们以步进的方式移动,因此不能将轴限制设置为在刻度之间,这是获得动画所需的操作。因此,您需要使用线散点图,因为散点图可以具有任意轴限制。可以通过为每个数据点编号,并将该编号指定给该数据点的x值来完成此操作。例如,要生成随机数据集,可以执行以下操作:

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));
}
其中lineChart是我们的图表对象,将在下面定义。请注意,如果x轴的最小值处有标签,ChartJS绘制图表的方式略有不同,因此如果值==x轴的最小值,则需要编写此函数以返回空字符串。然后可以定义图表对象:

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,

                },
            }]
        }
    }
});
ticks.callback设置为上面的
getXAxisLabel
函数。当ChartJS绘制x轴时,它会将数据点的x值传递给回调函数,然后使用结果字符串作为x轴上的值。用这种方法,我们可以画一个像折线图一样的散点图。我还设置了
autoSkip=false
maxRotation=0
,以确保以一致的方式绘制轴标签

然后,可以通过调整x轴
ticks.min
ticks.max
值并调用图表的
.update()
方法来设置图表的动画。为了说明这一点,下面的代码沿着图表的x轴扫描,一次显示十个数据点

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();
var xMin=0;//x轴的起始最小值
变量x长度=10;//x轴的长度
var animationDuration=5000;//动画的持续时间(毫秒)
//计算动画特性
var framesPerSec=100;
var frameTime=1000/framesPerSec;
var xStep=(数据点数xMin+xLength)/(动画持续时间/1000*framesPerSec);
函数nextFrame(){
var xMax=xMin+xLength;
if(xMaxDATA_POINT_NUM-1){
xMax=数据点数量-1;
xMin=xMax x长度;
}
lineChart.options.scales.xAxes[0].ticks.min=xMin;
lineChart.options.scales.xAxes[0].ticks.max=xMax;
lineChart.update();
设置超时(下一帧,帧时间);
xMin+=0.1;
}
}
nextFrame();

总而言之:

正如问题所述,问题是在折线图上设置x轴的动画。这个答案现在已经过时了。Chart.js不再具有函数
removeData()
addData()
。不清楚您是在询问是否要像ctg下面所做的那样在X维中设置图形数据的动画,还是要在X轴上设置标签的动画(这就是我所理解的你的问题的意思,也是我在创建悬赏时所寻找的),这里没有答案。你能澄清一下吗?现在我重新阅读了这个问题,似乎不清楚,但当我创建悬赏时,我所寻找的是使l动画化的能力
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();