0

I'm trying to draw lines progressively (currently using recursive functions) in a canvas element, and I'm able to successfully draw pairs of lines that are parallel to the x or y axes, this way:

function line(xa, ya, xb, yb) {
    context.beginPath();
    context.moveTo(xa, ya);
    context.lineTo(xb, yb);
    context.stroke();
}

(function drawLine(i){
    line(155, i, 155, i-2);
    line(245, i, 245, i-2);
    if (i > 35) {
        setTimeout(function(){
            drawLine(i-2);
        }, 10);
    }
})(57);

And I get this:

(context.lineWidth is set to 10 and context.lineCap is set to round)

However, I've tried several ways of drawing pairs of lines that aren't strictly horizontal nor vertical but I'm only able to get something like this:

(function drawLine(i){
    line(155, i, 155+(57-i)/2, i-2);
    line(245, i, 245-(57-i)/2, i-2);
    if (i > 35) {
        setTimeout(function(){
            drawLine(i-2);
        }, 10);
    }
})(57);

(changing the value of context.lineWidth or context.lineCap doesn't solve the problem)

Is there a way to draw any kind of line progressively in a canvas element?

Algorythmis
  • 642
  • 1
  • 7
  • 19
  • 1
    Maybe these two links are a good start: - https://stackoverflow.com/questions/25480506/how-to-progressively-draw-line-animation-in-html5-canvas - https://www.html5canvastutorials.com/advanced/html5-canvas-linear-motion-animation/ – Florian Blum Jan 06 '18 at 00:34
  • Is the line going to be straight? – Gustav G Jan 06 '18 at 00:34

3 Answers3

1

In your first version, you draw lines from a point based on the current value of i to a point based on the value of i in the next iteration. But in the second version, the x value of your start point is a constant. Base the start point on i, and the end point on i - 2:

let c = document.querySelector('canvas');
let context = c.getContext('2d');
context.lineWidth = 10;
context.lineCap = 'round';
function line(xa, ya, xb, yb) {
    context.beginPath();
    context.moveTo(xa, ya);
    context.lineTo(xb, yb);
    context.stroke();
}
(function drawLine(i){
    line(155 + (57 - i) / 2, i, 155 + (57 - (i - 2)) / 2, (i - 2));
    line(245 - (57 - i) / 2, i, 245 - (57 - (i - 2)) / 2, (i - 2));
    if (i > 35) {
        setTimeout(function(){
            drawLine(i-2);
        }, 10);
    }
})(57);
<canvas></canvas>
AuxTaco
  • 4,883
  • 1
  • 12
  • 27
0

The easiest way is to use Canvas.js:

const canvas = new Canvas('my-canvas', 200, 200).start();

const line1 = new Canvas.Line({
  from: {
    x: 50,
    y: 70
  },
  to: {
    x: 60,
    y: 30
  },
  lineWidth: 7,
  lineCap: 'round',
  lineLength: 0.1
});

canvas.addElement(line1);

line1.animate('lineLength', {lineLength: 1, duration: 500});

const line2 = new Canvas.Line({
  from: {
    x: 90,
    y: 70
  },
  to: {
    x: 80,
    y: 30
  },
  lineWidth: 7,
  lineCap: 'round',
  lineLength: 0.1
});

canvas.addElement(line2);

line2.animate('lineLength', {lineLength: 1, duration: 500});
<script src="https://gustavgenberg.github.io/handy-front-end/Canvas.js"></script>
Gustav G
  • 459
  • 3
  • 10
0

Using line dash to animate along paths.

A simple way to animate along any path is to use the line dash and line dash offset.

const ctx = canvas.getContext('2d');
ctx.lineWidth = 10;
ctx.lineCap = 'round';


function drawLines(){
   function drawLine(x1, y1, x2, y2){
      ctx.moveTo(x1,y1);
      ctx.lineTo(x2,y2); 
   }
   drawLine(10,10,490,90);
   drawLine(10,190,490,110);
}

var lineLength = 30; // pixels
var distanceBetween = 400;
var lineSpeed = 300;  //pixels per second
ctx.setLineDash([lineLength, distanceBetween]); 

function animateLines(time){
    ctx.lineDashOffset = -time * lineSpeed / 1000;
    ctx.stroke();
}

function loop(time){
    ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
    ctx.beginPath();
    drawLines();
    animateLines(time);
    requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
<canvas id="canvas" width=500 height=200></canvas>
Community
  • 1
  • 1
Blindman67
  • 51,134
  • 11
  • 73
  • 136