Diagram - Pan and Zoom
Navigate a canvas, fit a selection and constrain the view without changing the saved diagram.
#Usage
import { Diagram } from '@primeui/vue-diagram';<Diagram.Root :store="store" page-id="page" :navigation-options="{ minZoom: 0.4, maxZoom: 1.8 }">
<Diagram.CommandButton command-id="fit" v-slot="{ getButtonProps }">
<button v-bind="getButtonProps({ type: 'button' })">Fit diagram</button>
</Diagram.CommandButton>
<Diagram.Viewport :auto-fit="true" label="Workflow editor" style="height: 24rem" />
</Diagram.Root>Navigation limits configure session camera behavior. A measurable viewport height is required; zoom does not resize saved nodes.
This skeleton assumes an initialized store with page page. Use First Diagram for model creation, style imports and store disposal.
Pan and zoom change the session's view, not node positions or model history. Start with the root and viewport from First Diagram; navigation needs no optional module.
#Move the canvas and fit a selection
Turn Pan tool on, then drag the canvas. Select Review request and choose Fit selection to frame that card. Fit all restores a view of the graph. Zoom near upper left uses an explicit anchor at 120, 80 in viewport-local CSS pixels.
session.panBy(x, y) translates the view by CSS pixels. zoomAt(zoom, anchor?)
takes an absolute zoom factor, preserving the world point beneath the anchor.
The default anchor is the viewport center. Built-in zoom commands multiply or
divide the current zoom by 1.2; they use that center anchor.
session.fit(ids?, padding?) frames the visible scene, or the visible supplied
IDs, with 32 CSS pixels of padding by default. Fit selection uses current
selection IDs; an empty selection makes no view change. Fit and reveal include
projected visual geometry, not just authored node rectangles.
:auto-fit="true" fits once when that viewport first measures a nonzero size.
Its default is false. Later content edits and viewport resizes do not keep
refitting; a resize updates the session size and reapplies view bounds. Reset in
these examples remounts the viewport, so the new instance performs its initial fit.
#Limit the view and use an overview
Reveal Archive request, then try Pan 600 px and the zoom controls. The view obeys a finite world rectangle and zoom range. The copied overview shows node rectangles and selection, with Fit and zoom actions; its map is not a draggable minimap or a rendering of rich node content and connectors.
import type { DiagramNavigationOptions } from '@primeui/vue-diagram';
const navigation: DiagramNavigationOptions = {
minZoom: 0.4,
maxZoom: 1.8,
scrollBounds: { x: -40, y: -40, width: 760, height: 360 }
};Bind this object to root navigationOptions. Keep its identity stable; changing
navigation options cancels an active pointer gesture and reapplies the limits.
The root's empty options object uses these session defaults:
| Option | Default and units | Requirement |
|---|---|---|
minZoom | 0.1, dimensionless | Finite and greater than zero. |
maxZoom | 4, dimensionless | Finite and at least minZoom. |
fitMaxZoom | Omitted; uses maxZoom | Finite and greater than zero; clamped to minZoom/maxZoom. |
scrollBounds | Unbounded when omitted; world units | Finite rectangle with positive width and height. |
An extent smaller than the viewport is centered on that axis. A larger extent clamps its edges. Fit, zoom and reveal all obey these limits, so a restrictive rectangle can prevent the requested framing.
Set fitMaxZoom when fitting a sparse graph should leave it at a readable scale
instead of enlarging it to fill the canvas. It applies to session.fit(), Fit
selection, the built-in Fit commands, keyboard Home/End and viewport auto-fit.
It leaves deliberate zoom and reveal unchanged. These demos set
fitMaxZoom: 1.15 while retaining their manual zoom limits. In your application,
set fitMaxZoom alongside your other navigation limits. Omitting the option
preserves the default Fit behavior.
session.reveal(id) centers visible node/connector geometry at the existing
zoom. A collapsed child may reveal its visible collapsed owner; otherwise a
hidden or unknown target has no effect. Reveal does not select or focus the
target. Use the Selection guide when
those states should change too.
#Native input and keyboard alternatives
| Input on the canvas | Source behavior |
|---|---|
| Wheel or trackpad scroll | Pans by the event deltas. Line/page deltas are normalized to CSS pixels. |
| Ctrl or Command plus wheel | Zooms around the pointer. |
| Pan tool or middle-button drag | Pans the view. |
| Touch on empty canvas | A moved press becomes pan; two captured pointers provide anchored pinch zoom. |
| Mouse/pen in Select | Picks/selects entities; empty-space dragging can marquee. |
Dragging a node remains an editing gesture when permitted; a pen is not automatically treated as a touch pan. Native controls inside nodes keep their input. With canvas focus, +/− zoom, Home fits all, End fits selection and PageUp/PageDown pan vertically. Tool buttons provide a pointer alternative.
Navigation remains available in a read-only editor. Test touch, pen and assistive technology on the platforms your application supports.
#Start with a readable detail
For a large drawing in a narrow canvas, opt in to one-time detail framing:
<Diagram.Viewport :initial-frame="{ targetId: 'request', detailBelowWidth: 600, minZoom: 0.9, padding: 16 }" label="Request details" style="height: 24rem" />
<Diagram.CommandButton command-id="fit" v-slot="{ getButtonProps }">
<button v-bind="getButtonProps({ type: 'button' })">Fit all</button>
</Diagram.CommandButton>This fragment belongs inside the root from the usage example. Widths up to the threshold frame the visible target; wider measurements use Fit all. The runtime waits for a nonzero viewport and the target. It respects prior host or user camera changes and initializes once per session. Edits, themes and resizes do not reset the camera. Replacing the Store or page allows the new session to initialize. Viewports under one root share the session, camera and measured viewport size; the first eligible viewport initializes the camera. Use independent roots for independent sizes and navigation. Content updates and unchanged measurements do not resize the session or cancel active gestures.
view.frame(id, options?) and session.frame(id, options?) explicitly frame a
visible node or connector without changing selection or history. Options default
to minZoom: 0.9 and padding: 16. Navigation limits and scroll bounds apply; an
oversized target may be partly outside the canvas. Hidden/missing targets,
zero-size viewports or invalid options return false. Keep pan, zoom and Fit all
reachable. Without initialFrame, existing autoFit behavior is unchanged.