Yesvinkumar
Yesvinkumar

Reputation: 559

Canvas line drawing animation

I am new learner of animation using HTML5 Canvas. I am struggling to create line drawing animation in a canvas with desired length of a line.

Here is the code

var canvas = document.getElementById("canvas"),
  context = canvas.getContext("2d"),
  width = canvas.width = window.innerWidth,
  height = canvas.height = window.innerHeight;
var x = 200;
var y = 200;
draw();
update();

function draw() {
  context.beginPath();
  context.moveTo(100, 100);
  context.lineTo(x, y);
  context.stroke();
}

function update() {
  context.clearRect(0, 0, width, height);
  x = x + 1;
  y = y + 1;
  draw();
  requestAnimationFrame(update);
}
html,
body {
  margin: 0px;
}

canvas {
  display: block;
}
<canvas id="canvas"></canvas>

The line is growing on Canvas in the above code. But how to achieve that the 200px wide line and animate the movement in x and y direction. And the same animation with multiple lines using for loop and move them in different direction.

Check the reference image ....
enter image description here

Need to move each line in a different direction

Thanks in advance

enter image description here

Find a new reference image which i want to achieve

Upvotes: 1

Views: 3035

Answers (3)

user1693593
user1693593

Reputation:

You need to either use transforms or a bit of trigonometry.

Transforms

For each frame:

  • Reset transforms and translate to center
  • Clear canvas
  • Draw line from center to the right
  • Rotate x angle
  • Repeat from step 2 until all lines are drawn

var ctx = c.getContext("2d");
var centerX = c.width>>1;
var centerY = c.height>>1;
var maxLength = Math.min(centerX, centerY); // use the shortest direction for demo
var currentLength = 0;                      // current length, for animation
var lenStep = 1;                            // "speed" of animation

function render() {
  ctx.setTransform(1,0,0,1, centerX, centerY);
  ctx.clearRect(-centerX, -centerY, c.width, c.height);
  ctx.beginPath();
  
  for(var angle = 0, step = 0.1; angle < Math.PI * 2; angle += step) {
    ctx.moveTo(0, 0);
    ctx.lineTo(currentLength, 0);
    ctx.rotate(step);
  }
  ctx.stroke();  // stroke all at once
}

(function loop() {
  render();
  currentLength += lenStep;
  if (currentLength < maxLength) requestAnimationFrame(loop);
})();
<canvas id=c></canvas>

You can use transformation different ways, but since you're learning I kept it simple in the above code.

Trigonometry

You can also calculate the line angles manually using trigonometry. Also here you can use different approaches, ie. if you want to use delta values, vectors or brute force using the math implicit.

For each frame:

  • Reset transforms and translate to center
  • Clear canvas
  • Calculate angle and direction for each line
  • Draw line

var ctx = c.getContext("2d");
var centerX = c.width>>1;
var centerY = c.height>>1;
var maxLength = Math.min(centerX, centerY); // use the shortest direction for demo
var currentLength = 0;                      // current length, for animation
var lenStep = 1;                            // "speed" of animation

ctx.setTransform(1,0,0,1, centerX, centerY);

function render() {
  ctx.clearRect(-centerX, -centerY, c.width, c.height);
  ctx.beginPath();
  
  for(var angle = 0, step = 0.1; angle < Math.PI * 2; angle += step) {
    ctx.moveTo(0, 0);
    ctx.lineTo(currentLength * Math.cos(angle), currentLength * Math.sin(angle));
  }
  ctx.stroke();  // stroke all at once
}

(function loop() {
  render();
  currentLength += lenStep;
  if (currentLength < maxLength) requestAnimationFrame(loop);
})();
<canvas id=c></canvas>

Bonus animation to play around with (using the same basis as above):

var ctx = c.getContext("2d", {alpha: false});
var centerX = c.width>>1;
var centerY = c.height>>1;

ctx.setTransform(1,0,0,1, centerX, centerY);
ctx.lineWidth = 2;
ctx.strokeStyle = "rgba(0,0,0,0.8)";
ctx.shadowBlur = 16;

