【问题标题】:Moving object from A to B smoothly across canvas在画布上平滑地将对象从 A 移动到 B
【发布时间】:2017-03-21 05:17:44
【问题描述】:

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

基本上我想不出要做的就是让 while 循环变慢(这样它就显得动画了,而不是只经历每次迭代并显示结果)。

我也不知道如何防止 Arc 复制,以便它创建一条永久的线,而不是看起来从 a 点移动到 b 点。

【问题讨论】:

    标签: javascript html animation canvas


    【解决方案1】:

    这里的平滑动画实际上是关于确定每次循环迭代将对象移动多远。

    这里涉及到一点数学,但还不错。

    速度

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

    利用这些信息,您可以轻松确定在给定任意时间长度的情况下要移动(动画)粒子的像素数。

    pixels = pixelsPerSecond * seconds

    很高兴知道要移动多少个像素,但不会转换为单独的 X 和 Y 坐标。这就是向量的用武之地。

    向量

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

    向量的一大特点是它可以分解成单独的 X 和 Y 分量(对于二维空间)。

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

    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 坐标集,以根据您的速度计算移动它们。

    鼠标移动向量

    以这种方式为您的对象建模还有一个额外的好处,那就是使事物变得美观且在数学上保持一致。你的粒子和鼠标之间的距离只是另一个向量。

    我们可以使用更多的数学来计算距离和角度。还记得毕达哥拉斯那个家伙吗?原来他很聪明。

    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);
    

    把它们放在一起

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

    【讨论】:

    • 感谢您的回复和精彩的解释,这对我有很大帮助并改变了我对这种“动画”的看法。非常感谢:)
    • @Levi - 使用向量的好处在于它们都可以独立地应用于您的粒子以创建更复杂的行为。如果您想将环境 wind 应用于您的对象,那只是另一个向量。重力?是的,只是另一个向量。
    猜你喜欢
    • 1970-01-01
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    • 2018-09-05
    • 1970-01-01
    相关资源
    最近更新 更多