2016-07-03 109 views
10

我想使用chartjs线条图可视化我的数据点。 Chartjs默认情况下似乎为图形设置了动画效果,但不会为x轴上的值生成动画。 x轴仅以不连续的步骤移动。Chartjs动画x轴

有什么办法可以在轴上启用动画吗?

谢谢!

+0

目前还不清楚是否是问在X维动画的图形数据作为CTG已经低于完成,或者如果你的意思是在x动画标签斧头(这是我把你的问题的意思,是我创造赏金时寻找的),这里没有答案。你能澄清吗? – Aerovistae

回答

4

据我所知,ChartJS不支持x轴动画外的所述盒。所以你必须破解它。有几种方法可能做到这一点,但以下方法似乎工作。

如果要进行动画的数据在X轴

当图表被更新时,发生以下步骤:1)将轴拉伸,然后2)draw()函数被调用,以绘制数据。对于不同的图表类型,有不同的draw()函数,折线图的函数是Chart.controllers.line.prototype.drawdraw()函数带有一个参数,我将调用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(); 

在上面,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是我们的图表对象,这将在下面定义。请注意,ChartJS以略微不同的方式绘制图表,如果在x轴的最小值处存在标签,则需要编写此函数以返回空字符串,如果值== 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=falsemaxRotation=0以确保轴标签以一致的方式绘制。

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

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/

+0

现在我重新阅读这个问题似乎还不清楚,但是当我创建赏金时,我所寻找的就是能够在x轴上对*标签*进行动画制作,而不是x维中的图形数据。我不确定那些原始提问者是指哪一个。您可以通过点击此图上的'更新'来查看我的意思是在这里d3的示例〜http://bl.ocks.org/d3noob/7030f35b72de721622b8 – Aerovistae

+0

@Aerovistae,我明白了。我编辑了我的答案,其中包括一种可能的标签动画制作方法。希望它能为你工作。 – cjg

+0

谢谢,这是完美的! –

1

我不是javascript的专家,但是我发现Chartjs的一个例子,当插入一个新的数据点,通过动画更新x轴,看起来可能会帮助你:example

示例源:sitepoint.com

+1

由于问题表明问题是在折线图上为x轴设置动画。 –