Zoom and Drag for Html Canvas

//Set onscreen canvas and its context
let onScreenCVS = document.getElementById("onScreen");
let onScreenCTX = onScreenCVS.getContext("2d");
//improve sharpness
let ocWidth = onScreenCVS.width;
let ocHeight = onScreenCVS.height;
let sharpness = 4;
let zoom = 1;
onScreenCVS.width = ocWidth * sharpness;
onScreenCVS.height = ocHeight * sharpness;
onScreenCTX.scale(sharpness * zoom, sharpness * zoom);
const state = {
...,
xOffset: 0,
yOffset: 0,
lastOffsetX: 0,
lastOffsetY: 0,
}
//zoom buttons
let zoomCont = document.querySelector(".zoom");
zoomCont.addEventListener('click', handleZoom);
function handleZoom(e) {
if (e.target.closest(".square")) {
let zoomBtn = e.target.closest(".square");
let z;
if (zoomBtn.id === "minus") {
z = 0.8;
zoom *= z;
state.xOffset += ocWidth / 10 / zoom;
state.yOffset += ocHeight / 10 / zoom;
} else if (zoomBtn.id === "plus") {
z = 1.25;
state.xOffset -= ocWidth / 10 / zoom;
state.yOffset -= ocHeight / 10 / zoom;
zoom *= z;
}
//re scale canvas
onScreenCTX.scale(z, z);
state.xOffset = Math.floor(
state.xOffset - (state.xOffset % (ocWidth / offScreenCVS.width))
);
state.yOffset = Math.floor(
state.yOffset - (state.yOffset % (ocHeight / offScreenCVS.height))
);
state.lastOffsetX = state.xOffset;
state.lastOffsetY = state.yOffset;
renderImage();
}
}
function handleMouseMove(e) {
state.event = "mousemove";
//currently only square dimensions work
state.trueRatio = onScreenCVS.offsetWidth / offScreenCVS.width * zoom;
state.ratio = ocWidth / offScreenCVS.width * zoom;
//coords
state.mox = Math.floor(e.offsetX / state.trueRatio);
state.moy = Math.floor(e.offsetY / state.trueRatio);
state.mouseX = state.mox - (state.xOffset / state.ratio * zoom);
state.mouseY = state.moy - (state.yOffset / state.ratio * zoom);
//Hover brush
state.onX = state.mox * state.ratio / zoom;
state.onY = state.moy * state.ratio / zoom;
if (state.clicked) {
//run selected tool step function
state.tool.fn();
} else {
//only draw preview brush when necessary
if (state.onX !== state.lastOnX || state.onY !== state.lastOnY) {
onScreenCTX.clearRect(0, 0, ocWidth / zoom, ocHeight / zoom);
drawCanvas();
renderCursor();
state.lastOnX = state.onX;
state.lastOnY = state.onY;
}
}
}
 const tools = {
...,
grab: {
name: "grab",
fn: grabSteps,
brushSize: 1,
options: []
}
}
function grabSteps() {
switch (state.event) {
case "mousemove":
//only draw when necessary, get color here too
state.xOffset = state.onX - state.lastOnX + state.lastOffsetX;
state.yOffset = state.onY - state.lastOnY + state.lastOffsetY;
renderImage();
break;
case "mouseup":
state.lastOffsetX = state.xOffset;
state.lastOffsetY = state.yOffset;
state.lastOnX = state.onX;
state.lastOnY = state.onY;
break;
case "mouseout":
state.lastOffsetX = state.xOffset;
state.lastOffsetY = state.yOffset;
break;
default:
//do nothing
}
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store