【问题标题】:Creating a line animation on canvas在画布上创建线条动画
【发布时间】:2018-12-14 14:15:28
【问题描述】:

我是画布绘图的新手。我想画出光伏串模型和电子流向<canvas>标签。

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

如何初始设置动画位置,是否需要通过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>

任何帮助将不胜感激!

【问题讨论】:

  • 我不清楚您要达到的目标。您想沿着绿色条的路径绘制动画红色箭头吗?
  • @ggorlen 我想在当前ctx.beginPath() 上重绘一条动画路径。
  • 所以你想让三条绿线在开始时看起来没有绘制,然后从左上角开始逐渐绘制它们自己,首先移动到右上角,然后到右下角,然后到左下角。几秒钟?并且没有涉及红色箭头?
  • @ggorlen 是的,这正是我想要的。

标签: javascript animation canvas


【解决方案1】:

有很多方法可以对此进行动画处理;这是我的方法(摘录;见 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 作为绘图宽度。

【讨论】:

    猜你喜欢
    • 2014-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    • 2023-03-19
    • 2020-09-30
    • 2019-11-11
    相关资源
    最近更新 更多