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;
相关推荐
webmote17 小时前
做一个FabricJS.cc的中文文档网站——面向markdown编程
canvas·fabric·使用手册·中文·fabricjs
小黄人软件7 天前
【AI协作】让所有用电脑的场景都能在ChatGPT里完成。Canvas :新一代可视化交互,让AI易用易得
人工智能·chatgpt·canvas
柳晓黑胡椒10 天前
cesiusm实现 多图例展示+点聚合(base64图标)
css3·canvas·base64·cesium·animation
余生H17 天前
即时可玩web小游戏(二):打砖块(支持移动端版) - 集成InsCode快来阅读并即时体验吧~
前端·javascript·inscode·canvas·h5游戏
普兰店拉马努金25 天前
【Canvas与图标】牛皮纸文件袋图标
canvas·图标·文件袋·牛皮纸
德育处主任1 个月前
前端啊,拿Lottie炫个动画吧
前端·svg·canvas
GDAL1 个月前
深入剖析Canvas的getBoundingClientRect:精准定位与交互事件实现
canvas
剑亦未配妥1 个月前
使用js和canvas、html实现简单的俄罗斯方块小游戏
前端·javascript·canvas·1024程序员节
howard20051 个月前
2.1 HTML5 - Canvas标签
html5·canvas
普兰店拉马努金1 个月前
【Canvas与标牌】立入禁止标牌
canvas·警示·标识·立入禁止