scale canvas with imageData inside

I have a canvas with imageData inside. I would like to learn how to zoom canvas
(the fastest way)

Right now my code looks like this

// get canvas element
var canvas = document.getElementById('canvas');
var canvasWidth  = 1000;
var canvasHeight = 1000;
var ctx = canvas.getContext('2d');


var imageData = ctx.getImageData(0, 0, window.innerWidth, window.innerHeight);

var buf = new ArrayBuffer(imageData.data.length);
var buf8 = new Uint8ClampedArray(buf);
var data = new Uint32Array(buf);

// little noise 
for (var y = 0; y < canvasHeight; ++y) {
    for (var x = 0; x < canvasWidth; ++x) {
        var value = x * y & 0xff;

        data[y * canvasWidth + x] =
            (255 << 24) |    // alpha
            (Math.floor(Math.random() * 256) << 24) |    // blue
            (Math.floor(Math.random() * 256) << 12) |    // green
             Math.floor(Math.random() * 256) << 6;            // red
    }
}

imageData.data.set(buf8);


// lets start  zooming

let WINDOW_WIDTH = window.innerWidth;
let WINDOW_HEIGHT = window.innerHeight;


// max and minimum level of zooming
let MAX_ZOOM = 5;
let MIN_ZOOM = 0.5;
let SCROLL_SENSITIVITY = 0.0005;
let cameraZoom = 1;


function adjustZoom(zoomAmount) {
    if (zoomAmount) 
    {
        cameraZoom += zoomAmount;
    }
        
    cameraZoom = Math.min( cameraZoom, MAX_ZOOM ); 
    cameraZoom = Math.max( cameraZoom, MIN_ZOOM );
}


function draw() {

      canvas.width = WINDOW_WIDTH;
    canvas.height = WINDOW_HEIGHT;
    // set new center 
    ctx.translate( WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 );

    // scalling 
    ctx.scale(cameraZoom, cameraZoom);
    
    // clear canvas
    ctx.clearRect(0,0, WINDOW_WIDTH, WINDOW_HEIGHT);

    // draw pixels
    ctx.putImageData(imageData, 0, 0);

  // draw rectangle
    ctx.fillStyle = "#FF0000";
    ctx.fillRect( 100, 100, 100, 100 );

    requestAnimationFrame( draw );
}

// wheel listener
canvas.addEventListener( 'wheel', (e) => adjustZoom(e.deltaY*SCROLL_SENSITIVITY));


draw();
canvas {
    position: absolute;
  top: 0; 
  left: 0;
  width: 100%; 
  height: 100%;
  border: 1px solid black;
  image-rendering: pixelated;
}
<canvas id="canvas" width="1000px" height="1000px"></canvas>

You can see that the red square is moving while the imageData is not
How can i fix it?

Also, there is a small problem that when you scroll with the mouse, the page itself starts to move, despite the fact that I added an event handler to the canvas

UPD

maybe I need replace putImage to drawImage?

167 thoughts on “scale canvas with imageData inside”