How can I move a rotated canvas image without disorientation?

I have an image uploaded to the canvas. I can not (drag) correctly move the image after it is rotated. In fact, it moves, but moves along the coordinate plane of the image. Therefore, moving 90 degrees of the rotated image to the right, moving down and not right, as expected. What could be a good way to solve this problem?

enter image description here

This is my drawing 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 a jsdiddle where you can mimic it and see what I mean.

PS: You can rotate the image using the slider on the left. The bottom slider is for scaling. Re-run the script if the image does not appear on the first boot.

+9
source share
2 answers

Reset conversion after drawing. Mouse events are also converted when applied to the canvas context, so using transforms only when the drawing can solve this problem. However, this also requires 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 compensate 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 violin

Optionally, you will need to use the inverse matrix. This is something that will become available later, when we can select the SVGMatrix based on the current transformation matrix, but currently it is not widely available. Otherwise, the inverse matrix will be applied to the x / y position of the mouse for sorting, as the name implies, to invert the effect of the main transformation.

Optionally use a custom matrix conversion tracking solution (I will invite you to see my own approach to this here , it's free).

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

+8
source
 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 compensate 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

+1
source

All Articles