我正在尝试使用 HTML Canvas 和常规 javascript 将对象从 A 点平滑地移动到 B 点。
A点是一组坐标
B点就是光标所在的位置。
我把我目前拥有的东西做了一个 jsfiddle:https://jsfiddle.net/as9fhmw8/
while(projectile.mouseX > projectile.x && projectile.mouseY < projectile.y)
{
ctx.save();
ctx.beginPath();
ctx.translate(projectile.x, projectile.y);
ctx.arc(0,0,5,0,2*Math.PI);
ctx.fillStyle = "blue";
ctx.fill();
ctx.stroke();
ctx.restore();
if(projectile.mouseX > projectile.x && projectile.mouseY < projectile.y)
{
var stepsize = (projectile.mouseX - projectile.x) / (projectile.y - projectile.mouseY);
projectile.x += (stepsize + 1);
}
if(projectile.mouseY < projectile.y)
{
var stepsize = (projectile.y - projectile.mouseY) / (projectile.mouseX - projectile.x);
projectile.y -= (stepsize + 1);
}
}
基本上我想不通的是让 while 循环变慢(这样它看起来像动画而不是仅仅经历每一次迭代并显示结果)。
我也不知道如何防止 Arc 重复,从而创建一条永久线,而不是看起来从 a 点移动到 b 点。
最佳答案
此处的平滑动画实际上是关于确定每次循环迭代将对象移动多远。
这里涉及到一点数学,但还算不错。
速度
在您的情况下,速度就是您的粒子在一段时间内沿任何给定方向行进的速度。如果您希望粒子在 4 秒内移动 200px
,则速度将为 50px/second
。
利用此信息,您可以轻松确定在给定任意时间长度的情况下移动(动画)粒子的像素数。
像素 = pixelsPerSecond * 秒
很高兴知道要移动多少像素,但不会转换为单独的 X 和 Y 坐标。这就是向量的用武之地。
向量
数学中的矢量是方向和大小的度量。就我们的目的而言,这就像将我们的速度与 Angular (47°) 相结合。
向量的一个重要特性是它可以分解为单独的 X 和 Y 分量(对于二维空间)。
因此,如果我们想以47°
Angular 以50px/second
的速度移动我们的粒子,我们可以计算一个向量,例如所以:
function Vector(magnitude, angle){
var angleRadians = (angle * Math.PI) / 180;
this.magnitudeX = magnitude * Math.cos(angleRadians);
this.magnitudeY = magnitude * Math.sin(angleRadians);
}
var moveVector = new Vector(50, 47);
这方面的美妙之处在于,这些值可以简单地添加到任何一组 X 和 Y 坐标,以根据您的速度计算移动它们。
鼠标移动矢量
以这种方式为您的对象建模还有一个额外的好处,那就是让事物变得漂亮并且在数学上保持一致。您的粒子和鼠标之间的距离只是另一个矢量。
我们可以使用更多的数学计算距离和 Angular 。还记得毕达哥拉斯那个家伙吗?事实证明他很聪明。
function distanceAndAngleBetweenTwoPoints(x1, y1, x2, y2){
var x = x2 - x1,
y = y2 - y1;
return {
// x^2 + y^2 = r^2
distance: Math.sqrt(x * x + y * y),
// convert from radians to degrees
angle: Math.atan2(y, x) * 180 / Math.PI
}
}
var mouseCoords = getMouseCoords();
var data = distanceAndAngleBetweenTwoPoints(particle.x, particle.y, mouse.x, mouse.y);
//Spread movement out over three seconds
var velocity = data.distance / 3;
var toMouseVector = new Vector(velocity, data.angle);
流畅的动画
以一种不不稳定的方式在屏幕上动画你的东西意味着执行以下操作:
- 尽可能快地运行你的动画循环
- 确定自上次以来经过了多少时间
- 根据经过的时间移动每个项目。
- 重新绘制屏幕
对于动画循环,我会使用 requestAnimationFrame
API 而不是 setInterval
,因为它将具有更好的整体性能。
清屏
此外,当您重新绘制屏幕时,只需在整个对象上以您想要的任何背景颜色绘制一个大矩形,然后再重新绘制您的项目。
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
将它们放在一起
这是一个演示所有这些技术的 fiddle :https://jsfiddle.net/jwcarroll/2r69j1ok/3/
关于javascript - 在 Canvas 上平滑地将对象从 A 移动到 B,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40472364/