function render(time) {
  ctx.globalAlpha=0.77;
  ctx.fillRect(-500, -500, 1000, 1000);
  ctx.globalAlpha=1;
  ctx.beginPath();
  ctx.rotate(0.025);
  ctx.shadowColor = "hsl(" + time*0.1 + ",100%,75%)";
  ctx.shadowBlur = 16;
  
  for(var angle = 0, step = Math.PI / ((time % 200) + 50); angle < Math.PI * 2; angle += step) {
    ctx.moveTo(0, 0);
    var len = 150 + 150 * Math.cos(time*0.0001618*angle*Math.tan(time*0.00025)) * Math.sin(time*0.01);
    ctx.lineTo(len * Math.cos(angle), len * Math.sin(angle));
  }
  ctx.stroke();
  ctx.globalCompositeOperation = "lighter";
  ctx.shadowBlur = 0;
  ctx.drawImage(ctx.canvas, -centerX, -centerY);
  ctx.drawImage(ctx.canvas, -centerX, -centerY);
  ctx.globalCompositeOperation = "source-over";
}

function loop(time) {
  render(time);
  requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
body {margin:0;background:#222}
<canvas id=c width=640 height=640></canvas>

Upvotes: 5

fmacdee
fmacdee

Reputation: 2436

This is one that is a variable length emerging pattern. It has a length array element for each spoke in the wheel that grows at a different rate. You can play with the settings to vary the results:

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var width = canvas.width = window.innerWidth;
var height = canvas.height = window.innerHeight;

var xcenter = width/4;
var ycenter = height/2;
var radius;
var time;

if(width>height) {
    radius = height*0.4;
}
else {
    radius = width*0.4;
}

var start_angle1 = 0;
var start_angle2 = 0;

function toRadians (angle) {
  return angle * (Math.PI / 180);
}
function draw(x1,y1,x2,y2) {
  context.beginPath();
  context.moveTo(x1,y1);
  context.lineTo(x2,y2);
  context.stroke();
}
var radmax=width;
var rads = [];
var radsinc = [];
function drawWheel(xc,yc,start_angle,count,rad) {
    var inc = 360/count;
    var i=0;
    for(var angle=start_angle; angle < start_angle+180; angle +=inc) {
        var x = Math.cos(toRadians(angle)) * rads[rad+i];
        var y = Math.sin(toRadians(angle)) * rads[rad+i];
        draw(xc-x,yc-y,xc+x,yc+y);
        rads[rad+i] += radsinc[i];
        if(rads[rad+i] > radmax) rads[rad+i] = 1;
        i++;
    }
}
function update() {
    var now = new Date().getTime();
    var dt = now - (time || now);
    time = now;
    start_angle1 += (dt/1000) * 10;
    start_angle2 -= (dt/1000) * 10;
    context.clearRect(0,0,width,height);                
    drawWheel(xcenter,ycenter,start_angle1,50,0);     
    drawWheel(xcenter,ycenter,start_angle2,50,50);     
    requestAnimationFrame(update);
}
function init() {
    for(var i=0;i<100;i++) {
        rads[i] = 0;
        radsinc[i] = Math.random() * 10;
    }
}

window.onload = function() {
  init();
  update();
};
html, body {
            margin: 0px;

        }
        canvas {
        width:100%;
        height:200px;
            display: block;
        }
<canvas id="canvas"></canvas>

Upvotes: 1

fmacdee
fmacdee

Reputation: 2436

Here is what I think you are describing...

window.onload = function() {
  var canvas = document.getElementById("canvas"),
    context = canvas.getContext("2d"),
    width = canvas.width = 400,
    height = canvas.height = 220,
    xcenter = 200,
    ycenter = 110,
    radius = 0,
    radiusmax = 100,
    start_angle1 = 0,
    start_angle2 = 0;

  function toRadians(angle) {
    return angle * (Math.PI / 180);
  }

  function draw(x1, y1, x2, y2) {
    context.beginPath();
    context.moveTo(x1, y1);
    context.lineTo(x2, y2);
    context.stroke();
  }

  function drawWheel(xc, yc, start_angle, count, rad) {
    var inc = 360 / count;
    for (var angle = start_angle; angle < start_angle + 180; angle += inc) {
      var x = Math.cos(toRadians(angle)) * rad;
      var y = Math.sin(toRadians(angle)) * rad;
      draw(xc - x, yc - y, xc + x, yc + y);
    }
  }

  function update() {
    start_angle1 += 0.1;
    start_angle2 -= 0.1;
    if(radius<radiusmax) radius++;
    context.clearRect(0, 0, width, height);
    drawWheel(xcenter, ycenter, start_angle1, 40, radius);
    drawWheel(xcenter, ycenter, start_angle2, 40, radius);
    requestAnimationFrame(update);
  }


  update();
};
html,
body {
  margin: 0px;
}

canvas {
  display: block;
}
<canvas id="canvas"></canvas>

Upvotes: 3

Related Questions