You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

React风格下Vis.js添加showPopup及事件绑定问题咨询

在React中实现Vis.js弹出窗口(Popup)功能的解决方案

我帮你梳理一下在React中用react-graph-vis实现Vis.js弹出窗口的具体步骤,结合你提到的select事件场景来解决问题:

1. 准备基础状态与引用

首先在你的组件里定义控制弹出窗口的状态,以及用来获取Vis.js network实例的引用,这是后续获取节点位置和数据的关键:

import React, { useState, useRef } from 'react';
import Graph from 'react-graph-vis';

function GraphWithPopup() {
  // 管理弹出窗口的显示状态、位置和内容
  const [popupState, setPopupState] = useState({
    isVisible: false,
    positionX: 0,
    positionY: 0,
    content: ''
  });
  // 保存Vis.js的network实例,方便调用原生API
  const networkInstanceRef = useRef(null);

2. 配置事件处理函数

针对你用到的select事件,我们可以在事件里获取选中节点的信息,计算弹出窗口的位置,更新状态来显示弹窗;同时加上deselect事件来关闭弹窗:

const graphEvents = {
    select: (event) => {
      const { nodes } = event;
      // 只处理单个节点选中的情况
      if (nodes.length === 1) {
        const network = networkInstanceRef.current;
        const selectedNodeId = nodes[0];
        // 获取节点的画布位置
        const nodePosition = network.getPositions(selectedNodeId)[selectedNodeId];
        // 获取节点的自定义数据(比如label、描述等)
        const selectedNodeData = network.body.data.nodes.get(selectedNodeId);

        // 更新弹窗状态,这里可以根据需求调整位置偏移,避免弹窗挡住节点
        setPopupState({
          isVisible: true,
          positionX: nodePosition.x + 15,
          positionY: nodePosition.y + 15,
          content: `节点ID: ${selectedNodeId}\n节点标签: ${selectedNodeData.label}`
        });
      }
    },
    deselect: () => {
      // 取消选中时关闭弹窗
      setPopupState(prev => ({ ...prev, isVisible: false }));
    }
  };

3. 定义图数据与配置

按照你的需求准备节点、边数据,以及Vis.js的配置项:

const graphData = {
    nodes: [
      { id: 1, label: '用户节点' },
      { id: 2, label: '订单节点' },
      { id: 3, label: '商品节点' }
    ],
    edges: [
      { from: 1, to: 2 },
      { from: 2, to: 3 }
    ]
  };

  const graphOptions = {
    nodes: {
      shape: 'circle',
      size: 25
    },
    interaction: {
      selectable: true // 确保节点可以被选中
    }
  };

4. 渲染组件与自定义弹窗

最后渲染Graph组件,通过getNetwork方法保存network实例,同时根据状态渲染自定义的弹出窗口:

return (
    <div style={{ position: 'relative', width: '800px', height: '600px' }}>
      <Graph
        graph={graphData}
        options={graphOptions}
        events={graphEvents}
        getNetwork={(network) => {
          networkInstanceRef.current = network;
        }}
      />
      {/* 自定义弹出窗口 */}
      {popupState.isVisible && (
        <div
          style={{
            position: 'absolute',
            left: popupState.positionX,
            top: popupState.positionY,
            backgroundColor: '#fff',
            padding: '10px 15px',
            border: '1px solid #ddd',
            borderRadius: '4px',
            boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
            zIndex: 999,
            whiteSpace: 'pre-line'
          }}
        >
          {popupState.content}
        </div>
      )}
    </div>
  );
}

export default GraphWithPopup;

额外提示

  • 如果你想实现鼠标悬停弹出而不是选中弹出,可以把事件换成hoverNodeblurNode,逻辑和上面类似。
  • 弹出窗口的内容可以根据你的节点数据自定义,比如展示节点的更多属性、按钮等。
  • 记得确保父容器设置position: relative,这样弹出窗口的绝对定位才会基于图的容器。

内容的提问来源于stack exchange,提问作者Lieberta

火山引擎 最新活动