Zoom, Pan and Export

ApexTree supports interactive zoom and pan, a built-in toolbar, and SVG export. All of it can be driven programmatically through the graph returned by render().

Interactive zoom and pan

enableZoomPan (on by default) enables Ctrl/⌘ + mouse-wheel (or trackpad pinch) zoom and drag-to-pan. A plain wheel without a modifier still scrolls the page, so the chart doesn't hijack scrolling inside a longer page:

const tree = new ApexTree(document.getElementById('chart'), {
  enableZoomPan: true,   // default
})
tree.render(data)

Set enableZoomPan: false to lock the viewport — useful when embedding the tree in a scrollable page where you don't want zoom interactions at all.

Built-in toolbar

enableToolbar shows a zoom/pan/export toolbar inside the container. It also hosts the search input when enableSearch is on:

const tree = new ApexTree(el, {
  enableToolbar: true,
  enableSearch: true,
})
tree.render(data)

Programmatic zoom

The graph returned by render() exposes zoom and fit methods:

MethodDescription
zoom(zoomFactor)Zoom by a numeric factor (e.g. 1.2 in, 0.8 out)
fitScreen()Fit the entire tree within the viewport
centerOnNode(nodeId)Center the camera on a node at the current zoom
const graph = tree.render(data)

document.getElementById('zoom-in').onclick  = () => graph.zoom(1.2)
document.getElementById('zoom-out').onclick = () => graph.zoom(0.8)
document.getElementById('fit').onclick      = () => graph.fitScreen()
document.getElementById('focus-root').onclick = () => graph.centerOnNode(graph.getRootNodeId())

centerOnNode animates when enableAnimation is on and snaps otherwise.

Viewport padding

paddingX and paddingY control the breathing room between the outermost nodes and the viewBox edge, which also affects how fitScreen() frames the tree:

const tree = new ApexTree(el, {
  paddingX: 120,
  paddingY: 120,
})

Internal viewport

viewPortWidth and viewPortHeight set the internal SVG coordinate space (defaults 800 × 600). Adjust when a very large tree needs a different internal resolution before scaling to the canvas.

Export to SVG

exportToSvg() downloads the current tree as an SVG file. The built-in toolbar includes an export button when enableToolbar is on; call the method directly to wire your own trigger:

const tree = new ApexTree(el, { enableToolbar: false })
const graph = tree.render(data)

document.getElementById('export').addEventListener('click', () => {
  graph.exportToSvg()
})

Complete example

const tree = new ApexTree(document.getElementById('chart'), {
  enableZoomPan: true,
  enableToolbar: true,
  paddingX: 100,
  paddingY: 100,
})

const graph = tree.render(data)

const controls = {
  'zoom-in':  () => graph.zoom(1.2),
  'zoom-out': () => graph.zoom(0.8),
  'fit':      () => graph.fitScreen(),
  'export':   () => graph.exportToSvg(),
}
Object.entries(controls).forEach(([id, fn]) => {
  document.getElementById(id).addEventListener('click', fn)
})

React example

import { useRef } from 'react'
import { ApexTreeChart } from 'react-apextree'
import type { ApexTreeRef } from 'react-apextree'

export default function ZoomableTree() {
  const ref = useRef<ApexTreeRef>(null)

  return (
    <div>
      <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>
        <button onClick={() => ref.current?.getGraph()?.zoom(1.2)}>Zoom in</button>
        <button onClick={() => ref.current?.getGraph()?.zoom(0.8)}>Zoom out</button>
        <button onClick={() => ref.current?.fitScreen()}>Fit</button>
        <button onClick={() => ref.current?.getGraph()?.exportToSvg()}>Export</button>
      </div>
      <ApexTreeChart
        ref={ref}
        data={data}
        options={{ enableZoomPan: true }}
      />
    </div>
  )
}

fitScreen() is available directly on the ref handle; zoom() and exportToSvg() are reached via getGraph().