跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScript大前端算法

前端关系图组件 relation-graph 推荐与使用

前言 Relation-Graph 是一个开源的免费关系图谱组件,支持 Vue2、Vue3 和 React 框架。它提供开箱即用的体验,配置简单,文档清晰,并支持通过插槽自定义节点样式。文章详细介绍了在 Vue2、Vue3 和 React 中的安装和使用方法,包含完整的代码示例和运行效果图。该组件具有高度可定制性,支持节点点击事件等交互功能,适用于构建各种关系图谱应用。 官网地址 relation…

RedisGeek发布于 2026/4/6更新于 2026/7/2589K 浏览
前端关系图组件 relation-graph 推荐与使用

前言

Relation-Graph 是一个开源的免费关系图谱组件,支持 Vue2、Vue3 和 React 框架。它提供开箱即用的体验,配置简单,文档清晰,并支持通过插槽自定义节点样式。文章详细介绍了在 Vue2、Vue3 和 React 中的安装和使用方法,包含完整的代码示例和运行效果图。该组件具有高度可定制性,支持节点点击事件等交互功能,适用于构建各种关系图谱应用。

官网地址

relation-graph - A Relationship Graph Component

推荐原因

  1. 超级容易上手,基本开箱即用
  2. 官方文档清晰明了,有在线示例、可自定义配置,配置完可直接复制配置的代码
  3. 完全支持 Vue2、Vue3、React 三种框架
  4. 关系节点可通过插槽完全自定义定制
  5. 免费

使用方法

1. Vue2 使用

1.1 安装 relation-graph

npm install --save relation-graph

1.2 可直接复制到 Vue 文件中运行使用

<template>
  <div>
    <div>
      <RelationGraph ref="graphRef" :options="graphOptions" :on-node-click="onNodeClick" :on-line-click="onLineClick" />
    </div>
  </div>
</template>
<script>
// relation-graph 也支持在 main.js 文件中使用 Vue.use(RelationGraph);这样,你就不需要下面这一行代码来引入了。
import RelationGraph from 'relation-graph'
export default {
  name: 'Demo',
  components: { RelationGraph },
  data() {
    return {
      graphOptions: {
        defaultJunctionPoint: 'border'
        // 这里可以参考"Graph 图谱"中的参数进行设置 https://www.relation-graph.com/#/docs/graph
      }
    }
  },
  mounted() {
    this.showGraph()
  },
  methods: {
    showGraph() {
      const jsonData = {
        rootId: 'a',
        nodes: [
          { id: 'a', text: 'A', borderColor: 'yellow' },
          { id: 'b', text: 'B', color: '#43a2f1', fontColor: 'yellow' },
          { id: 'c', text: 'C', nodeShape: 1, width: 80, height: 60 },
          { id: 'e', text: 'E', nodeShape: 0, width: 150, height: 150 }
        ],
        lines: [
          { from: 'a', to: 'b', text: '关系 1', color: '#43a2f1' },
          { from: 'a', to: 'c', text: '关系 2' },
          { from: 'a', to: 'e', text: '关系 3' },
          { from: 'b', to: 'e', color: '#67C23A' }
        ]
      }
      // 以上数据中的 node 和 link 可以参考"Node 节点"和"Link 关系"中的参数进行配置
      this.$refs.graphRef.setJsonData(jsonData, (graphInstance) => {
        // Called when the relation-graph is completed
      })
    },
    onNodeClick(nodeObject, $event) {
      console.log('onNodeClick:', nodeObject)
    },
    onLineClick(lineObject, $event) {
      console.log('onLineClick:', lineObject)
    }
  }
}
</script>

2. Vue3 使用

2.1 安装 relation-graph

npm install --save relation-graph-vue3

2.2 可直接复制到 Vue 文件中运行使用

<template>
  <div>
    <div>
      <relation-graph ref="graphRef$" :options="options" />
    </div>
  </div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import RelationGraph from 'relation-graph-vue3'

const graphRef$ = ref<RelationGraph>()
const options = {
  defaultExpandHolderPosition: 'right'
}

