javascript - 在 Canvas 上平滑地将对象从 A 移动到 B

标签 javascript html animation canvas

我正在尝试使用 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);

流畅的动画

以一种不不稳定的方式在屏幕上动画你的东西意味着执行以下操作:

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

对于动画循环,我会使用 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/

相关文章:

javascript - 如何获取 iframe 的 url?

javascript - 应用 CSS onclick

html - H1 没有任何样式,但是 h2、h3、... h6 是

javascript - 看不到选项并且无法选择

javascript - 在其中也有链接的表行中使用 onClick

java - AngularJS 和 Spring MVC 安全性

javascript - Harmony代理,检测属性是否被访问或调用

c# - 如果集合发生变化,Listview 中的 Xamarin.Forms 动画将停止工作

css - 用 CSS 创意制作 SVG 动画?

几次 setAnimation 调用后 Android View 旋转没有发生