我是画布绘制中的新手。我想将PV串模型和电子流向绘制到<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>
任何帮助将不胜感激!
答案 0 :(得分: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作为绘图宽度。