在画布上创建线条动画

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在画布上创建线条动画相关的知识,希望对你有一定的参考价值。

我是帆布画的新手。我想绘制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>

任何帮助,将不胜感激!

答案

有很多方法可以动画这个;这是我的方法(摘录;请参阅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作为绘图宽度。

以上是关于在画布上创建线条动画的主要内容,如果未能解决你的问题,请参考以下文章

如何在html5画布中逐步绘制线条动画

如何在画布上为路径设置动画 - android

在画布中使用形状制作动画线条

使用带有actionscript 3 Flash cs6的矩形或线条创建2D重复模式

为啥我的 HTML5 画布边缘的线条变得不那么不透明?

实现多彩线条摆出心形