2

For a school assignment we have to make a graph in Javascript. The teacher would like to see some animated graphs. So I build a graph about my Tweets in one week, but cannot find how to ease between two y-coordinates.

You can find my project here on jsfiddle, or on this website.

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var form = document.getElementById("form");
var data = [];
var huidigeYpos = [];
var nieuweYpos = [];
var count = [];
var snelheid = 0;

function init(){
    ctx.fillStyle="rgb(255,255,255)";
    ctx.fillRect(0,0,canvas.width,canvas.height);
    ctx.translate(0, 445);

    for(var i = 0; i < 7; i++){
        data[i] = form[i].value*30;
    }

    draw();
}

function draw(){
    ctx.fillStyle="rgb(255,255,255)";
    ctx.fillRect(0,0,canvas.width,-canvas.height);
    ctx.beginPath();    
    ctx.moveTo(0,0);
    for(var i = 0; i <= 750; i += 125){
        ctx.lineTo(i,-data[i/125]);
        huidigeYpos.push((data[i/125]));
    }
    if(huidigeYpos.length > 7){
        huidigeYpos.splice(0, 7);
    }
    ctx.lineTo(750,0);
    ctx.closePath();
    ctx.fillStyle="#0084FF";    
    ctx.fill();
}

function invullen(){
    for(var i = 0; i < 7; i++){
        data[i] = form[i].value*30;
    }
    draw();
}

function drawRandomGraph(){ 

    for(var i = 0; i < 7; i++){
        form[i].value = Math.round(Math.random()*10);
        nieuweYpos.push(form[i].value*30);
    }
    if(nieuweYpos.length > 7){
        nieuweYpos.splice(0, 7);
    }
    invullen();
}

init();

Thanks in advance!

alphamikevictor
  • 595
  • 7
  • 17
Jonas Leupe
  • 31
  • 1
  • 3

1 Answers1

13

You can use interpolation in combination with a easing-function. Standard interpolation between two points, aka lerping, is simple enough:

p = p1 + (p2 - p1) * t

where t is in the range [0, 1]

By injecting a easing-function for t, which also is in the [0, 1] range, you can ease the transition:

...
y = y1 + (y2 - y1) * easeInOut(t);
...

function easeInOut(t) {return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1}

There are several variations of easing functions, the above is cubic. You can find more here as well as the popular Penner versions.

For your case you would just update y2 with the new target value as use the old y2 as y1, then lerp/ease between them for each x point using the same t value.

The demo below shows how to use these, integrate as you want.

Example

var ctx = document.querySelector("canvas").getContext("2d"),
    y1 = 10, y2 = 140,                   // source and destination positions
    current = 0, max = 50, delta = 1;    // counters for calculating/animating t

(function loop() {

  // calc t
  current += delta;
  var t = current / max;                 // normalize so we get [0, 1]
  if (t <= 0 || t >= 1) delta = -delta;  // to ping-pong the animation for demo
  
  // calc lerp linear
  var yl = lerp(y1, y2, t),              // linear
      ye = lerp(y1, y2, easeInOut(t));   // with easing
  
  // draw some graphics to show (linear : easing)
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  ctx.fillRect(20, yl - 10, 20, 20);
  ctx.fillRect(50, ye - 10, 20, 20);
  
  requestAnimationFrame(loop);
})();

function lerp(p1, p2, t) {
  return p1 + (p2 - p1) * t
}

function easeInOut(t) {
  return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1
}
<canvas></canvas>