onMounted(() => {
  const jsonData = {
    rootId: 'a',
    nodes: [
      { id: 'a', text: 'a', },
      { id: 'b', text: 'b', },
      { id: 'c', text: 'c', },
      { id: 'd', text: 'd', },
      { id: 'e', text: 'e', },
      { id: 'f', text: 'f', },
    ],
    lines: [
      { from: 'a', to: 'b', },
      { from: 'a', to: 'c', },
      { from: 'a', to: 'd', },
      { from: 'a', to: 'e', },
      { from: 'a', to: 'f', },
    ],
  }
  // The node and line in the above data can refer to the options in "Node" and "Link & Line" for configuration.
  // Node: https://www.relation-graph.com/#/docs/node
  // Link & Line: https://www.relation-graph.com/#/docs/link
  graphRef$.value.setJsonData(jsonData)
  // The graphRef$.value.setJsonData(jsonData, callback) method is a convenient method that is equivalent to the following code:
  //  const graphInstance = graphRef$.value.getInstance();
  //  graphInstance.addNodes(jsonData.nodes);
  //  graphInstance.addLines(jsonData.lines);
  //  graphInstance.rootNode = graphInstance.getNodeById(jsonData.rootId);
  //  await graphInstance.doLayout(); // Layout using the layouter set in graphOptions
  //  await graphInstance.moveToCenter(); // Find the center based on node distribution and center the view
  //  await graphInstance.zoomToFit(); // Zoom to fit, so that all nodes can be displayed in the visible area
})
</script>

3. React 使用

3.1 安装 relation-graph

npm install --save relation-graph-react

3.2 可直接复制到文件中运行使用

import React, { useEffect, useRef } from 'react'
import RelationGraph, { RelationGraphInstance } from 'relation-graph-react'
import type { MutableRefObject } from 'react'
import type {
  RGLine,
  RGLink,
  RGNode,
  RGNodeSlotProps,
  RGOptions,
  RelationGraphExpose
} from 'relation-graph-react'

const staticJsonData = {
  rootId: '2',
  nodes: [
    { id: '1', text: '节点 -1', myicon: 'el-icon-star-on' },
    { id: '2', text: '节点 -2', myicon: 'el-icon-setting', width: 100, height: 100 },
    { id: '3', text: '节点 -3', myicon: 'el-icon-setting' },
    { id: '4', text: '节点 -4', myicon: 'el-icon-star-on' },
    { id: '6', text: '节点 -6', myicon: 'el-icon-setting' },
    { id: '7', text: '节点 -7', myicon: 'el-icon-setting' },
    { id: '8', text: '节点 -8', myicon: 'el-icon-star-on' },
    { id: '9', text: '节点 -9', myicon: 'el-icon-headset' },
    { id: '71', text: '节点 -71', myicon: 'el-icon-headset' },
    { id: '72', text: '节点 -72', myicon: 'el-icon-s-tools' },
    { id: '73', text: '节点 -73', myicon: 'el-icon-star-on' },
    { id: '81', text: '节点 -81', myicon: 'el-icon-s-promotion' },
    { id: '82', text: '节点 -82', myicon: 'el-icon-s-promotion' },
    { id: '83', text: '节点 -83', myicon: 'el-icon-star-on' },
    { id: '84', text: '节点 -84', myicon: 'el-icon-s-promotion' },
    { id: '85', text: '节点 -85', myicon: 'el-icon-sunny' },
    { id: '91', text: '节点 -91', myicon: 'el-icon-sunny' },
    { id: '92', text: '节点 -82', myicon: 'el-icon-sunny' },
    { id: '5', text: '节点 -5', myicon: 'el-icon-sunny' }
  ],
  lines: [
    { from: '7', to: '71', text: '投资' },
    { from: '7', to: '72', text: '投资' },
    { from: '7', to: '73', text: '投资' },
    { from: '8', to: '81', text: '投资' },
    { from: '8', to: '82', text: '投资' },
    { from: '8', to: '83', text: '投资' },
    { from: '8', to: '84', text: '投资' },
    { from: '8', to: '85', text: '投资' },
    { from: '9', to: '91', text: '投资' },
    { from: '9', to: '92', text: '投资' },
    { from: '1', to: '2', text: '投资' },
    { from: '3', to: '1', text: '高管' },
    { from: '4', to: '2', text: '高管' },
    { from: '6', to: '2', text: '高管' },
    { from: '7', to: '2', text: '高管' },
    { from: '8', to: '2', text: '高管' },
    { from: '9', to: '2', text: '高管' },
    { from: '1', to: '5', text: '投资' }
  ]
}

const NodeSlot: React.FC<RGNodeSlotProps> = ({ node }) => {
  console.log('NodeSlot:')
  if (node.id === '2') { // if rootNode
    return (
      <div style={{
        zIndex: 555,
        opacity: 0.5,
        lineHeight: '100px',
        width: '100px',
        height: '100px',
        color: '#000000',
        borderRadius: '50%',
        boxSizing: 'border-box',
        fontSize: '18px',
        textAlign: 'center',
        overflow: 'hidden'
      }}>
        <div style={{
          width: '100%',
          height: (node.data!.percent * 100) + '%',
          marginTop: ((1 - node.data!.percent) * 100) + '%',
          background: 'linear-gradient(to bottom, #00FFFF, #FF00FF)'
        }}>
          {node.text}
        </div>
      </div>
    )
  }
  return (
    <div style={{ lineHeight: '80px', textAlign: 'center' }}>
      <span>{node.text}</span>
    </div>
  )
}

const SimpleGraph: React.FC = () => {
  const graphRef = useRef() as MutableRefObject<RelationGraphExpose>
  useEffect(() => {
    showGraph()
  }, [])

  const showGraph = async () => {
    // The node and line in the above data can refer to the options in "Node" and "Link & Line" for configuration.
    // Node: https://www.relation-graph.com/#/docs/node
    // Link & Line: https://www.relation-graph.com/#/docs/link
    await graphRef.current.setJsonData(staticJsonData, (graphInstance) => {
      // Do something when graph ready
    })
    // The graphRef.current.setJsonData(jsonData, callback) method is a convenient method that is equivalent to the following code:
    //  const graphInstance = graphRef.current.getInstance();
    //  graphInstance.addNodes(jsonData.nodes);
    //  graphInstance.addLines(jsonData.lines);
    //  graphInstance.rootNode = graphInstance.getNodeById(jsonData.rootId);
    //  await graphInstance.doLayout(); // Layout using the layouter set in graphOptions
    //  await graphInstance.moveToCenter(); // Find the center based on node distribution and center the view
    //  await graphInstance.zoomToFit(); // Zoom to fit, so that all nodes can be displayed in the visible area
  }

  const options: RGOptions = {
    debug: true,
    defaultLineShape: 1,
    layout: {
      layoutName: 'center',
      maxLayoutTimes: 3000
    },
    defaultExpandHolderPosition: 'right'
  }

  const onNodeClick = (node: RGNode, _e: MouseEvent | TouchEvent) => {
    console.log('onNodeClick:', node.text)
    return true
  }

  const onLineClick = (line: RGLine, _link: RGLink, _e: MouseEvent | TouchEvent) => {
    console.log('onLineClick:', line.text, line.from, line.to)
    return true
  }

  return (
    <div>
      <div>ok</div>
      <div style={{ height: 600, width: 900, border: '#efefef solid 1px' }}>
        <RelationGraph
          ref={graphRef}
          options={options}
          nodeSlot={NodeSlot}
          onNodeClick={onNodeClick}
          onLineClick={onLineClick}
        />
      </div>
    </div>
  )
}

export default SimpleGraph

运行结果

因为我是 Vue2 项目,所以下面展示的是我在 Vue2 项目中的代码,可直接复制运行,需要注意的是我使用了 less。

<template>
  <div>
    <div>
      <h3>设备联动图</h3>
    </div>
    <div>
      <RelationGraph ref="graphRef" :options="graphOptions" :on-node-click="onNodeClick" :on-line-click="onLineClick">
        <template #node="{ node }">
          <div>
            <div>
              <div>
                <span></span>
                <strong>声光</strong>
                <div>离线</div>
              </div>
              <div>
                <span>4</span>
              </div>
            </div>
            <div>
              办公室 1
            </div>
          </div>
        </template>
      </RelationGraph>
    </div>
  </div>
