Skip to content
D
Documentation

Navigate diagrams

how-to
3 min readUpdated

Add viewport controls, make visible detail respond to zoom, and support touch navigation in a mounted diagram. The canvas and camera share one headless model across framework bindings.

Add a minimap, controls, and zoom-level feedback

Use the shipped canvas plugins for the minimap, zoom/fit toolbar, and dotted background; the plugin-enabled canvas also supports the built-in pan, zoom, tap-selection, node-drag, and pinch gestures. Add your own zoom choices through the mounted instance when you want a predictable detail readout: the renderer chooses a level-of-detail tier from the current zoom. The JavaScript, Angular, React, and Vue samples disable the adaptive quality governor so the tier follows zoom directly, matching the contextual-zoom demo.

Each sample mounts a small connected diagram and leaves room for touch navigation. JavaScript, Angular, Qwik, React, and Vue show the minimap and shipped zoom/fit controls; only React and Vue add buttons with a tier readout. Angular displays its chosen zoom. The renderer changes detail as the camera zooms, without application code rewriting node data.

Build on the mounting and typed-data pattern in Build runnable workflows: this page adds the minimap, zoom-level controls and rendered-tier feedback, plus touch navigation. The Angular example uses DiagramCanvasComponent.

js
import { render } from '@grafloria/element';
import { attachCanvasPlugins } from '@grafloria/renderer';

const nodes = Array.from({ length: 9 }, (_, i) => ({
  id: `n${i}`,
  position: { x: 90 + (i % 3) * 300, y: 70 + Math.floor(i / 3) * 190 },
  size: { width: 170, height: 74 },
  data: { label: `Step ${i + 1}` },
}));
const edges = Array.from({ length: 8 }, (_, i) => ({
  id: `e${i}`, source: `n${i}`, target: `n${i + 1}`,
}));

const app = document.createElement('main');
app.style.height = '100vh';
const host = document.createElement('div');
host.style.cssText = 'height:100%;touch-action:none';
document.body.append(app);
app.append(host);

const instance = render({ nodes, edges }, host, { renderer: { qualityGovernor: false } });
attachCanvasPlugins(instance, {
  background: { variant: 'dots' },
  minimap: true,
  controls: true,
});
instance.fitView(40);
instance.renderNow();

In the React and Vue samples, the buttons set zoom to 1.5×, 0.7×, 0.3×, or 0.15× and the readout shows the tier reported after each selection. The tiers are high, medium, sketch, and low at those zoom levels in the contextual-zoom demo, and rendered detail falls as you zoom out. Angular displays its current zoom value. JavaScript and Qwik use the minimap and zoom/fit toolbar; Qwik's status output changes when its canvas initializes.

The minimap mirrors the nodes and camera; its camera rectangle follows navigation. On a touch screen, drag empty canvas to pan, pinch to zoom, tap a node to select it, or drag a node with one finger. The canvas container uses touch-action: none so the browser does not consume those gestures for page scrolling or zooming.

Options that affect navigation

OptionTypeDefaultWhat it does
pluginsboolean | CanvasPluginOptionsOff unless enabledOn a framework canvas, true mounts the minimap, zoom/fit controls, and background grid. In JavaScript, configure those pieces with attachCanvasPlugins().
minZoomnumber0.1Sets the camera's lower zoom bound.
maxZoomnumber3.0Sets the camera's upper zoom bound.
zoomSensitivitynumber0.1Sets the relative step per wheel notch or keyboard zoom.
enablePanbooleanEnabledEnables canvas panning.
enableZoombooleanEnabledEnables canvas zooming. Angular names the wheel option enableMouseWheelZoom; touch zoom uses the shared gesture pipeline.
rendererConfig.qualityGovernorboolean | GovernorOptionsEnabledThe adaptive governor can adjust detail under load. Set it to false when you want detail tier to follow zoom alone, as in the sample.

NodeSpec and EdgeSpec are the framework data types used for the mounted graph. The instance-level camera methods and the Angular viewportController() provide the same zoom operation; the Angular example binds the canvas through its component rather than constructing a second camera.

Use the plugins prop when its default minimap, controls, and grid suit the editor. Use attachCanvasPlugins() when mounting through render() and when you need to choose plugin options separately. The instance's viewport controller sets zoom and reads the current zoom; getQualityState() reports the tier actually rendered.

Pitfalls

  • Give the canvas a resolved height. It fills its parent; a zero-height parent appears blank.
  • Keep touch handling on the canvas area: touch-action: none prevents native browser gestures from interrupting pointer movement.
  • The zoom values in the sample are choices for its buttons, not universal thresholds. minZoom and maxZoom clamp camera movement; use the tier readout and your own diagram to choose useful stops.

See it running

Was this page helpful?

Navigate diagrams — Grafloria · GPT-6 Luna