A graph visualization library that combines the best of both worlds:
- Canvas for high performance when viewing the full graph
- HTML/React for rich interactions when zoomed in
No more choosing between performance and interactivity. Perfect for large diagrams, flowcharts, and node-based editors.
Modern web applications often require complex visualization and interactivity, but existing solutions typically focus on a single rendering technology:
- Canvas offers high performance for complex graphics but is limited in text handling and interactivity.
- HTML DOM is convenient for interfaces but less efficient for complex graphics or large numbers of elements.
@gravity-ui/graph solves this by automatically switching between Canvas and HTML based on zoom level:
- Zoomed Out: Uses Canvas for efficient rendering of the full graph
- Medium Zoom: Shows schematic view with basic interactivity
- Zoomed In: Switches to HTML/React components for rich interactions
The library uses a smart rendering system that automatically manages the transition between Canvas and React components:
- At low zoom levels, everything is rendered on Canvas for performance
- When zooming in to detailed view, the
BlocksList
component:- Tracks camera viewport and scale changes
- Calculates which blocks are visible in the current viewport (with padding for smooth scrolling)
- Renders React components only for visible blocks
- Automatically updates the list when scrolling or zooming
- Removes React components when zooming out
// Example of React components rendering
const MyGraph = () => {
return (
<GraphCanvas
graph={graph}
renderBlock={(graph, block) => (
<MyCustomBlockComponent
graph={graph}
block={block}
/>
)}
/>
);
};
npm install @gravity-ui/graph
Detailed React Components Documentation
import { GraphCanvas, GraphState, GraphBlock, useGraph } from "@gravity-ui/graph";
import React from "react";
const config = {};
export function GraphEditor() {
const { graph, setEntities, start } = useGraph(config);
useEffect(() => {
setEntities({
blocks: [
{
is: "block-action",
id: "action_1",
x: -100,
y: -450,
width: 126,
height: 126,
selected: true,
name: "Block #1",
anchors: [],
},
{
id: "action_2",
is: "block-action",
x: 253,
y: 176,
width: 126,
height: 126,
selected: false,
name: "Block #2",
anchors: [],
}
],
connections: [
{
sourceBlockId: "action_1",
targetBlockId: "action_2",
}
]
});
}, [setEntities]);
const renderBlockFn = (graph, block) => {
return <GraphBlock graph={graph} block={block}>{block.id}</GraphBlock>;
};
return (
<GraphCanvas
graph={graph}
renderBlock={renderBlockFn}
onStateChanged={({ state }) => {
if (state === GraphState.ATTACHED) {
start();
graph.zoomTo("center", { padding: 300 });
}
}}
/>
);
}
import { Graph } from "@gravity-ui/graph";
// Create container element
const container = document.createElement('div');
container.style.width = '100vw';
container.style.height = '100vh';
container.style.overflow = 'hidden';
document.body.appendChild(container);
// Initialize graph with configuration
const graph = new Graph({
configurationName: "example",
blocks: [],
connections: [],
settings: {
canDragCamera: true,
canZoomCamera: true,
useBezierConnections: true,
showConnectionArrows: true
}
}, container);
// Add blocks and connections
graph.setEntities({
blocks: [
{
is: "block-action",
id: "block1",
x: 100,
y: 100,
width: 120,
height: 120,
name: "Block #1"
},
{
is: "block-action",
id: "block2",
x: 300,
y: 300,
width: 120,
height: 120,
name: "Block #2"
}
],
connections: [
{
sourceBlockId: "block1",
targetBlockId: "block2"
}
]
});
// Start rendering
graph.start();
// Center the view
graph.zoomTo("center", { padding: 100 });
-
System
-
Components
-
Rendering
-
Blocks and Connections