</template>
<script>
import RelationGraph from 'relation-graph'
export default {
  name: "DevLinkageDiagram",
  components: { RelationGraph },
  props: {},
  data() {
    return {
      graphOptions: {
        defaultJunctionPoint: 'border',
        allowShowDownloadButton: false,
        defaultFocusRootNode: false,
        defaultNodeWidth: 1,
        defaultNodeHeight: 1,
        defaultShowLineLabel: false,
        allowShowRefreshButton: true,
        // 这里可以参考"Graph 图谱"中的参数进行设置 https://www.relation-graph.com/#/docs/graph
      }
    }
  },
  computed: {},
  created() {},
  mounted() {
    this.showGraph()
  },
  methods: {
    showGraph() {
      const jsonData = {
        rootId: 'a',
        nodes: [
          { id: 'a', text: 'A', },
          { id: 'b', text: 'B', },
          { id: 'c', text: 'C', },
          { id: 'e', text: 'E', }
        ],
        lines: [
          { from: 'a', to: 'b', },
          { from: 'a', to: 'c', },
          { from: 'a', to: 'e', },
        ]
      }
      // 以上数据中的 node 和 link 可以参考"Node 节点"和"Link 关系"中的参数进行配置
      this.$refs.graphRef.setJsonData(jsonData, (graphInstance) => {
        // Called when the relation-graph is completed
      })
    },
    onNodeClick(nodeObject, $event) {
      // console.log('onNodeClick:', nodeObject)
    },
    onLineClick(lineObject, $event) {
      // console.log('onLineClick:', lineObject)
    }
  },
};
</script>
<style scoped lang="less">
.dev-linkage-diagram {
  padding: 15px;
  background-color: #ffffff;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
    padding-bottom: 10px;
    border-bottom: 1px solid #eee;
  }
  .graphRefBox {
    height: 580px;
    background-color: #cfcece;
  }
  .rel-node-peel {
    position: relative;
    .c-my-rg-node {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
  }
  .nodeBox {
    width: 200px;
    border-radius: 20px;
    overflow: hidden;
    >div {
      padding: 0 16px;
    }
    .top {
      display: flex;
      justify-content: space-between;
      align-items: center;
      width: 100%;
      height: 40px;
      background-color: #deb922;
      .left {
        display: flex;
        align-items: center;
        color: #fff;
        .state {
          padding: 1px 4px;
          margin-left: 4px;
          background-color: rgba(245, 245, 245, 0.3);
          border-radius: 4px;
        }
      }
      .num {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 24px;
        height: 24px;
        background-color: rgba(226, 226, 226, 0.5);
        border: 1px solid #fff;
        border-radius: 50%;
        color: #fff;
        font-weight: 700;
        font-size: 14px;
      }
    }
    .bottom {
      display: flex;
      align-items: center;
      width: 100%;
      height: 40px;
      background-color: #72716d;
      font-size: 14px;
    }
  }
}
</style>

运行成果图

文章配图

该组件表现良好,推荐使用。

目录

  1. 前言
  2. 官网地址
  3. 推荐原因
  4. 使用方法
  5. 1. Vue2 使用
  6. 1.1 安装 relation-graph
  7. 1.2 可直接复制到 Vue 文件中运行使用
  8. 2. Vue3 使用
  9. 2.1 安装 relation-graph
  10. 2.2 可直接复制到 Vue 文件中运行使用
  11. 3. React 使用
  12. 3.1 安装 relation-graph
  13. 3.2 可直接复制到文件中运行使用
  14. 运行结果
  15. 运行成果图
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 渐进式 AIGC 系统架构与功能特性:支持多模态大模型与 Agent 智能体
  • Telegram 搜索机器人搭建指南(含 Python 脚本)
  • 从零搭建Clawdbot+企微机器人:单向推送全流程指南(新手可玩)
  • Windows 本地部署 OpenClaw 并接入飞书机器人
  • 前端实战:如何让用户回到上次阅读的位置
  • 网络基础安全六大组件:防火墙、WAF、IPS、行为管控、DDoS 及蜜罐详解
  • OpenClaw 架构解析:从语言交互到行动型 AI 的跃迁
  • Arduino BLDC 机器人 IMU 角度读取与 PID 互补滤波控制
  • uv 虚拟环境管理:venv 创建、激活与 Python 版本指定
  • Java 剪辑接单报价比价系统架构设计与实现
  • 黑客技术入门指南:编程语言与操作系统选择建议
  • SpringBoot+Vue 无人超市管理系统设计与实现
  • GitHub 高效挖掘开源项目的四种实用方法
  • PyCharm 接入 DeepSeek 实现 AI 辅助编程
  • TRAE AI 编程:从工具入门到 Vue 全栈实战
  • Mac Mini M4 本地部署大模型:Ollama 与 Llama 环境配置
  • Ubuntu 安装 OpenClaw 并接入飞书机器人
  • 使用 Trae IDE 与 MCP Server 将 Figma 设计稿转为前端代码
  • LeetCode 栈结构经典题目解析与代码实现
  • Kiro IDE 实战:Spec 驱动 AI 编程,需求明确自动出代码

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online