简体   繁体   中英

Rotate Moving Object on Canvas

I'm trying to draw an object based on it's rotate property, but it seems to get confused when the object is moving.

    ctx.save();
    ctx.translate(this.width * 0.5, this.height*0.5);
    ctx.rotate(DegToRad(45));
    ctx.translate(-this.width*0.5,-this.height*0.5);
    ctx.drawImage(this.img, this.spriteOffset, 0, this.width, this.height, this.x, this.y,this.width,this.height);
    ctx.restore();  

The image is drawn rotated 45 degrees, however it now moves in a down-left direction, when the object should only be moving downwards. The movement code is simply handled by incrementing the this.y position. Is there a simpler way to accomplish this?

This is because the whole canvas is being rotated.

What you could try is looking into a framework like Kinetic JS , which creates a sort of SVG API for the canvas.

This site has tons of information on how to use it as well, including rotation , transition, transformation, and pretty much anything else that you might need in working with it.

This should suit your needs rather well.


I think I should provide a low-level, framework-free option as well. Basically, using raw javascript and HTML to pull this off.

Now, as I understood your question, you are trying to make an object (let's assume a black square) move downwards AND have it spin. The only way I can think of to spin it in the canvas without going into path hell is to rotate the entire rendering context. BUT you can also import an image into canvas, for instance, a transparent black diamond (ie that same square rotated). So you'd use a separate canvas to render each step of the rotation for the square.

Essentially something like this:

var canvas2 = document.createElement('canvas'), ctx2 = canvas2.getContext('2d');
//do something with the second canvas
//let's assume the second canvas is the same size as the square
ctx.drawImage(canvas2, squareX, squareY);

See my attempt

As you can see, it is a bit wonky, but it does do essentially what the question asks; it moves the square down, and rotates it. It also plots the result of that rotation below the actual canvas so you can see what's happening under the hood , but the square cuts out due to the "center" being on the top left of the square, and not in the middle.

In the end, it really comes down to how you want to do it.

I was playing around with the API and found it was easier to just keep track of where the object should be. here's an example of a square moving diagonally across the screen and rotating.

<canvas id="canvas" style="width: 100%; height: 100%;">
</canvas>

<script>
  var DELAY = 15; // ms
  var RECT_WIDTH = 100; // px
  var RECT_HEIGHT = 100; // px

  var canvas = document.getElementById('canvas');

  // set intrinsic dimensions
  canvas.width = 1000;
  canvas.height = 1000;
  var ctx = canvas.getContext('2d')
  ctx.fillStyle = 'teal';

  var step = 0
  var vx = 2
  var animate = setInterval(function () {
    ctx.resetTransform()
    ctx.clearRect(0, 0, 1000, 1000);
    ctx.translate(vx * step, vx * step);

    // rotation in place, translate to center of square and back
    ctx.translate(RECT_WIDTH / 2, RECT_HEIGHT / 2);
    ctx.rotate((Math.PI / 180) * step);
    ctx.translate(-(RECT_WIDTH / 2), -(RECT_HEIGHT / 2));

    // Draw the rectangle
    ctx.fillRect(0, 0, RECT_WIDTH, RECT_HEIGHT);
    step = step + 1
  }, DELAY)

  setTimeout(function () {
    clearInterval(animate);
  }, 5000);
</script>

Here, I use vx and keep track of the steps to translate, and calculate what the rotation will be in radians based on the steps a new not caring what the previous state was . Make sure you rotate across the center of where you're square will be as well.

Use ctx.translate to set the object's position before applying the rotation. This should fix the problem.

ctx.save();
ctx.translate(this.x, this.y);

ctx.translate(this.width * 0.5, this.height*0.5);
ctx.rotate(DegToRad(45));
ctx.translate(-this.width*0.5,-this.height*0.5);

ctx.drawImage(this.img, this.spriteOffset, 0, this.width, this.height, 0, 0,this.width,this.height);
ctx.restore(); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM