I'm struggling with an implementation of canvas zooming (on mouse wheel), using Vanilla Javascript, without success.
The zoom must be applied on the coordinates of the mouse, when the wheel is rolled.
It's been asked here before, but my situation is quite different, considering I can't use canvasContext.translate , and the values of offsetX and offsetY must be kept in its absolute representation (not scaled)
I would really appreciate some light.
In the following snippet, I provide my current and dysfunctional implementation. You will see how it works when you zoom in and out keeping the same zoom coordinates, but as soon as you move the mouse to new coordinates (when scale != 1)and continue zooming, the new offsets become wrong.
// initiate variabks : canvas ref, offsets, scale...
const context = document.getElementById('c').getContext('2d');
let scale = 1;
let scaleFactor = 0.2;
let offsetX=0;
let offsetY=0;
// Handle mousenwheel zoom
context.canvas.onwheel= function(e){
e.preventDefault();
// calculate scale direction 6 new value
let direction = e.deltaY > 0 ? 1 : -1;
scale += scaleFactor * direction;
// calculatethe new offsets (unscaled values)
offsetX = e.offsetX - (e.offsetX / scale);
offsetY = e.offsetY - (e.offsetY / scale);
// apply new scale
context.setTransform(1, 0, 0, 1, 0, 0);
context.scale(scale, scale);
}
// clear canvas and draw two boxes
// NO CHANGES CAN BE DONE IN THIS FUNCTION
function render(){
context.beginPath();
context.clearRect(0,0,context.canvas.width/scale,context.canvas.height/scale);
context.rect(100-offsetX,50-offsetY,50,50);
context.rect(200-offsetX,50-offsetY,50,50);
context.stroke();
document.getElementById("info").innerHTML=`
Scale : ${scale} <br>
Offets : ${ Math.round(offsetX) + ' , ' + Math.round(offsetY)} <br>
`;
requestAnimationFrame( render );
}
render()
<canvas id="c" width="350" height="150" style="border: 1px solid red;"></canvas>
<div id="info"></div>