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.

Loading Demo...

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.

Loading Demo...
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:

OptionDefault and unitsRequirement
minZoom0.1, dimensionlessFinite and greater than zero.
maxZoom4, dimensionlessFinite and at least minZoom.
fitMaxZoomOmitted; uses maxZoomFinite and greater than zero; clamped to minZoom/maxZoom.
scrollBoundsUnbounded when omitted; world unitsFinite 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 canvasSource behavior
Wheel or trackpad scrollPans by the event deltas. Line/page deltas are normalized to CSS pixels.
Ctrl or Command plus wheelZooms around the pointer.
Pan tool or middle-button dragPans the view.
Touch on empty canvasA moved press becomes pan; two captured pointers provide anchored pinch zoom.
Mouse/pen in SelectPicks/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.