Search code examples
javascripthtml5-canvas

How to rotate a triangle in the direction it is moving?


I have some triangles on canvas and they are randomly moving around the canvas according to given velocity. It is similar to this exercise but triangles instead of circles.

draw(){
    ctx.fillStyle="white";
    const angle = Math.atan2(this.velY,this.velX);
    
    ctx.save();
    ctx.translate(this.x,this.y);
    ctx.rotate(angle);
    ctx.restore();
    
    ctx.beginPath();
    ctx.moveTo(this.x,this.y);
    ctx.lineTo(this.x+10,this.y+10);
    ctx.lineTo(this.x-10,this.y+10);
    ctx.fill();
}

I tried this and it's having no effect whatsoever

here's how I am using the function

while(boids.length < 250){
    boid = new Boid(
        random(10,canvas.width-10),
        random(10,canvas.height-10),
        random(-5,5),
        random(-5,5)
    )
    boids.push(boid);
}

function animate(){
    ctx.fillStyle = "rgb(17 17 17)";
    ctx.fillRect(0,0,canvas.width,canvas.height);

    for(const boid of boids){
        boid.draw();
    }

    requestAnimationFrame(animate);
}

boid is a class with members, x,y,velX,velY.


Solution

  • You could try drawing triangles without using rotate or translate...

    Just a bit of trigonometry math:

    const canvas = document.getElementById('c');
    const ctx = canvas.getContext('2d');
    
    function drawTriangle(center, size, angle, color) {
      ctx.beginPath();
      for (let j = 0; j < 3; j++) {
        a = angle * Math.PI / 180
        x = center.x + size * Math.sin(a)
        y = center.y + size * Math.cos(a)
        ctx.lineTo(x, y);
        angle += 120
      }
      ctx.fillStyle = color;
      ctx.fill();
    }
    
    colors = ["cyan", "blue", "red"]
    for (let i = 6; i > 0; i--) {
      drawTriangle({ x: i * 30, y: 50 }, i*8, i*19, colors[i % 3])
    }
    <canvas id="c" width=300 height=120></canvas>

    On this case I'm using equilateral triangles, but you can use any others once you play around with the math, if it confuses you might want to start here:
    https://study.com/skill/learn/how-to-inscribe-an-equilateral-triangle-in-a-circle-explanation.html


    If you insist on using rotate and translate, here is an example:

    const canvas = document.getElementById('c');
    const ctx = canvas.getContext('2d');
    
    function draw(x, y, velY, velX) {
      const angle = Math.atan2(velY, velX);
    
      ctx.translate(x, y);
      ctx.rotate(angle);
    
      ctx.beginPath();
      ctx.moveTo(0, 0);
      ctx.lineTo(10, 10);
      ctx.lineTo(-10, 10);
      ctx.fill();
    
      ctx.rotate(-angle);
      ctx.translate(-x, -y);
    }
    
    
    draw(20, 10, 10, 10)
    draw(40, 10, 30, 10)
    draw(60, 10, 10, 30)
    draw(80, 10, 0, 180)
    <canvas id="c" width=300 height=120></canvas>

    My approach here is to translate and rotate then draw our triangle right at that position then undo the rotation and translate to go back to the starting position, you can see that I'm drawing four triangles with different angles and they are spaced at an increment of 20 on the X axis.