在画布上平滑地将对象从A移动到B.

Lev*_*evi 1 html javascript animation canvas

我正在尝试使用HTML画布和常规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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

基本上我无法想到的是使while循环更慢(这样它看起来是动画的,而不是仅仅遍历每次迭代并显示结果).

我也无法弄清楚如何防止Arc重复,以便它创建一个永久的线,而不是似乎从a点移动到b点.

Jos*_*osh 8

这里的平滑动画实际上是关于确定循环的每次迭代移动对象的距离.

这里有一点数学,但也不算太糟糕.

速度

在你的情况下速度只是你的粒子在一段时间内沿任何给定方向行进的速度.如果你想让你的粒子在200px4秒的时间内移动,那么速度就会是50px / second.

通过此信息,您可以轻松确定在给定任意长度的时间内移动(动画)粒子的像素数.

pixels = pixelsPerSecond * seconds

很高兴知道要移动多少像素,但不会转换为单独的X和Y坐标.这就是矢量进来的地方.

矢量

数学中的向量是方向和幅度的测量.就我们的目的而言,就像将速度与角度(47°)相结合.

矢量的一个重要特性是它可以分解为单独的X和Y分量(对于二维空间).

因此,如果我们想要以一定角度移动粒子,我们可以像这样计算一个向量:50px / second47°

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);
Run Code Online (Sandbox Code Playgroud)

关于这一点的奇妙之处在于,这些值可以简单地添加到任何X和Y坐标集中,以根据您的速度计算移动它们.

鼠标移动矢量

以这种方式对对象进行建模具有使事物变得美观和数学一致的额外好处.粒子和鼠标之间的距离只是另一个向量.

我们可以使用更多的数学来反算距离和角度.记得那个人毕达哥拉斯?事实证明他非常聪明.

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);
Run Code Online (Sandbox Code Playgroud)

平滑动画

以不生涩的方式在屏幕上动画您的内容意味着执行以下操作:

  1. 尽可能快地运行动画循环
  2. 确定自上次以来经过的时间
  3. 根据已用时间移动每个项目.
  4. 重新绘制屏幕

对于动画循环,我会使用requestAnimationFrameAPI而不是setInterval因为它将具有更好的整体性能.

清除屏幕

此外,当您重新绘制屏幕时,只需在重新绘制项目之前以任何背景颜色在整个事物上绘制一个大矩形.

ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
Run Code Online (Sandbox Code Playgroud)

把它放在一起

这是一个演示所有这些技术的小提琴:https://jsfiddle.net/jwcarroll/2r69j1ok/3/