Skip to content

Controlling the Camera

The camera decides which part of your graph is on screen and at what scale and angle. Everything camera-related lives on nodus.view. This guide is a set of recipes: zooming, panning, rotating, fitting the graph, animating moves, converting between screen and graph coordinates, hit-testing, and sizing.

For how the two coordinate spaces relate, see The Coordinate System. For the full method list, see API: View.

Zooming

// Set an absolute zoom level.
nodus.view.setZoom(2);
// Relative zoom in / out (centred on the viewport).
nodus.view.zoomIn();
nodus.view.zoomOut();
// Read the current zoom.
const z = nodus.view.getZoom();

Panning

Move the camera by setting its centre, nudging it by a delta, or moving to a target. getCenter() returns the current centre in graph coordinates.

// Centre the view on a specific graph point.
nodus.view.setCenter({ x: 0, y: 0 });
// Nudge by a delta.
nodus.view.move({ x: 50, y: 0 });
// Move to a target point or element.
nodus.view.moveTo({ x: 120, y: 80 });
// Frame a specific bounding box.
nodus.view.moveToBounds({ minX: 0, minY: 0, maxX: 200, maxY: 150 });

Rotating

// Set an absolute angle (radians).
nodus.view.setAngle(Math.PI / 6);
// Rotate by a delta.
nodus.view.rotate(-Math.PI / 12);
// Read the current angle.
const a = nodus.view.getAngle();

Fitting the graph

locateGraph() zooms and pans so the entire graph fits the viewport. It returns a promise — run it after a layout (or after adding nodes) to frame the final positions.

await nodus.layouts.force({ duration: 0 });
await nodus.view.locateGraph();

To preview the framing for some data without loading it, use locateRawGraph(graph).

Try it live — fit the whole graph, zoom, and focus a single node:

Fit, zoom & focus Open in new tab ↗

Animating camera moves

Most camera methods accept an options object that commonly carries { duration } (milliseconds) to animate the transition instead of jumping.

// Glide to a new centre over 600ms.
nodus.view.setCenter({ x: 0, y: 0 }, { duration: 600 });
// Animate a zoom.
nodus.view.setZoom(1.5, { duration: 400 });
// Animate the fit-to-graph.
await nodus.view.locateGraph({ duration: 600 });

You can wait for the renderer between frames with beforeNextFrame() / afterNextFrame(), and check whether a transition is running with animationInProgress().

Saving and restoring the full view

get() snapshots the complete camera state (zoom, centre, angle); set(view) restores it. Handy for bookmarks or “reset to default” buttons.

// Remember where we are.
const saved = nodus.view.get();
// ...user explores...
// Jump back, animated.
nodus.view.set(saved, { duration: 500 });

Converting coordinates

Graph coordinates are the data space your nodes live in; screen coordinates are pixels in the container. Convert both ways — for example to place a DOM tooltip next to a node, or to turn a click position into a graph point.

// Graph point -> screen pixels (e.g. to position an overlay).
const screenPt = nodus.view.graphToScreenCoordinates({ x: 120, y: 80 });
// Screen pixels -> graph point (e.g. from a mouse event).
const graphPt = nodus.view.screenToGraphCoordinates({ x: event.offsetX, y: event.offsetY });

Try it live — set center and zoom, and convert between screen and world points:

Coordinates Open in new tab ↗

Hit-testing and queries

Ask the view what’s under a point, or what falls inside a region.

// The element at a screen point (or null).
const hit = nodus.view.getElementAt({ x: 200, y: 140 });
// Everything currently visible in the viewport.
const visible = nodus.view.getElementsInView();
// Everything inside a rectangle. Pass coords as graph or screen space.
const inBox = nodus.view.getElementsInside(0, 0, 200, 150, /* inGraphCoords */ true);
// The current visible bounds, and the graph's overall bounding box.
const bounds = nodus.view.getBounds();
const graphBox = nodus.view.getGraphBoundingBox();

Locating a single element

Any node or edge can bring itself into view with element.locate(). It accepts the same animation options as the camera methods.

nodus.getNode('ada').locate({ duration: 500 });

Sizing and resizing

The view tracks the container’s pixel size. Read it with getSize(). When you resize the container yourself (e.g. a panel collapses), set the new size or call forceResize() to make the view re-measure.

// Current pixel size.
const { width, height } = nodus.view.getSize();
// Set an explicit size (returns a promise).
await nodus.view.setSize({ width: 800, height: 600 });
// Or re-measure the container after a CSS layout change.
window.addEventListener('resize', () => nodus.view.forceResize());

Fullscreen

nodus.view.setFullScreen(true);
const isFull = nodus.view.isFullScreen();

A snapshot of the canvas

For a raster image of the current view, use getImageData():

const imageData = nodus.view.getImageData();

Next steps