Tutorial 03 · Frame an existing page
One function call wraps this entire page in a zoom/pan surface and gives you a Panel API viewport to attach panels to. xy ratio preserved.
The minimal recipe
<script type="module">
import panel from 'https://cdn.jsdelivr.net/npm/panel-api/+esm';
import { framePage } from 'https://cdn.jsdelivr.net/npm/panel-api/zui/+esm';
const viewport = framePage(); // wraps document.body content
panel.attachViewport(viewport); // panels now know about ZUI
panel.open("", "Hello", { width: 320 }).setHTML("Hello!");
</script>
What framePage() does
- Moves your current body content into a new
.panel-api-surfaceelement. - Puts that surface inside a fixed-size, clipped
.panel-api-viewport. - Injects minimal styles to make the layout work.
- Wires default pan/zoom interactions (override with
{ interactions: false }). - Returns a
PanelViewportyou can pass topanel.attachViewport().
No restructuring
Drop in two imports and a call. Existing layout, scripts, and event handlers still work.
Preserves xy ratio
A single uniform scale applies to both axes — content never looks squashed.
Panels stay crisp
Panels float in a sibling layer that doesn't transform with the world.
Try it
- Drag the background to pan the entire page content.
- Use the scroll wheel to zoom in and out.
- Open a panel — it stays at fixed screen size.