一、介绍
Sigma.js
是一个专门用于图形绘制的JavaScript库
。 它使在Web页面上发布网络变得容易,并允许开发人员将网络探索集成到丰富的Web应用程序中。
Sigma.js
提供了许多内置功能,例如Canvas
和WebGL
渲染器或鼠标和触摸支持,以使用户在网页上的网络操作流畅且快速。
通过使用Sigma.js
,用户可以方便地创建和展示网络图,从而更好地理解和分析数据之间的关系。
二、实战
1、环境&目录结构
Next.js
初始化
# npx create-next-app@latest
# ...
√ What is your project named? ... graph-sigma
√ Would you like to use TypeScript? ... Yes
√ Would you like to use ESLint? ... No
√ Would you like to use Tailwind CSS? ... No
√ Would you like to use `src/` directory? ... Yes
√ Would you like to use App Router? (recommended) ... Yes
√ Would you like to customize the default import alias (@/*)? ... Yes
√ What import alias would you like configured? ... @/*
sigma.js
安装
需要安装两个核心库:
sigma
、graphology
Sigma
: 它支持多种布局算法,并允许用户通过鼠标和触摸来交互网络。提供丰富的API和配置选项,使得网络图的绘制和定制变得相对简单。Graphology
是一个简单、高效且灵活的图形数据结构库,它支持节点和边的添加、删除和查询操作,并提供了许多用于分析图形结构的实用方法。Graphology
与Sigma.js
常常一起使用,因为Sigma.js
可以使用Graphology
作为其后端图形数据结构。
npm install sigma graphology
package.json
配置
"dependencies": {
"graphology": "^0.25.4",
"next": "14.2.2",
"react": "^18",
"react-dom": "^18",
"sigma": "^3.0.0-beta.17"
}
2、sigma组件使用示例
import type {Node, Edge} from "@/component/SigmaGraph/types.d";
import SigmaGraph from "@/component/SigmaGraph";
import SigmaGraphData from "@/component/SigmaGraph/SigmaGraphData";
export default function Home() {
// 示例:节点 数据
const nodes:Node[] = [
{id: "1", label: "Node 1", x: 0, y: 0, size: 10, color: "blue" },
{id: "2", label: "Node 2", x: 1, y: 1, size: 20, color: "red" },
];
// 示例:边 数据
const edges:Edge[] = [
{source: "1", target: "2", size: 5, color: "purple"}
];
return (
<div style={{width: '50vw', height: '50vh', backgroundColor: "#eee"}}>
<SigmaGraph>
<SigmaGraphData nodes={nodes} edges={edges}/>
</SigmaGraph>
</div>
);
}
3、创建sigma组件
在
next.js
中,切记sigma.js
的一切代码只能在客户端模式
下进行
在根目录的component
目录创建一个SigmaGraph
目录和其他准备文件
types.d.ts
声明文件
// 节点(Node)、边(Edge)数据结构声明
export type Node = {
id: string,
[key: string]: any
}
export type Edge = {
source: string,
target: string,
[key: string]: any
}
index.tsx
父组件
"use client";
import type {Attributes} from "graphology-types";
import type {Settings} from "sigma/settings";
import React, {useEffect, useRef, useState, createContext, useContext, useMemo} from "react";
import Graph from "graphology";
import Sigma from "sigma";
// 声明组件可传参数
type SigmaGraphProps = {
children?: React.ReactNode,
settings?: Partial<Settings>
}
// 创建 SigmaGraph 上下文
export const SigmaGraphContext = createContext<Sigma<Attributes, Attributes, Attributes>|null>(null);
// 定义div容器基本样式(一定要有宽高设定)
const containerStyle: React.CSSProperties = {
width: '100%',
height: '100%'
}
let graph: Graph | null = new Graph;
const SigmaGraph = function ({children, settings}: SigmaGraphProps) {
const containerRef = useRef<HTMLDivElement>(null);
const [sigma, setSigma] = useState<any>(null);
// 默认配置
const sigmaSettings: Partial<Settings> = useMemo(() => (Object.assign({}, {
allowInvalidContainer: true,
}, settings || {})), [settings])
//
useEffect(() => {
if (typeof window !== 'undefined' && containerRef.current) {
const sigmaInstance = new Sigma(graph, containerRef.current, sigmaSettings);
// 为上下文操作准备 graph 和 sigma 实例
setSigma(sigmaInstance);
}
}, []);
//
return (
<SigmaGraphContext.Provider value={sigma}>
<div ref={containerRef} style={containerStyle}>
{children}
</div>
</SigmaGraphContext.Provider>
)
}
// 导出 sigma hook
export const useSigma = () => useContext(SigmaGraphContext);
// 导出 graph hook
export const useGraph = () => graph;
export default SigmaGraph;
SigmaGraphData.tsx
子组件:用于数据更新、维护
"use client";
import type {Node, Edge} from "./types.d";
import {useSigma, useGraph} from "./index"
import React, {useEffect} from "react";
// 声明组件可传参数
type SigmaDataProps = {
nodes: Node[],
edges: Edge[],
}
const SigmaGraphData = function ({nodes, edges}:SigmaDataProps) {
// 挂载 sigma、graph
const sigma = useSigma();
const graph = useGraph();
useEffect(() => {
if (!sigma || !graph)return;
// 清空原有数据
graph.clear();
// 添加 节点 数据
nodes.forEach((node: Node)=>{
graph.addNode(node.id, node);
});
// 添加 边 数据(也就是节点之间的关系)
edges.forEach((edge: Edge)=>{
graph.addEdge(edge.source, edge.target, edge);
});
sigma.refresh();
// 组件销毁时 清空
return () => graph.clear();
}, [graph,sigma, nodes, edges]);
return <></>
}
export default SigmaGraphData;