思维导图关系数据开发——组件relation-graph

市面上常见的思维导图库 jsMindGoJSMindMup等。
以下介绍的是在vue3中使用的relation-graph

使用:
npm install --save relation-graph-vue3 //
注意:使用时import的方式与vue2不一样:import RelationGraph from
‘relation-graph-vue3’

relation-graph

官方链接: https://www.relation-graph.com/#/docs/graph

relation-graph是支持Vue2、Vue3、React的关系数据展示组件,支持通过【插槽】让使用者使用"普通HTML元素、Vue组件、React组件"来完全自定义图形元素,并提供实用的API接口让使用者轻松构建可交互的图形应用。

非会员功能——官方提供展示功能、双击编辑功能。

	<RelationGraph
      v-show="treeVisible"
       ref="graphRefTree"
       :options="graphOptionsTree"
       @node-click="onTreeNodeClick"
       @line-click="onTreeLineClick"
       :onContextmenu=“onTreeContextmenu”
     >
       <template #node="{ node }">
         <addNodeDialog
           v-if="isEditLink"
           :nodeData="node"
           :rootId="rootIdTree"
           :graph-instance="graphInstanceTree"
           :enable-editing-mode="true"
           @on-node-text-change="onNodeTextChange"
         />
       </template>
     </RelationGraph>

设置图谱的选项和事件:

运行时属性: options
图谱会根据options生成一个包含默认值的完整配置对象,它就是options,
可以通过this.$refs.graphRef.getInstance().options来获取;
你还可以从这个对象中获取当前图谱的可见区域大小、画布大小、画布偏移量、当前布局器等运行时对象。

节点点击事件 @node-click=“onTreeNodeClick” (nodeObject, $event)
连线点击事件 @line-click=“onTreeLineClick” (nodeObject, $event)

点击下载图片按钮时触发 onImageDownload (cavansDom, $event)
可通过此事件接收到一个图谱的dom对象,你可以根据此对象来生成图片,如果要阻止默认的下载动作,此方法需要返回false。注意:请使用<graph :on-image-download=functionName />的方式来绑定关系线事件。

在图谱中点击右键 :onContextmenu=“onTreeContextmenu” ($event, objectType:canvas|node|link|line, object:Node|Link|Line|undefined)
右键可分别返回canvas、node、link 右键点击类型及节点与连线对象。

点击画布 onCanvasClick ($event)
节点拖动结束时 onNodeDragEnd (nodeObject, $event)

画布拖动结束时 onCanvasDragEnd ($event)

节点展开收缩事件,。。。

插槽:

node节点插槽

<template #node="{node}">
	xxx
</template>

line自定义连线内容的插槽

<MyLine
	slot="line"
/>

graph-plug自定义图谱区域内容的插槽,通过此功能可以在图谱中显示一些内容,比如筛选区域,图例说明等。

<template #graph-plug>
	xxx
</template>
或者
<div slot="graph-plug" ></div>

canvas-plug自定义图谱画布区域内容的插槽,通过此功能可以在画布中显示一些内容,这些内容会和节点、线条一样可以被缩放、根据画布被拖动。

示例:

	<RelationGraph
      ref="graphRef"
       :options="graphOptions">
       <MyLine
           v-if="line.isHide === false"
           slot="line"
           slot-scope="{line, link, relationGraph}"
           :line="line"
           :link="link"
           :relation-graph="relationGraph"
       />
       <template #graph-plug>
         <div class="c-my-panel">
           <div>
             以下图谱中的线条以及线条上的花,是通过连线插槽slot=line实现的。注意:node插槽/画布插槽/图谱插槽都可以使用常规方式来编写,但连线插槽必须通过svg来编写。
           </div>
         </div>
       </template>
     </RelationGraph>

在这里插入图片描述

方法:

https://www.relation-graph.com/#/docs/graph

这个链接是可参考的类似gitee案例https://github.com/p-moon/genealogy-ui/commit/2870ee7565690eef514778474c817f2487568492

getInstance() : 获取图谱实例,通过this.$refs.graphRef.getInstance()来获取。

setOptions(options, callback) : 设置/重新设置图谱的选项,options。更改设置:this.$refs.graphRef.setOptions(newOptions, callback);

setJsonData(jsonData, callback): 设置/重新设置图谱中的数据,jsonData。
this.$refs.graphRef.setJsonData(jsonData, callback)方法是一个方便使用的方法,它和以下代码等效:

const graphInstance = this.$refs.graphRef.getInstance();
graphInstance.addNodes(jsonData.nodes);
graphInstance.addLines(jsonData.lines);
graphInstance.rootNode = graphInstance.getNodeById(jsonData.rootId);
await graphInstance.doLayout(); // 使用graphOptions中设置的布局器布局
await graphInstance.moveToCenter(); // 根据节点分布找到画面中心并居中
await graphInstance.zoomToFit(); // 缩放到合适大小,以让所有节点可以在可见区域展示
await callback();

appendJsonData(jsonData, callback):向图谱中追加数据,jsonData。
this.$refs.graphRef.appendJsonData(jsonData, callback)方法是一个方便使用的方法,它和以下代码等效:

