admin管理员组

文章数量:1303412

I am trying to move an object smoothly from point A to point B using HTML canvas and regular javascript.

Point A is a set of coordinates

Point B is in the case the cursor location.

I made a jsfiddle of what I have so far: /

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

Essentially what I can't figure out to do is to make the while loop slower (so that it appears animated in stead of just going through every iteration and showing the result).

I also can't figure out how to prevent the Arc from duplicating so that it creates a line that is permanent, instead of appearing to move from point a to point b.

I am trying to move an object smoothly from point A to point B using HTML canvas and regular javascript.

Point A is a set of coordinates

Point B is in the case the cursor location.

I made a jsfiddle of what I have so far: https://jsfiddle/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);
        }
    }

Essentially what I can't figure out to do is to make the while loop slower (so that it appears animated in stead of just going through every iteration and showing the result).

I also can't figure out how to prevent the Arc from duplicating so that it creates a line that is permanent, instead of appearing to move from point a to point b.

Share Improve this question asked Nov 7, 2016 at 18:46 LeviLevi 1052 silver badges9 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 10

Smooth animation here is really about determining how far to move your object for each iteration of the loop.

There is a little math involved here, but it's not too bad.

Velocity

Velocity in your case is just the speed at which your particles travel in any given direction over a period of time. If you want your particle to travel 200px over the course of 4 seconds, then the velocity would be 50px / second.

With this information, you can easily determine how many pixels to move (animate) a particle given some arbitrary length of time.

pixels = pixelsPerSecond * seconds

This is great to know how many pixels to move, but doesn't translate into individual X and Y coordinates. That's where vectors e in.

Vectors

A vector in mathematics is a measurement of both direction and magnitude. For our purposes, it's like bining our velocity with an angle (47°).

One of the great properties of vectors is it can be broken down into it's individual X and Y ponents (for 2-Dimensional space).

So if we wanted to move our particle at 50px / second at a 47° angle, we could calculate a vector for that like so:

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

The wonderful thing about this is that these values can simply be added to any set of X and Y coordinates to move them based on your velocity calculation.

Mouse Move Vector

Modeling your objects in this way has the added benefit of making things nice and mathematically consistent. The distance between your particle and the mouse is just another vector.

We can back calculate both the distance and angle using a little bit more math. Remember that guy Pythagoras? Turns out he was pretty smart.

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

Smoothly Animating

Animating your stuff around the screen in a way that isn't jerky means doing the following:

  1. Run your animation loop as fast as possible
  2. Determine how much time has passed since last time
  3. Move each item based on elapsed time.
  4. Re-paint the screen

For the animation loop, I would use the requestAnimationFrame API instead of setInterval as it will have better overall performance.

Clearing The Screen

Also when you re-paint the screen, just draw a big rectangle over the entire thing in whatever background color you want before re-drawing your items.

ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);

Putting It All Together

Here is a Fiddle demonstrating all these techniques: https://jsfiddle/jwcarroll/2r69j1ok/3/

本文标签: javascriptMoving object from A to B smoothly across canvasStack Overflow