Viewport
A panning/zooming wrapper that keeps child content in world space while the camera moves.
Zoom or pan here
Usage
<script lang="ts">
import { Viewport } from '@obelus/trioxide';
let viewport = $state({ x: 0, y: 0, zoom: 1 });
</script>
<Viewport
bind:viewport
min-zoom={0.25}
max-zoom={20}
pattern="grid"
pattern-color="var(--trioxide_neutral-8)"
>
<div class="h-32 w-32 rounded-md bg-(--trioxide_highlight-4)"></div>
</Viewport> - Bind
viewportto react to panning/zooming or to programmatically set the camera. - Scroll/trackpad pans by default; hold
Ctrl/Cmdwhile scrolling to zoom at the cursor position. - Left mouse drag also pans the canvas; set
pan-with-mouse={false}if your content already uses dragging. - Touch: pinch to zoom, single-finger drag to pan.
- Place any elements inside; they are translated and scaled together.
Props
bind:viewport:{ x: number; y: number; zoom: number }— camera state in pixels and scale.min-zoom/max-zoom: zoom clamp (default0.2/20).pan-with-mouse: allow left-click drag panning (defaulttrue); scroll and touch gestures still work when disabled.pattern:'none' | 'dots' | 'grid' | 'cross'— canvas pattern behind your content (default'none').pattern-color: CSS color or CSS variable for the pattern (default#fff).min-cell-size: smallest pattern spacing in px; Viewport crossfades between larger spacings as you zoom (default3).grid-size: multiplier between pattern spacings (default5); higher values make the pattern stay sparse at low zoom.- Rest props are forwarded to the outer
<div>so you can add classes, inline styles, or aria attributes.