UNPKG

@rbuljan/zoompan

Version:

Zoomable and pannable area with scrollbars. Inspired by graphical editors like Photoshop.

235 lines (203 loc) 6.99 kB
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <link rel="shortcut icon" href="#!" type="image/x-icon"> <title>ZoomPan - @rokobuljan</title> <link rel="stylesheet" href="./../zoompan.css"> <style> * { margin: 0; box-sizing: border-box; } body { background: hsl(200, 4%, 16%); font: 1rem/1.4 sans-serif; color: rgba(255, 255, 255, 0.8); display: flex; } a, h1, h2 { color: #0bf; font-weight: 100; } h1 { font-size: 2rem; } aside { flex: none; padding: 2rem; font-size: 0.8rem; max-width: 240px; display: flex; flex-direction: column; } footer { margin-top: auto; } main { position: relative; flex: 1; height: 100vh; } #myEditor { position: absolute; width: 100%; height: 100%; } #controls { display: flex; gap: 2px; } #controls button, #controls select { flex: none; outline: none; border: 0; background: rgba(0, 0, 0, 0.3); color: rgba(255, 255, 255, 0.6); font-size: 11px; padding: 0 0.5rem; } #controls option { color: #000; } #zoomPct { width: 4.5rem; } #zoomPct option[disabled] { display: none; } /* ZoomPan: Custom overrides: */ .zoompan { background: rgba(0, 0, 0, 0.2); } .zoompan .zoompan-canvas { display: flex; align-items: center; justify-content: center; color: #000; font-size: 3rem; background-size: 50px 50px, 50px 50px, cover; background-image: linear-gradient(to right, black 1px, transparent 1px), linear-gradient(to bottom, black 1px, transparent 1px), linear-gradient(45deg, hsl(0, 100%, 50%), hsl(30, 100%, 50%), hsl(60, 100%, 50%), hsl(90, 100%, 50%), hsl(120, 100%, 50%), hsl(150, 100%, 50%), hsl(180, 100%, 50%), hsl(210, 100%, 50%), hsl(240, 100%, 50%), hsl(270, 100%, 50%), hsl(300, 100%, 50%), hsl(330, 100%, 50%), hsl(360, 100%, 50%)); } .zoompan .zoompan-track-x { /* Smaller track, to make space for #controls */ left: 150px; } </style> </head> <body> <aside> <h1>ZoomPan</h1> <br> In this example we respect the user experience by the way browsers wheel and keyboard shortcuts already handle scaling and scrolling. You can always change and customize this hotkeys as desired. <br> <br> <h3>Controls</h3> <br> <h2>Scale</h2> Ctrl WheelUp/Down<br> Ctrl +<br> Ctrl -<br> Pinch<br> <br> <h2>Pan</h2> Ctrl Drag<br> Ctrl Arrows<br> WheelUp/Down<br> Shift WheelUp/Down<br> <footer> Git: <a href="https://github.com/rokobuljan/zoompan">ZoomPan</a><br> Author: <a href="https://github.com/rokobuljan">rokobuljan</a><br> Licence: MIT </footer> </aside> <main> <div id="myEditor"> <div id="controls"> <button id="zoomOut">-</button> <button id="zoomIn">+</button> <select id="zoomPct"> <option disabled></option> <option value="0.25">25%</option> <option value="0.50">50%</option> <option value="0.75">75%</option> <option value="1.00">100%</option> <option value="1.25">125%</option> <option value="1.50">150%</option> <option value="2.00">200%</option> </select> <button id="fit">Fit</button> </div> </div> </main> <script type="module"> import ZoomPan from "./../zoompan.js"; import { hotkeys } from "./lib/hotkeys.js"; // DOM helper functions: const el = (sel, par) => (par || document).querySelector(sel); // Scale select box: const elZoomPct = el("#zoomPct"); const setSelectOptionText = (scale) => { const elOpt0 = el("option", elZoomPct); elOpt0.textContent = Math.round(scale * 100) + "%"; elZoomPct.selectedIndex = 0; }; // Initialize ZoomPan with options const ZP = new ZoomPan("#myEditor", { width: 800, height: 500, canDrag: false, // We want to use "Ctrl" key to drag-pan (See below) onInit() { this.elCanvas.textContent = "Welcome to ZoomPan"; }, onChange() { setSelectOptionText(this.scale); } }); // Allow dragging only while Ctrl key is pressed ZP.elViewport.addEventListener("pointermove", (ev) => ZP.canDrag = ev.ctrlKey ); // Example calling ZP methods on specific hotkeys // This example uses an external library for hotkeys hotkeys({ "ctrl wheelup": (ev) => ZP.scaleWheel(ev), "ctrl wheeldown": (ev) => ZP.scaleWheel(ev), "ctrl +": () => ZP.scaleUp(), "ctrl -": () => ZP.scaleDown(), "ctrl arrowup": () => ZP.panDown(), "ctrl arrowdown": () => ZP.panUp(), "ctrl arrowleft": () => ZP.panRight(), "ctrl arrowright": () => ZP.panLeft(), "wheelup": () => ZP.panDown(), "wheeldown": () => ZP.panUp(), "shift wheelup": () => ZP.panRight(), "shift wheeldown": () => ZP.panLeft(), }, ZP.elViewport); // UI inputs events: elZoomPct.addEventListener("input", () => ZP.scaleTo(+elZoomPct.value)); el("#zoomIn").addEventListener("click", () => ZP.scaleUp()); el("#zoomOut").addEventListener("click", () => ZP.scaleDown()); el("#fit").addEventListener("click", () => ZP.fit()); </script> </body> </html>