🍳 and 🔍. Space + drag to pan, Z to zoom, and shift + Z to reset.
Per
// ==UserScript==
// @name 🍳 Zoom
// @namespace https://greasyfork.org/users/281093
// @match https://sketchful.io/
// @grant none
// @version 1.0
// @author Bell
// @description 🍳 and 🔍. Space + drag to pan, Z to zoom, and shift + Z to reset.
// @run-at document-end
// ==/UserScript==
const canvas = document.querySelector("#canvas");
const zoomContainer = document.createElement("div");
const sheet = window.document.styleSheets[window.document.styleSheets.length - 1];
const resetObserver = new MutationObserver(resetCanvas);
let panning = false;
let startPos = {};
let canvasOffset = {};
let cursor = "default";
let zoomed = false;
(function init() {
canvas.style.position = "relative";
canvas.style.transition = "transform 0.1s ease";
zoomContainer.style.overflow = "hidden";
zoomContainer.id = "zoomContainer";
sheet.insertRule(".dark #zoomContainer { background: #2C2F33}");
sheet.insertRule("#zoomContainer { background: #c8c8c8}")
wrap(canvas, zoomContainer);
resetCanvas();
resetObserver.observe(document.querySelector("#gameSticky"), { childList: true });
document.addEventListener("keydown", keyDown, false);
document.addEventListener("keyup", stopPanning, false);
canvas.addEventListener("pointerdown", getStartPos, true);
canvas.addEventListener("pointermove", moveCanvas, true);
document.addEventListener("pointerup", stopMoving, false);
})();
function wrap(toWrap, wrapper) {
toWrap.parentNode.appendChild(wrapper);
wrapper.appendChild(toWrap);
};
function stopPanning(e) {
if (e.code !== "Space" || !panning) return;
e.preventDefault();
canvas.style.cursor = cursor;
panning = false;
}
function keyDown(e) {
if (!isDrawing()) return;
switch (e.code) {
case "Space":
startPanning();
e.preventDefault();
break;
case "KeyZ":
if (e.ctrlKey) return;
else if (e.shiftKey) {
resetCanvas();
e.stopImmediatePropagation();
return;
}
toggleZoom();
e.stopImmediatePropagation();
}
}
function toggleZoom() {
canvas.style.transform = zoomed ? "": "scale(2)";
zoomed = !zoomed;
}
function startPanning() {
if (panning) return;
cursor = canvas.style.cursor;
canvas.style.cursor = "grab";
panning = true;
}
function moveCanvas(e) {
if (!panning || !e.buttons) return;
let offset = {};
offset.x = e.clientX - startPos.x;
offset.y = e.clientY - startPos.y;
canvas.style.left = `${(canvasOffset.x + offset.x)}px`;
canvas.style.top = `${(canvasOffset.y + offset.y)}px`;
e.preventDefault();
e.stopImmediatePropagation();
}
function getStartPos(e) {
if (!panning) return;
startPos.x = e.clientX;
startPos.y = e.clientY;
canvas.style.cursor = "grabbing";
e.preventDefault();
e.stopImmediatePropagation();
}
function stopMoving(e) {
canvasOffset.x = parseInt(canvas.style.left.match(/-?\d+/)[0]);
canvasOffset.y = parseInt(canvas.style.top.match(/-?\d+/)[0]);
if (panning) {
canvas.style.cursor = "grab";
e.stopImmediatePropagation();
}
}
function resetCanvas() {
canvas.style.left = "0px";
canvas.style.top = "0px";
canvas.style.transform = "";
zoomed = false;
canvasOffset = { x: 0, y: 0 };
}
function isDrawing() {
return document.querySelector("#gameTools").style.display !== "none" &&
document.querySelector("body > div.game").style.display !== "none" &&
document.activeElement !== document.querySelector("#gameChatInput");
}