Pan and zoom for images
Intorduction
@beoe/pan-zoom is a small client side script that adds pan and zoom capabilities to SVG images (to any DOM node actually).
There are a lot of similar scripts, but the main difference is that this one supports gestures for all types of devices:
| intention | mouse | trackpad/touchpad | touchscren |
|---|---|---|---|
| pan | click + move | click + move | two finger drag |
| zoom | Ctrl + wheel | pinch | pinch |
| reset | double click | double click | double tap |
| scroll | wheel | two finger drag | one finger drag |
Pay attention:
- gestures intentionally selected to not interfere with the system’s default scroll gestures, to avoid “scroll traps”
- Cmd + click - zoom in
- Alt + click - zoom out
- First double click (tap) - zoom in x2
Try to use gestures with this image 👇
Installation
-
Install dependencies
Terminal window pnpm add @beoe/pan-zoom -
Add
svgpanzoom.tssrc/components/svgpanzoom.ts import "@beoe/pan-zoom/css/PanZoomUi.css";import { PanZoomUi } from "@beoe/pan-zoom";// for BEOE diagramsdocument.querySelectorAll(".beoe").forEach((container) => {const element = container.firstElementChild;if (!element) return;// @ts-expect-errornew PanZoomUi({ element, container }).on();});// for content imagesdocument.querySelectorAll(".sl-markdown-content > img[src$='.svg' i]," +".sl-markdown-content > p > img[src$='.svg' i]," +// for development environment".sl-markdown-content > img[src$='f=svg' i]," +".sl-markdown-content > img[src$='f=svg' i]").forEach((element) => {if (element.parentElement?.tagName === "PICTURE") {element = element.parentElement;}const container = document.createElement("figure");container.classList.add("beoe", "not-content");element.replaceWith(container);container.append(element);// @ts-expect-errornew PanZoomUi({ element, container }).on();}); -
Use
svgpanzoom.tsin the base layout
Starlight specific code
-
Use
svgpanzoom.tsin thePageFramesrc/components/PageFrame.astro ---import type { Props } from "@astrojs/starlight/props";import Default from "@astrojs/starlight/components/PageFrame.astro";---<Default {...Astro.props}><slot name="header" slot="header" /><slot name="sidebar" slot="sidebar" /><slot /></Default><script>import "./svgpanzoom.ts";</script> -
Override
PageFramein Astro configastro.config.mjs export default defineConfig({integrations: [starlight({components: {PageFrame: "./src/components/PageFrame.astro",},}),],});
Further improvements
- style pan-zoom buttons
- create rehype plugin to wrap images into container (
<figure class="beoe"></figure>), to avoid creating it on the client side