【React】Sigma.js框架网络图-入门篇

发布于:2024-04-24 ⋅ 阅读:(22) ⋅ 点赞:(0)

一、介绍

Sigma.js是一个专门用于图形绘制的JavaScript库 它使在Web页面上发布网络变得容易,并允许开发人员将网络探索集成到丰富的Web应用程序中。
Sigma.js提供了许多内置功能,例如CanvasWebGL渲染器或鼠标和触摸支持,以使用户在网页上的网络操作流畅且快速。
通过使用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安装

需要安装两个核心库:sigmagraphology

  • Sigma: 它支持多种布局算法,并允许用户通过鼠标和触摸来交互网络。提供丰富的API和配置选项,使得网络图的绘制和定制变得相对简单。
  • Graphology 是一个简单、高效且灵活的图形数据结构库,它支持节点和边的添加、删除和查询操作,并提供了许多用于分析图形结构的实用方法。GraphologySigma.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;