G6(六)为图应用插件及工具

为辅助用户在图上探索,G6 提供了一些辅助工具,其中一部分是插件工具,另一部分是交互工具。

本文将为 图 添加缩略图插件网格插件节点提示框边提示框

插件

使用插件时,有三个步骤:

  • Step 1: 引入插件;
  • Step 2: 实例化插件;
  • Step 3: 在实例化图时将插件的实例配置到图上。

Minimap

缩略图 (Minimap) 是一种常见的用于快速预览和探索图的工具,可作为导航辅助用户探索大规模图。

现在,我们配置一个 Minimap:

目标效果

使用方式

js 复制代码
// 实例化 minimap 插件
const minimap = new G6.Minimap({
  size: [100, 100],// Minimap 的大小
  className: 'minimap',
  type: 'delegate',// 只渲染图上元素的大致图形
});

// 实例化图
const graph = new G6.Graph({
  // ...                           // 其他配置项
  plugins: [minimap], // 将 minimap 实例配置到图上
});

Grid 网格

网格可用于辅助用户在拖拽节点时对齐到网格。

目标效果

使用方式

js 复制代码
// const minimap = ...

// 实例化 grid 插件
const grid = new G6.Grid();

// 实例化图
const graph = new G6.Graph({
  // ...                        // 其他配置项
  plugins: [minimap, grid], // 将 grid 实例配置到图上
});

交互工具

交互工具是指配置到图上交互模式中的工具。使用交互工具时,有两个步骤:

  • Step 1: 在实例化图时配置 modes;
  • Step 2: 为交互工具定义样式。

tooltip 节点提示框

节点提示框可以用在节点的详细信息的展示。当鼠标滑过节点时,显示一个浮层告知节点的详细信息。

目标效果

使用方式

实例化图时配置 'tooltip' 到 modes 中:

js 复制代码
const graph = new G6.Graph({ 
    modes: { 
        default: [ 
            // ... 
            { 
                type: 'tooltip', // 提示框 
                formatText(model) { // 提示框文本内容 
                    const text = 'label: ' + model.label + '<br/> class: ' + model.class; return text; 
                }, 
             }, 
        ], 
    }, 
});

由于 tooltip 实际上是一个悬浮的 <div> 标签,因此可在 CSS 中设置样式。下面展示在 CSS 中设置样式:

css 复制代码
  /* 提示框的样式 */
  .g6-tooltip {
      border: 1px solid #e2e2e2;
      border-radius: 4px;
      font-size: 12px;
      color: #545454;
      background-color: rgba(255, 255, 255, 0.9);
      padding: 10px 8px;
      box-shadow: rgb(174, 174, 174) 0px 0px 10px;
   }

edge-tooltip 边提示框

边提示框可以用在边的详细信息的展示。当鼠标滑过边时,显示一个浮层告知边的详细信息。

目标效果

使用方式

js 复制代码
const graph = new G6.Graph({
  modes: {
    default: [
      // ...
      {
        type: 'tooltip', // 节点提示框
        // ...
      },
      {
        type: 'edge-tooltip', // 边提示框
        formatText(model) {
          // 边提示框文本内容
          const text =
            'source: ' +
            model.source +
            '<br/> target: ' +
            model.target +
            '<br/> weight: ' +
            model.weight;
          return text;
        },
      },
    ],
  },
});

与 tooltip 相同,edge-tooltip 是一个悬浮的 <div> 标签,可以使用与 tooltip 相同的方法设置其悬浮框的样式。

效果代码

css 复制代码
.plugin-container .g6-tooltip {
    border: 1px solid #e2e2e2;
    border-radius: 4px;
    font-size: 12px;
    color: #545454;
    background-color: rgba(255, 255, 255, 0.9);
    padding: 10px 8px;
    box-shadow: rgb(174, 174, 174) 0px 0px 10px;
}
js 复制代码
import { useRef, useEffect } from "react";
import G6 from "@antv/g6";
import "./index.css";

