Thursday, May 11, 2017

Chartjs animate x-axis

Leave a Comment

I want to use a chartjs linechart to visualize my data points. Chartjs seems to animate the graph by default, but it does not animate the values on the x-axis. The x-axis only move in discrete steps.

Is there any way to enable animation on the axis also?

Thanks!

3 Answers

Answers 1

As far as I am aware, ChartJS does not support x-axis animation out-of-the-box. So you'll have to hack it. There are several ways to possibly do this, but the following method seems to work.

When a chart is updated, the following steps occur: 1) The axes are drawn, and then 2) a draw() function is called to draw the data. There are different draw() functions for different chart types, and the function for line charts is Chart.controllers.line.prototype.draw. The draw() functions take one argument, which I will call animationFraction, that indicates how complete the animation is as a fraction. For instance, if an animation is 5% complete, animationFraction will be 0.05, and if an animation is 100% complete (i.e. if the chart is in its final form), animationFraction=1. The draw() function is called at each step of the animation to update the data display.

One hack to animate the x-axis then is to monkey-patch the line chart draw() function to translate the canvas in the horizontal dimension at every draw step:

var hShift = (1-animationFraction)*ctx.canvas.width; 

hShift is the horizontal shift in pixels of the chart. As defined above, the data will sweep in from the right; if you want it to sweep in from the left, you can make the above negative. You then save the canvas context state, transform the canvas using hShift, draw the chart data, and then restore the canvas to its original state so that on the next animation frame the axes will be drawn in the correct spot:

ctx.save(); ctx.setTransform(1, 0, 0, 1, hShift, 0); ctx.oldDraw.call(this, animationFraction); ctx.restore(); 

In the above, this refers to the chart object, and oldDraw refers to the original line chart drawing function that was saved previously:

var oldDraw = Chart.controllers.line.prototype.draw; 

You can additionally setup your new draw() function to read new animation options that allow you to set whether the x-axis and y-axis are animated:

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);     } } 

You can then create a line chart with both axes animated with:

var lineChart = new Chart(ctx, {     type: 'line',     data: data,     options: {          animation: {              duration: 5000,             xAxis: true,             yAxis: true,         }     } }); 

See https://jsfiddle.net/16L8sk2p/ for a demo.

Answers 2

I am no expert in javascript but I found an example for Chartjs that, when inserted a new data point, updates the x-axis via animation as it seems, maybe it helps you: example.

Example source: sitepoint.com

Answers 3

You can loop through the points / bars onAnimationComplete and display the values


Preview

enter image description here


HTML

<canvas id="myChart1" height="300" width="500"></canvas> <canvas id="myChart2" height="300" width="500"></canvas> 

Script

var chartData = {     labels: ["January", "February", "March", "April", "May", "June"],     datasets: [         {             fillColor: "#79D1CF",             strokeColor: "#79D1CF",             data: [60, 80, 81, 56, 55, 40]         }     ] };  var ctx = document.getElementById("myChart1").getContext("2d"); var myLine = new Chart(ctx).Line(chartData, {     showTooltips: false,     onAnimationComplete: function () {          var ctx = this.chart.ctx;         ctx.font = this.scale.font;         ctx.fillStyle = this.scale.textColor         ctx.textAlign = "center";         ctx.textBaseline = "bottom";          this.datasets.forEach(function (dataset) {             dataset.points.forEach(function (points) {                 ctx.fillText(points.value, points.x, points.y - 10);             });         })     } });  var ctx = document.getElementById("myChart2").getContext("2d"); var myBar = new Chart(ctx).Bar(chartData, {     showTooltips: false,     onAnimationComplete: function () {          var ctx = this.chart.ctx;         ctx.font = this.scale.font;         ctx.fillStyle = this.scale.textColor         ctx.textAlign = "center";         ctx.textBaseline = "bottom";          this.datasets.forEach(function (dataset) {             dataset.bars.forEach(function (bar) {                 ctx.fillText(bar.value, bar.x, bar.y - 5);             });         })     } }); 

Fiddle - http://jsfiddle.net/uh9vw0ao/

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment