Search code examples
javascripthtmlcanvas

Centerize the base point of scale


I am using the scale of the canvas

This code at first shows the red box, then blue box appears.

However this blue box is not centrized it's a bit shifted.

I have a few questions.

  1. Is it possible to centerize the point of scale?

  2. If 1) is impossible, how can I calculate the point as if it looks like centerized?

var canvas = document.getElementById( "target" ) ;
var ctx = canvas.getContext( "2d" ) ;


ctx.fillStyle = "red";
ctx.fillRect(75,75,10,10);
ctx.fillRect(115,75,10,10);
ctx.fillRect(75,115,10,10);
ctx.fillRect(115,115,10,10);

// I want to scale this fromthe center point and rewrite.



setTimeout(() => {
var scale= 2
ctx.scale(scale,scale);
ctx.fillStyle = 'blue';

ctx.fillRect(75 / scale,75 / scale,10 ,10 );
ctx.fillRect(115 / scale,75 / scale,10 ,10 );
ctx.fillRect(75 / scale,115 / scale,10 ,10 );
ctx.fillRect(115 / scale,115 / scale,10,10 );
}, 2000);
<canvas id="target" width=200 height=200
style="border: 1px solid black; ">
</canvas>


Solution

  • I'm not totally sure what you are asking, but here's this:

    First I use translate() to move the origin of the canvas from the top left corner to the center.

    Also, I draw the rectangles with the center at x,y and not the top left at x,y.

    var canvas = document.getElementById( "target" ) ;
    var ctx = canvas.getContext( "2d" ) ;
    
    // Move origin to center
    ctx.translate(canvas.width / 2, canvas.height / 2);
    
    // Draw a rect centered on x,y
    const centerRect = (x, y, sz) => {
      ctx.fillRect(x - sz / 2, y - sz / 2, sz, sz);
    };
    
    // Positions (centers) of the 4 rectangles
    const pos = [[-20, -20], [20, -20], [-20, 20], [20, 20]];
    
    ctx.fillStyle = "red";
    pos.forEach(p => centerRect(p[0], p[1], 10));
    
    setTimeout(() => {
      ctx.fillStyle = 'blue';
      var scale = 2
      ctx.scale(scale, scale);
      // Draw the same 4 rectangles, this time scaled.
      pos.forEach(p => centerRect(p[0], p[1], 10));
    }, 2000);
    <canvas id="target" width=200 height=200
    style="border: 1px solid black; ">
    </canvas>