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


    一、介绍

    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? ... @/*
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • sigma.js安装

    需要安装两个核心库:sigmagraphology

    • Sigma: 它支持多种布局算法,并允许用户通过鼠标和触摸来交互网络。提供丰富的API和配置选项,使得网络图的绘制和定制变得相对简单。
    • Graphology 是一个简单、高效且灵活的图形数据结构库,它支持节点和边的添加、删除和查询操作,并提供了许多用于分析图形结构的实用方法。GraphologySigma.js 常常一起使用,因为 Sigma.js 可以使用 Graphology 作为其后端图形数据结构。
    npm install sigma graphology
    
    • 1
    • package.json配置
    "dependencies": {
       "graphology": "^0.25.4",
       "next": "14.2.2",
       "react": "^18",
       "react-dom": "^18",
       "sigma": "^3.0.0-beta.17"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    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>
        );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    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
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    三、实际执行流程

    上面看着是不是好像挺复杂,其实只做了以下几个事情:

    • 假定容器
    <div id="graphContainer">div>
    
    • 1
    • 模拟数据
    // 示例:节点 数据
    const nodes = [
      { 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 = [
      { source: "1", target: "2", size: 5, color: "purple" },
    ];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 视图渲染
    import Graph from "graphology";
    import Sigma from "sigma";
    
    const graphContainer = document.getElementById('graphContainer')
    
    // 设置默认 sigma 库配置
    const sigmaSettings = {};
    
    // 实例化 Graph 库(既Graphology图形数据结构库)
    const graphInstance = new Graph();
    
    // 添加 节点 数据
    nodes.forEach((node)=>{
        graphInstance.addNode(node.id, node);
    });
    
    // 添加 边 数据(也就是节点之间的关系)
    edges.forEach((edge)=>{
        graphInstance.addEdge(edge.source, edge.target, edge);
    });
    
    // 实例化 Sigma 库,传入
    const sigmaInstance = new Sigma(graph, graphContainer, sigmaSettings);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 相关阅读:
    css实现的动态导航菜单,倾斜放置,鼠标悬停回正html前端源码
    WCF异常System.ServiceModel.ProtocolException问题处理
    ubuntu20.04.5 LTS搭建高可用k3s集群
    Linux内存管理——段页式访问
    浅谈以驱动为中心的运维架构
    模拟实现Hash-Table(线性探测)
    Vue2面试题100问
    【Proteus仿真】【Arduino单片机】OLED液晶显示
    IntelliJ IDEA 如何设置类注释和方法注释
    frxJSON用法
  • 原文地址:https://blog.csdn.net/u011159821/article/details/137981982