代码之家  ›  专栏  ›  技术社区  ›  Penny Liu

在画布上创建线条动画

  •  0
  • Penny Liu  · 技术社区  · 7 年前

    我是油画新手。我想画出pv弦模型和电子流入的方向 <canvas> 标签

    这就是我想要实现的,从以下方向重新绘制线:

    enter image description here

    如何初始设置动画位置,以及是否需要通过 setTimeout ?

    以下是我目前所做的尝试:

    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("2d");
    
    if (canvas.getContext) {
      var ctx = canvas.getContext('2d');
      // drawing code here
    
      /* First Row */
      ctx.fillStyle = "rgb(2,150,224, 1)";
      ctx.fillRect(50, 50, 50, 50);
    
      ctx.fillStyle = "rgb(2,150,224, 1)";
      ctx.fillRect(110, 50, 50, 50);
    
      ctx.fillStyle = "rgb(188,12,50, 1)";
      ctx.fillRect(170, 50, 50, 50);
    
      ctx.fillStyle = "rgb(2,150,224, 1)";
      ctx.fillRect(230, 50, 50, 50);
    
      ctx.fillStyle = "rgb(2,150,224, 1)";
      ctx.fillRect(290, 50, 50, 50);
    
      /* Second Row */
      ctx.fillStyle = "rgb(0,106,160, 1)";
      ctx.fillRect(50, 150, 50, 50);
    
      ctx.fillStyle = "rgb(0,106,160, 1)";
      ctx.fillRect(110, 150, 50, 50);
    
      ctx.fillStyle = "rgb(0,106,160, 1)";
      ctx.fillRect(170, 150, 50, 50);
    
      ctx.fillStyle = "rgb(0,106,160, 1)";
      ctx.fillRect(230, 150, 50, 50);
    
      ctx.fillStyle = "rgb(0,106,160, 1)";
      ctx.fillRect(290, 150, 50, 50);
    
      /* Paths */
      ctx.beginPath();
      ctx.lineWidth = "3";
      ctx.strokeStyle = "rgb(34,177,76, 1)";
      ctx.moveTo(0, 75);
      ctx.lineTo(400, 75);
      ctx.stroke();
    
      ctx.beginPath();
      ctx.lineWidth = "10";
      ctx.strokeStyle = "rgb(34,177,76, 1)";
      ctx.moveTo(400, 75);
      ctx.lineTo(400, 175);
      ctx.stroke();
    
      ctx.beginPath();
      ctx.lineWidth = "3";
      ctx.strokeStyle = "rgb(34,177,76, 1)";
      ctx.moveTo(0, 175);
      ctx.lineTo(400, 175);
      ctx.stroke();
    
    
    } else {
      // canvas-unsupported code here
    }
    /* canvas {
      border: 1px solid #d3d3d3;
    } */
    <canvas id="myCanvas" width="400" height="400">
    Your browser does not support the HTML5 canvas tag.</canvas>

    任何帮助都将不胜感激!

    1 回复  |  直到 7 年前
        1
  •  1
  •   ggorlen Hoàng Huy Khánh    7 年前

    有很多方法可以使之生动化;以下是我的方法(节选;请参阅 JSFiddle 对于完整代码):

    var lerp = (a, b, t) => a + t * (b - a);
    var speed = 0.01;
    var time = 0;
    var visited = [];
    var points = [
      {
        from: { x: 0, y: 75 },
        to: { x: 395, y: 75 }
      },
      {
        from: { x: 395, y: 75 },
        to: { x: 395, y: 175 }
      },
      {
        from: { x: 395, y: 175 },
        to: { x: 0, y: 175 }
      }
    ];
    
    /* Paths */
    ctx.lineWidth = 3;
    ctx.strokeStyle = "rgb(34, 177, 76, 1)";
    
    (function update() {
      if (points.length) {
        visited.push({
            x: lerp(points[0].from.x, points[0].to.x, time),
            y: lerp(points[0].from.y, points[0].to.y, time)
        });
    
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        drawBoxes(ctx);
        ctx.beginPath();
        ctx.moveTo(visited[0].x, visited[0].y)
        visited.forEach(e => ctx.lineTo(e.x, e.y));
        ctx.stroke();
    
        time += speed;
    
        if (time >= 1) {
            time = 0;
            points.shift();
        }
    
        requestAnimationFrame(update);
      }
    })();
    

    其思想是保持所有转折点的数据结构,然后 lerp 沿着这条路,画一条线。使用 easing 如果您喜欢更“现代”的动画,则使用函数而不是LERP;轻松通常更容易实现,并可能导致删除某些代码(例如,无需跟踪起点和时间)。

    最后一个小提示——您的原始代码在画布的右边缘截断了线,所以我冒昧地使用395而不是400作为绘图宽度。

    推荐文章