const PluginAndUtils = () => {
    const containerRef = useRef(null);
    const graphRef = useRef();
    useEffect(() => {
        if (graphRef.current || !containerRef.current) return;
        // 实例化 minimap 插件
        const minimap = new G6.Minimap({
            size: [100, 100], // Minimap 的大小
            className: "minimap",
            type: "delegate", // 只渲染图上元素的大致图形
        });
        // 实例化 grid 插件
        const grid = new G6.Grid();

        const graph = new G6.Graph({
            container: containerRef.current, // String | HTMLElement,必须,在 Step 1 中创建的容器 id 或容器本身
            width: 800, // Number,必须,图的宽度
            height: 600, // Number,必须,图的高度
            // 布局配置项
            layout: {
                // Object,可选,布局的方法及其配置项,默认为 random 布局。
                type: "force", // 指定为力导向布局
                preventOverlap: true, // 防止节点重叠
                // nodeSize: 40        // 节点大小,用于算法中防止节点重叠时的碰撞检测。由于已经在上一节的元素配置中设置了每个节点的 size 属性,则不需要在此设置 nodeSize。
                linkDistance: 150, // 指定边距离为150
            },
            // 设置画布的交互模式
            modes: {
                default: [
                    "drag-canvas",
                    "zoom-canvas",
                    "drag-node",
                    {
                        type: "tooltip", // 提示框
                        formatText(model) {
                            // 提示框文本内容
                            const text =
                                "label: " +
                                model.label +
                                "<br/> class: " +
                                model.class;
                            return text;
                        },
                    },
                    {
                        type: "edge-tooltip", // 边提示框
                        formatText(model) {
                            // 边提示框文本内容
                            const text =
                                "source: " +
                                model.source +
                                "<br/> target: " +
                                model.target +
                                "<br/> weight: " +
                                model.weight;
                            return text;
                        },
                    },
                ], // 允许拖拽画布、放缩画布、拖拽节点
            },
            plugins: [minimap, grid], // 将 minimap 实例配置到图上
            // 节点在默认状态下的样式配置(style)和其他配置
            defaultNode: {
                size: 40, //节点的大小
                // 节点样式配置
                style: {
                    fill: "steelblue", // 节点填充色
                    stroke: "#666", // 节点描边色
                    lineWidth: 1, // 节点描边粗细
                },
                // 节点上的标签文本配置
                labelCfg: {
                    // 节点上的标签文本样式配置
                    style: {
                        fill: "#fff", // 节点标签文字颜色
                    },
                },
            },
            // 边在默认状态下的样式配置(style)和其他配置
            defaultEdge: {
                // 边上的标签文本配置
                labelCfg: {
                    autoRotate: true, // 边上的标签文本根据边的方向旋转
                },
            },
            // 节点不同状态下的样式集合
            nodeStateStyles: {
                // 鼠标 hover 上节点,即 hover 状态为 true 时的样式
                hover: {
                    fill: "lightsteelblue",
                },
                // 鼠标点击节点,即 click 状态为 true 时的样式
                click: {
                    stroke: "#000",
                    lineWidth: 3,
                },
            },
            // 边不同状态下的样式集合
            edgeStateStyles: {
                // 鼠标点击边,即 click 状态为 true 时的样式
                click: {
                    stroke: "steelblue",
                },
            },
        });

        onLoadData((data) => {
            graph.data(data); // 绑定数据
            graph.render(); // 渲染图
            graphRef.current = graph;

            // 鼠标进入节点
            graph.on("node:mouseenter", (e) => {
                const nodeItem = e.item; // 获取鼠标进入的节点元素对象
                graph.setItemState(nodeItem, "hover", true); // 设置当前节点的 hover 状态为 true
            });
            // 鼠标离开节点
            graph.on("node:mouseleave", (e) => {
                const nodeItem = e.item; // 获取鼠标离开的节点元素对象
                graph.setItemState(nodeItem, "hover", false); // 设置当前节点的 hover 状态为 false
            });

            // 点击节点
            graph.on("node:click", (e) => {
                // 先将所有当前是 click 状态的节点置为非 click 状态
                const clickNodes = graph.findAllByState("node", "click");
                clickNodes.forEach((cn) => {
                    graph.setItemState(cn, "click", false);
                });
                const nodeItem = e.item; // 获取被点击的节点元素对象
                graph.setItemState(nodeItem, "click", true); // 设置当前节点的 click 状态为 true
            });

            // 点击边
            graph.on("edge:click", (e) => {
                // 先将所有当前是 click 状态的边置为非 click 状态
                const clickEdges = graph.findAllByState("edge", "click");
                clickEdges.forEach((ce) => {
                    graph.setItemState(ce, "click", false);
                });
                const edgeItem = e.item; // 获取被点击的边元素对象
                graph.setItemState(edgeItem, "click", true); // 设置当前边的 click 状态为 true
            });
        });
    }, []);

    const onLoadData = async (callback) => {
        const response = await fetch(
            "https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json"
        );
        const remoteData = await response.json();
        const nodes = remoteData.nodes;
        nodes.forEach((node) => {
            if (!node.style) {
                node.style = {};
            }
            // 根据节点数据中的 class 属性配置图形
            switch (node.class) {
                case "c0": {
                    node.type = "circle"; // class = 'c0' 时节点图形为 circle
                    break;
                }
                case "c1": {
                    node.type = "rect"; // class = 'c1' 时节点图形为 rect
                    node.size = [35, 20]; // class = 'c1' 时节点大小
                    break;
                }
                case "c2": {
                    node.type = "ellipse"; // class = 'c2' 时节点图形为 ellipse
                    node.size = [35, 20]; // class = 'c2' 时节点大小
                    break;
                }
            }
        });
        const edges = remoteData.edges;
        edges.forEach((edge) => {
            if (!edge.style) {
                edge.style = {};
            }
            edge.style.lineWidth = edge.weight; // 边的粗细映射边数据中的 weight 属性数值
            // 移到此处
            edge.style.opacity = 0.6;
            edge.style.stroke = "grey";
        });
        callback(remoteData);
    };

    return (
        <div
            className="plugin-container"
            ref={containerRef}
            style={{ border: "2px solid #000", display: "inline-block" }}
        ></div>
    );
};

export default PluginAndUtils;
相关推荐
蛋蛋_dandan1 天前
Fabric.js从0到1实现图片框选功能
canvas
wayhome在哪3 天前
用 fabric.js 搞定电子签名拖拽合成图片
javascript·产品·canvas
德育处主任3 天前
p5.js 掌握圆锥体 cone
前端·数据可视化·canvas
德育处主任4 天前
p5.js 3D 形状 "预制工厂"——buildGeometry ()
前端·javascript·canvas
德育处主任6 天前
p5.js 3D盒子的基础用法
前端·数据可视化·canvas
掘金安东尼6 天前
2分钟创建一个“不依赖任何外部库”的粒子动画背景
前端·面试·canvas
百万蹄蹄向前冲7 天前
让AI写2D格斗游戏,坏了我成测试了
前端·canvas·trae
用户2519162427119 天前
Canvas之画图板
前端·javascript·canvas
FogLetter12 天前
玩转Canvas:从静态图像到动态动画的奇妙之旅
前端·canvas
用户25191624271113 天前
Canvas之贪吃蛇
前端·javascript·canvas