const graphInstance = this.$refs.graphRef.getInstance();
graphInstance.addNodes(jsonData.nodes);
graphInstance.addLines(jsonData.lines);
await graphInstance.doLayout(); // 使用graphOptions中设置的布局器布局
await callback();

refresh(): 刷新布局,你可以通过getNodes()获取当前图谱中的节点,并通过节点的isHide属性隐藏一些节点,再调用refresh()方法可以根据依然显示的节点重新布局图谱;或者在动态向图谱中添加数据候刷新布局;当你的图片默认默认状态是不可见的时,在切换到可见状态下后可能会显示不正常,这时你调用一下refresh()方法可以让图片正确显示。
总之一句话:当图谱中的节点看起来不正常时,你都可以调用refresh方法来让布局器重新为节点分配位置。

getNodeById(nodeId): 根据节点id获取节点对象。

removeNodeById(nodeId):移除指定id对应的节点,彻底移除,移除element和数据对象。

删除连线扩展方法待验证 deleteLine: (line: Line) => {
store.dispatch(“asyncDeleteLine”, line).then(() => {
// relationGraphView?.value?.getInstance()?.removeLinkById(line.from, line.to);
});
},

getGraphJsonData(): 获取当前图谱的节点、关系数据的json数据。

getGraphJsonOptions(): 获取当前图谱的完整的配置信息。

getNodes():获取图谱中所有的节点对象,可以直接修改该对象的属性,这些对象不能用于JSON序列化。
getLinks(): 获取图谱中所有的关系对象,这些对象不能用于JSON序列化。

所有【线条】可以通过以下代码获取:

const links = this.$refs.graphRef.getLinks();
const lines = links.reduce((currentLines, link) => currentLines.concat(...link.relations), []);

downloadAsImage(format, fileName):下载图片。调用:this.$refs.graphRef.getInstance().downloadAsImage(a,b)

dataUpdated(): 有时候在更改数据后视图并没有同步(比如直接修改对象属性更改了线条color属性值后,但图谱上的线条颜色没有变化时),可以调用此方法。(relationGraph.value?.updateView();待验证)

focusNodeById(nodeId):根据节点id在图谱中选中该节点并居中。
。。。

节点实例方法------

const clickTestButton = () => {
  const setGraphInstance = treeVisible.value
    ? graphRefTree.value?.getInstance()
    : graphRef.value?.getInstance();
  if (setGraphInstance) {
    setGraphInstance.refresh(); // 刷新画布
    setGraphInstance.doLayout(); // 重新布局(节点位置)
    setGraphInstance.zoomToFit(); // 缩放至适应画布(大小适应)
    setGraphInstance.moveToCenter();
  }
};

扩展:节点添加

graphInstance.addNodes([ nodeObj ]);
graphInstance.addLines([ lineObj
]); await graphInstance.doLayout(); // 使用graphOptions中设置的布局器布局

// 确认添加弹窗
const confirmHandel = async () => {
  let addId = 0;
  await getRelationAddId()
    .then((res) => {
      addId = res.retdata || 0;
    })
    .catch((error) => {
      ElMessage({
        message: `${error}`,
        type: 'error',
      });
    });
  if (!addId) {
    ElMessage({
      message: `id异常`,
      type: 'error',
    });
    addNodeVisible.value = false;
    resetForm();
    return;
  }
  if (props.nodeData && addId) {
    const graphInstance = props.graphInstance;
    if (graphInstance) {
      const newNode = {
        id: String(addId), // uuidv4()
        text: formData.name || '添加节点',
        x: props.nodeData.x + 100,
        y: props.nodeData.y,
      };
      graphInstance.addNodes([newNode]);
      graphInstance.addLines([
        {
          from: props.nodeData.id,
          to: newNode.id,
          text: formData.line || 'line',
        },
      ]);
      await graphInstance.doLayout();
      addNodeVisible.value = false;
      resetForm();
    }
  }
};

扩展:节点删除

graphInstance.removeNode(item);

// 删除节点
const deleteNode = async () => {
  console.log('删除节点:', props.nodeData);
  console.log('关系实例', props.graphInstance);
  if (props.nodeData) {
    const graphInstance = props.graphInstance;
    if (graphInstance) {
      // ---深度循环删除节点
      let arr = [];
      const removeDeepNode = (obj, isRoot = false) => {
        let length = obj.targetTo.length;
        if (isRoot) {
          arr.push(obj);
        }
        if (obj.targetTo && length > 0) {
          for (let i = 0; i < length; i++) {
            if (obj.targetTo[i].id != graphInstance?.graphData?.rootNode?.id) {
              arr.push(obj.targetTo[i]);
              removeDeepNode(obj.targetTo[i]);
            }
          }
        }
        return arr;
      };
      let removeArr = await removeDeepNode(props.nodeData, true);
      removeArr.forEach((item) => {
        graphInstance.removeNode(item);
      });
    }
  }
};

扩展:连线编辑

直接更改对象属性text值

const onLineClick = (lineObject, linkObject, $event) => {
  if (props.isEditLink) {
    lineObj.value = lineObject;
    lineText.value = lineObject.text || '';
    editLineVisible.value = true;
  }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值