最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can i move rotated canvas image whitout disorientation? - Stack Overflow

programmeradmin3浏览0评论

I have an image loaded into the canvas. I can't (drag) move the image properly, after it is rotated. Actually, it moves but it moves based on the image's coordinate plane. So moving a 90 degree rotated image to the right, moves down and not to the right as expected. What could be a good way to solve this problem?

This is my draw function:

function draw(){
    var im_width = parseInt( imageObj.width + resizeAmount );
    var im_height = parseInt( imageObj.height + resizeAmount );
    var rotationAmount = rotationVal - prevRotation;
    prevRotation = rotationVal;

    context.clearRect( 0, 0, canvas.width, canvas.height );
    context.translate( canvas.width/2, canvas.height/2 );
    context.rotate( rotationAmount * Math.PI / 180 );
    context.translate( -canvas.width/2, -canvas.height/2 );
    context.drawImage( imageObj, moveXAmount, moveYAmount, im_width, im_height );     
} 

Here is the jsdiddle where you can simulate it and see what I mean.

PS: You can rotate the image with the slider on the left. The bottom slider is for zooming. Please re-run the fiddle if the image does not appear in the first load.

I have an image loaded into the canvas. I can't (drag) move the image properly, after it is rotated. Actually, it moves but it moves based on the image's coordinate plane. So moving a 90 degree rotated image to the right, moves down and not to the right as expected. What could be a good way to solve this problem?

This is my draw function:

function draw(){
    var im_width = parseInt( imageObj.width + resizeAmount );
    var im_height = parseInt( imageObj.height + resizeAmount );
    var rotationAmount = rotationVal - prevRotation;
    prevRotation = rotationVal;

    context.clearRect( 0, 0, canvas.width, canvas.height );
    context.translate( canvas.width/2, canvas.height/2 );
    context.rotate( rotationAmount * Math.PI / 180 );
    context.translate( -canvas.width/2, -canvas.height/2 );
    context.drawImage( imageObj, moveXAmount, moveYAmount, im_width, im_height );     
} 

Here is the jsdiddle where you can simulate it and see what I mean.

PS: You can rotate the image with the slider on the left. The bottom slider is for zooming. Please re-run the fiddle if the image does not appear in the first load.

Share Improve this question asked May 18, 2015 at 19:14 SkeletorSkeletor 3,4135 gold badges36 silver badges56 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 8

Reset the transformations after drawing. The mouse events are transformed as well when applied to the canvas context so using transforms only when drawing can solve this. However, this also require the code to use absolute values, for example:

function draw(){
    var im_width = parseInt( imageObj.width + resizeAmount, 10 );
    var im_height = parseInt( imageObj.height + resizeAmount, 10 );
    var rotationAmount = rotationVal; // disabled: - prevRotation;

    context.clearRect( 0, 0, canvas.width, canvas.height );

    // move to origin first
    context.translate( moveXAmount, moveYAmount );

    // rotate
    context.rotate( rotationAmount * Math.PI / 180 );

    // change to translate back based on image size
    // (remember to pensate for scale, not shown here)
    context.translate( -imageObj.width/2, -imageObj.height/2 );
    context.drawImage( imageObj, 0, 0, im_width, im_height );

    // reset transforms (identity matrix)
    context.setTransform(1,0,0,1,0,0);
} 

Modified fiddle

Optionally you would need to use inverse matrix. This is something that will bee available later when we can take out a SVGMatrix based on the current transformation matrix, but this is not widely available at this time. Otherwise the inverse matrix would be applied to the mouse x/y position to sort of, as the name implies, inverse the effect of the main transformation.

Optionally use a custom transformation matrix solution to keep track of transform (I'll invite you to check out my own approach to this here, it's free).

PS: also fixed the image loading problem (see fiddle).

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 500;
var x      = 250;
var y      = 500;
var width  = 100;
var height = 100
var cx     = x + 0.5 * width;   // x of shape center
var cy     = y + 0.5 * height;  // y of shape center



class Meteor {
  constuctor(degrees){
    this.degrees = degrees;
    //this.y = 0; 
  }
  draw(d){
      //this.y = y++
      ctx.save();
      ctx.translate(x,d)
      ctx.rotate( (Math.PI / 180) * d);  //rotate 25 degrees.
      ctx.translate(-cx, -cy);            //translate center 
      ctx.fillStyle = "#0000ff";
       ctx.fillRect(x, y, width, height);
      ctx.restore();

      //ctx.setTransform(1, 0, 0, 1, 0, 0);

  }
}
let m = new Meteor(90)

d = 0; 
function animate(){
  ctx.clearRect(0,0,canvas.width,canvas.height)
  // Save the default state
  d++;
  m.draw(d)


  // Restore the default state


  ctx.fillRect(250, 40, 10, 10); //spaceship 
  ctx.fillRect(150, d, 100, 100);  
  window.requestAnimationFrame(animate)
}
animate()





function draw(){
    var im_width = parseInt( imageObj.width + resizeAmount, 10 );
    var im_height = parseInt( imageObj.height + resizeAmount, 10 );
    var rotationAmount = rotationVal; // disabled: - prevRotation;

    context.clearRect( 0, 0, canvas.width, canvas.height );

    // move to origin first
    context.translate( moveXAmount, moveYAmount );

    // rotate
    context.rotate( rotationAmount * Math.PI / 180 );

    // change to translate back based on image size
    // (remember to pensate for scale, not shown here)
    context.translate( -imageObj.width/2, -imageObj.height/2 );
    context.drawImage( imageObj, 0, 0, im_width, im_height );

    // reset transforms (identity matrix)
    context.setTransform(1,0,0,1,0,0);
} 

https://codepen.io/niko8888/pen/NWKXgdX?editors=0010

发布评论

评论列表(0)

  1. 暂无评论