Front‑End Graph Visualization with AntV G6 and Graphin: Concepts, Data Structures, Algorithms, and Custom Development
This article introduces front‑end graph visualization using AntV G6 and Graphin, explains graph models and JSON data structures, covers traversal, shortest‑path and clustering algorithms, compares G6 and Graphin, and provides detailed TypeScript and React code for custom extensions, event handling, and full‑screen support.
As business data becomes increasingly complex, a user‑friendly front‑end graph visualization product is needed; this article walks through how to develop such visualizations (excluding tree graphs) using AntV G6.
A graph model consists of nodes (objects) and edges (relationships); nodes can carry attributes, edges may be directed or undirected, and graph traversal enables queries and analysis.
In AntV G6, graph data is defined with JSON. An example structure includes a nodes array and an edges array, each element specifying id , label , and connection information.
{
"nodes": [
{"id": "node1", "label": "Node 1"},
{"id": "node2", "label": "Node 2"}
],
"edges": [
{"source": "node1", "target": "node2", "label": "Edge 1"}
]
}Typical graph algorithms are introduced. Depth‑First Search (DFS) explores a path as deep as possible before backtracking, while Breadth‑First Search (BFS) expands layer by layer. A TypeScript implementation of DFS is provided.
class Graph {
adjacencyList: Map
;
constructor() { this.adjacencyList = new Map(); }
addVertex(vertex: number): void { if (!this.adjacencyList.has(vertex)) this.adjacencyList.set(vertex, []); }
addEdge(v1: number, v2: number): void { if (this.adjacencyList.has(v1) && this.adjacencyList.has(v2)) { this.adjacencyList.get(v1)?.push(v2); this.adjacencyList.get(v2)?.push(v1); } }
dfs(startVertex: number): number[] {
const visited: number[] = [];
const stack: number[] = [];
stack.push(startVertex);
while (stack.length > 0) {
const currentVertex = stack.pop()!;
if (!visited.includes(currentVertex)) {
visited.push(currentVertex);
const neighbors = this.adjacencyList.get(currentVertex);
if (neighbors) {
for (let neighbor of neighbors) { stack.push(neighbor); }
}
}
}
return visited;
}
}
const graph = new Graph();
graph.addVertex(1); graph.addVertex(2); graph.addVertex(3); graph.addVertex(4);
graph.addEdge(1, 2); graph.addEdge(2, 3); graph.addEdge(3, 4);
const traversalResult = graph.dfs(1);
console.log(traversalResult); // [1, 2, 3, 4]Other algorithms such as Dijkstra’s shortest‑path and spectral clustering are briefly mentioned for routing, navigation, and data segmentation use cases.
Typical business scenarios for graph data include social‑network analysis, financial risk detection, logistics route optimization, and knowledge‑graph‑driven search.
For front‑end implementation, the article compares AntV G6 (WebGL‑based, flexible plugin system) with Graphin (React wrapper over G6 offering easier development). The choice depends on the need for low‑level engine control versus rapid React integration.
const graph = new G6.Graph({
container: 'mountNode',
width: 1000,
height: 600,
layout: { type: 'random', width: 300, height: 300 }
}); import React from 'react';
import Graphin, { Utils, GraphinContext } from '@antv/graphin';
const data = Utils.mock(10).circle().graphin();
const Demo = () => (
);
export default Demo;Custom Graphin development is illustrated with a component hierarchy that includes context providers, initialization logic, hover handling, relation activation, tooltips, toolbar, and behavior components. The InitRender component sets initial zoom, focuses the root node, and collapses secondary nodes using a DFS helper.
import React, { useContext, useEffect } from 'react';
import { GraphinContext } from '@antv/graphin';
import { Context } from '../views/atlas';
import { dfsSecondChildrenAlllHide } from './dfs';
const InitRender = props => {
const { graph, apis } = useContext(GraphinContext);
const { AtlasData } = useContext(Context);
useEffect(() => {
apis.focusNodeById('0');
dfsSecondChildrenAlllHide(graph, AtlasData);
graph.setMaxZoom(1.5);
graph.setMinZoom(0.5);
graph.zoomTo(1);
graph?.fitCenter(true);
return () => {};
}, []);
return null;
};
export default InitRender;Utility functions for node label truncation and line‑break insertion are provided to keep text within node dimensions.
export const strInsert = (str: string, size, insertStr: string): string => {
const { enterLen, maxLen } = size;
const strLen = str.length;
if (strLen < maxLen) {
const allSpaceLen = maxLen - strLen;
const averageSpaceLen = Math.floor((maxLen - strLen) / 2);
const beforSpaceLen = Math.floor(averageSpaceLen / enterLen) * enterLen || averageSpaceLen;
const afterSpaceLen = allSpaceLen - beforSpaceLen;
str = `${str}`;
} else if (strLen > maxLen) {
str = str.slice(0, maxLen - size.enterLen) + cutNodeLabelPoint;
}
let newStr = '';
let countLen = 0;
for (let i = 0; i < str.length; i++) {
if (countLen === enterLen) {
newStr += `${insertStr}${str[i]}`;
countLen = 1;
} else {
newStr += str[i];
countLen++;
}
}
return newStr;
};
export const cutNodeLabelPoint = '...';A full‑screen utility abstracts browser‑specific prefixes, offering beFull , exitFull , isFull , and toggleFull functions for any element.
type RFSMethodName = 'webkitRequestFullScreen' | 'requestFullscreen' | 'msRequestFullscreen' | 'mozRequestFullScreen';
// ...prefix detection logic omitted for brevity
export function beFull(el?: HTMLElement, backgroundColor?: string): Promise
{
// apply optional background style then request fullscreen
return getCurrentElement(el)[TYPE_REQUEST_FULL_SCREEN]();
}
export function exitFull(): Promise
{ return document[TYPE_EXIT_FULL_SCREEN](); }
export function isFull(el?: HTMLElement): boolean { return getCurrentElement(el) === document[TYPE_FULL_SCREEN_ELEMENT]; }
export function toggleFull(el?: HTMLElement, backgroundColor?: string): boolean {
if (isFull(el)) { exitFull(); return false; } else { beFull(el, backgroundColor); return true; }
}Overall, the article provides a comprehensive guide to building, customizing, and deploying interactive graph visualizations on the front end, covering theory, data modeling, algorithmic foundations, library selection, and practical code examples.
政采云技术
ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.