Usage guidesGraph

Viewport and coordinates

Fit the canvas, preserve the user view, convert coordinates, and position menus

The viewport is the part of the graph you can currently see. Panning or zooming changes how you view it; connections and node graph coordinates stay unchanged.

Graph positions and the current view

A node's x / y is its graph position, supplied by data or computed by layout. Camera x / y / zoom describes translation and scale. Dragging a node changes its position; dragging the canvas changes the camera.

Relayout and fitting are separate steps: layout computes positions, while fitView adjusts the camera to bring content into view.

Choose when to fit

TaskApproach
Show all contentfitView, with padding and zoom limits as needed
Center without changing scalefitCenter
Locate a node from a listfocusItem(id), shrinking when necessary to contain the target
Refresh data while keeping the viewsetData(next, { fitView: false })
Keep all content visible after a panel narrowsConfigure autoFit at initialization

The first await graph.render() performs an initial fit even with autoFit: false. Data replacement, relayout, and container resizing have separate policies. Do not call render again just to refresh the viewport.

Use the buttons below to compare centering and fitting. Zoom or pan first, then choose Center or Fit. Center retains zoom. Fit adjusts both translation and scale. Reset camera restores the first rendered camera.

Loading example…
A stays at graph (0, 0). Compare its canvas and client positions after zoom, pan, center, and fit. Wheel zoom and canvas dragging also work
const zoom = () => graph.zoomBy(1.5, { maxZoom: 4 });
const pan = () => {
  const camera = graph.getCamera();
  graph.setCamera({ x: camera.x + 80 });
};
const center = () => graph.fitCenter();
const fit = () => graph.fitView({ padding: [70, 50, 110, 50], maxZoom: 1 });
const reset = () => graph.resetCamera();

fitView parameters · fitCenter parameters

Why is the graph still small after fitting?

Check for distant nodes, far-reaching edges or Combos, then inspect padding and maxZoom. The example caps maxZoom at 1 to avoid over-enlarging a small graph. fitCenter only centers; use zoomTo or zoomBy to zoom in explicitly.

Refresh data with or without fitting

Zoom with the toolbar or drag empty canvas, then choose Reload + keep view. B moves from x=240 to x=800 while the camera stays unchanged; B may leave the viewport. Use Reset example, then Reload + fit to compare: the updated content fits into view.

Loading example…
Zoom or pan, then compare reloads. B alternates between x=240 / 800. Keep view preserves the camera; Fit refits. Reset restores the initial data
await graph.setData(data(next), {
  fitView: keepView ? false : fit,
});

Use fitView: false to keep the view; no camera save-and-restore is needed. New coordinates, layouts, and states still apply. Keeping the camera does not guarantee that a node stays at the same screen position. See preserving selection separately.

Omitting the second setData argument uses fitView(0.9); it does not inherit the initial autoFit padding. Pass a fit options object to this setData call, as in the example, to reuse your padding.

Asynchronous refresh and saved views

The example disables buttons during an update. For concurrent application requests, use a request sequence or cancellation to apply only the latest result. Check graph.destroyed after asynchronous work.

To restore a view across pages, save the getCamera() snapshot and call setCamera(saved) after the new instance's await render(). The camera records translation and zoom only; a different container size or different graph positions may show a different area. Calling fitView immediately afterward overwrites the restored camera.

Handle resizing and completed layouts

Configure autoFit at initialization to keep all content visible after panel resizing. Keep false (the default) to retain the user's zoom and pan during exploration. Graph uses ResizeObserver to synchronize container dimensions; neither policy requires recreating the instance.

Zoom first, then switch Width 65% / 100% below. Only container CSS width changes. Inspect the final zoom and camera after resize; the complete source includes the listener and cleanup.

Loading example…
Zoom first, then choose Width 65% / 100%. The dashed outline marks the container. ResizeObserver updates its size and autoFit refits. Reset restores the original width
autoFit: { padding: [84, 40, 100, 40], maxZoom: 1 },

The container needs nonzero width and height. To reset the view when revealing a hidden tab, explicitly fitView after the container reaches its final size. The resize event follows any automatic fitting.

After await graph.layout(), either call graph.fitView({ padding: 32, maxZoom: 1 }) or retain the current camera. Layout computes node positions; fitting is explicit. See layout methods for asynchronous cancellation.

Convert coordinates to position DOM content

Use screenToGraph and graphToScreen to convert between graph and client coordinates. Watch A in the canvas above to compare the three coordinate spaces. Zooming or panning changes the canvas position. Scrolling the page changes the client position.

CoordinatesOriginCommon use
graphThe graph's own coordinate systemStore node positions, run layouts, create graph elements
canvasCanvas top-left, CSS pixelsPosition auxiliary content inside the canvas container
clientBrowser viewport top-left, CSS pixelsMatch mouse clientX / clientY, place fixed menus

Convert DOM mouse events using clientX / clientY. Element events already supply event.graph, event.canvas, and event.client. Fixed menus use client coordinates. Absolutely positioned content inside a canvas container without borders or padding uses CSS coordinates relative to that container.

import type { Graph } from '@antv/g6-lite';

export function pointAtMouse(graph: Graph, event: MouseEvent) {
  return graph.screenToGraph(event.clientX, event.clientY);
}

// marker is mounted on document.body; point is in graph coordinates
export function placeMarker(graph: Graph, marker: HTMLElement, point: { x: number; y: number }) {
  const client = graph.graphToScreen(point.x, point.y);
  Object.assign(marker.style, {
    position: 'fixed', left: `${client.x}px`, top: `${client.y}px`,
  });
}

Reproject the anchor after zooming, panning, or page scrolling; close menus that should not follow. Do not multiply by DPR. screenToGraph does not take offsetX / offsetY or screenX / screenY.

Common questions

Should I save new node positions after panning or zooming?

These operations did not move nodes. Read getCamera to save the user's view, or element positions to save the layout; handle them separately.

Why does a menu drift as I zoom?

Check for graph coordinates used directly as CSS positions, or canvas positions treated as client. Choose coordinates according to where the menu is mounted.

Why does centered content still not fit?

fitCenter changes position only. Use fitView to adjust zoom too, and check padding and zoom bounds.

Why does refreshing move the view with autoFit disabled?

Check that setData receives fitView: false and that application code does not call fitView afterward. Disabling autoFit prevents automatic fitting on container resize; data replacement has its own fitting policy.

Why do method and wheel zoom limits differ?

minZoom and maxZoom on zoomTo / zoomBy constrain that call only. Wheel limits belong to the zoom-canvas Behavior, and fitView limits are separate again. Set each when consistent limits are required. See wheel zoom options.

Continue with viewport methods, autoFit, setData, and element event coordinates.

Related runnable examples