当前位置: 首页 > 知识库问答 >
问题:

动画x轴

呼延曜灿
2023-03-14

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

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

谢谢

共有2个答案

宇文航
2023-03-14

我不是javascript的专家,但我找到了一个Chartjs的例子,当插入一个新的数据点时,通过动画更新x轴,也许它对你有帮助:例如。

示例来源:sitepoint。通用域名格式

许庆
2023-03-14

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

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

当图表更新时,会发生以下步骤:1)绘制轴,然后2)调用Draw()函数来绘制数据。不同的图表类型有不同的绘制()函数,折线图的函数是Chart.controllers.line.prototype.draw。函数接受一个参数,我将称之为动画分数,它指示动画作为分数的完整程度。例如,如果一个动画是5%完成,动画分数将是0.05,如果一个动画是100%完成(即,如果图表是在其最终形式),动画分数=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();

在上面,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,
        }
    }
});

见https://jsfiddle.net/16L8sk2p/演示。

如果要设置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));
}

然后,您需要编写一个函数,在数据点的指定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绘制图表的方式会略有不同,所以如果值==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,

                },
            }]
        }
    }
});

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

然后,您可以通过调整x轴ticks.minticks.max值并调用图表的. date()方法来动画图表。为了说明这一点,下面的代码沿着图表的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();

总而言之:https://jsfiddle.net/qLhojncy/

 类似资料:
  • 问题内容: 我正在尝试使用动画制作两个子图。我希望x轴的值随着动画的进行而增加,以使动画的总长度为100,但在任何时候,子图仅向我显示0到24的时间值,然后迭代到100。 这里有一个很好的例子。链接使用并递增x值以滚动方式使用和更新x轴标签。可通过提供的链接中YouTube视频下方的链接获得代码。 我在下面附加了代码,这些代码显示了我尝试复制这些结果的尝试,但x限制似乎采用其最终值,而不是随时间增

  • 动画剪辑 动画剪辑是 Unity 动画系统的核心元素。Unity 不仅支持从外部源导入动画,而且支持在编辑器的动画视图中创建和编辑动画(剪辑)。 从外部源导入动画 从外部源导入的动画剪辑可能包括: 动作捕捉工作室捕捉的人形动画 设计师通过外部 3D 程序(例如 3D Max 或 Maya)创建的动画 第三方的动画集合库(例如来自 Unity Asset store) 导入的单个时间线等分切割为多个

  • 问题内容: 我有一个 实例在其内部,我的动画通过婷。 我想做的是也对X轴上的刻度进行动画处理。我正在相当频繁地更新AxesImage上(及其后)绘制其艺术家的数据,并且每次更新时,我都希望移动一个额外的刻度,以突出显示某些东西的位置。这就是我现在正在做的: 虽然我看到刻度正确更新,但标签却没有。我认为轴bbox不包括轴,这可能吗?如果是这样,我该如何设置动画?我应该从其他地方复制并还原吗? 问题答

  • 动画控制器 动画控制器允许你为一个角色或其他游戏对象安排和维护一组动画。 控制器引用了动画剪辑,并且使用 状态机 来管理各种动画状态和它们之间的转换,可以把状态机认为是一种流程图,或者是一段在 Unity 中用可视化编程语言编写的简单程序。 下面的章节涵盖了 动画系统 Mecanim 提供的控制和序列化动画的主要功能。

  • MATLAB提供两种生成生动活泼动画的方法: 在屏幕上不断擦除再重画对象,每次重画作增量变化。 保存许多不同图,然后作为电影回放。

  • trigger('shrinkOut', [ style({height: '*'}), ])