Rotating a small image on a background image places the small image in a different location

<div id="canvasContainer">
  <canvas id="canvas" width="900" height="520"></canvas>
</div>
const cCanvas = document.getElementById('canvas');
  cCanvas.width = 600;
  cCanvas.height = 300;
const cContext = cCanvas.getContext('2d');
const cBackgroundImage = new Image();
const cBackgroundWidth = cCanvas.width;

let lBackgroundHeight; 
const cCarImage = new Image();
const cCarImageWidth = 40; 
const cCarImageHeight = 100; 
let lCarTopLeftX; 
let lCarTopLeftY; 

document.addEventListener(
  'DOMContentLoaded', (ev) => 
  {
    cBackgroundImage.onload = function () 
    {
      cCarImage.onload = function () 
      {
        const cAspectRatio = cBackgroundImage.naturalWidth / cBackgroundImage.naturalHeight;
        lBackgroundHeight = cCanvas.height = cBackgroundWidth / cAspectRatio; 
        cContext.drawImage(cBackgroundImage, 0, 0, cBackgroundWidth, lBackgroundHeight); 
        lCarTopLeftX = cBackgroundWidth / 2 - cCarImageWidth / 2 + 70; 
        lCarTopLeftY = lBackgroundHeight / 2 - cCarImageHeight / 2 + 100; 
        //Note: lCarTopLeftX = 350
        //Note: lCarTopLeftY = 321.869
        cContext.drawImage(cCarImage, lCarTopLeftX, lCarTopLeftY, cCarImageWidth, cCarImageHeight);
      }
      cCarImage.src = "Car.jpg"; 
    }
    cBackgroundImage.src = "Streets.jpg";
  }
) 
document.body.addEventListener(
  "keydown", e =>
  {
    e.preventDefault();
    render();
  }
)
function render()
{
  //Note: lCarTopLeftX = 350
  //Note: lCarTopLeftY = 321.869
  cContext.clearRect(0, 0, cCanvas.width, cCanvas.height);
  cContext.drawImage(cBackgroundImage, 0, 0, cBackgroundWidth, lBackgroundHeight);  
  let lRadians = Math.PI / 180 * 0;  // let lRadians = Math.PI / 180 * 45;
  cContext.translate(lCarTopLeftX, lCarTopLeftY);
  cContext.rotate(lRadians);
  cContext.drawImage(cCarImage, -cCarImageWidth / 2, -cCarImageHeight / 2, cCarImageWidth, cCarImageHeight);
  cContext.rotate(-lRadians);
  cContext.translate(-lCarTopLeftX, -lCarTopLeftY);    
}

– This code puts a car on a street background. Pushing a key on the keyboard rotates the image.

The plan was to rotate the car 45 degrees. Because of the strange result, the angle has been changed to 0 degrees to help debug.

The car and background images — Car.jpg => https://snipboard.io/ptkWjJ.jpg — Streets.jpg => https://snipboard.io/4YgDaf.jpg.

The images combined — https://snipboard.io/IXlKiV.jpg.

The image after hitting the keyboard spacebar — https://snipboard.io/QTBlgS.jpg. — The car moved to a different location, even though X and Y did not change — lCarTopLeftX = 350 — lCarTopLeftY = 321.869.

The first time you drew it:
cContext.drawImage(
cCarImage,
lCarTopLeftX,
lCarTopLeftY,
cCarImageWidth,
cCarImageHeight

You put its top left corner at TopLeftX TopLeftY, its Width at its width, and its height at its height.

The second time you drew it,
cContext.drawImage(
cCarImage,
-cCarImageWidth / 2,
-cCarImageHeight / 2,
cCarImageWidth,
cCarImageHeight
);
You drew it with the top left at negative half its width and height, and then translated it to the same coordinates.

So in other words, you’ve shifted it by half its width and height. (You didnt put the top-left corner at TopLeftX TopLeftY, you put the center at TopLeftX TopLeftY).

You probably want to change your initial draw.

1 Like

Thanks for your comments. I had assumed that “context.translate” uses the X Y of the image top left corner, as “context.drawImage” does. Incorrect!

The “context.translate” does use the X Y of the image “center”.

Solution:

  let lCarCenterX = lCarTopLeftX + cCarImageWidth / 2;
  let lCarCenterY = lCarTopLeftY + cCarImageHeight / 2;
  ...
  cContext.translate(lCarCenterX, lCarCenterY);
  ...
  cContext.translate(-lCarCenterX, -lCarCenterY);    

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.