欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

cytoscape.js初级篇

程序员文章站 2024-02-01 08:46:52
...

很久之前写过一篇cytoscape.js基础篇, 地址是https://blog.csdn.net/dahaiaixiaohai/article/details/89669526. 可以适当的参考一下其内容.

本篇章, 正式使用cytoscape.js实现一些简单的节点显示操作, 主要包括节点的选择, 关系的选择, 节点的添加和关系的添加.

本文对应的源代码寄托于github, cytoscape.js初级篇github源代码, 在此感谢github提供的服务.

系列文章

前言

本实例通过Vue开发测试, 其他开发方式可以参考本篇章, 适当的修改后使用.

cytoscape依赖引用

  • npm : npm install cytoscape --save
  • bower : bower install cytoscape
  • jspm : jspm install npm:cytoscape

cytoscape扩展依赖引用

npm 布局及扩展依赖引用

# Cytoscape.js的圆形可滑动上下文扩展菜单
npm install cytoscape-cxtmenu --save
# Cytoscape.js的布局方式
npm install cytoscape-avsdf --save
npm install cytoscape-cola --save
npm install cytoscape-cose-bilkent --save

创建Cytoscape组件

创建Cytoscape模板容器

<template>
  <div style="position: relative; height: 100%; width: 100%; z-index: 0;">
    <div id="cytoscape_id" style="height: 100%; width: 100%; z-index: 1;"></div>
  </div>
</template>

创建Cytoscape实例对象

  • 下载代码中仅截取了cytoscape实例对象的创建部分, 并不是完成内容, 完成内容请参数本篇章最后部分.
<script>
  import cytoscape from 'cytoscape';
  import cxtmenu from 'cytoscape-cxtmenu';
  import cola from 'cytoscape-cola';
  import avsdf from 'cytoscape-avsdf';
  import coseBilkent from 'cytoscape-cose-bilkent';

  mounted() {
    if (!cytoscape().cxtmenu) {
  	  cytoscape.use(cxtmenu);
  	  cytoscape.use(cola);
  	  cytoscape.use(avsdf);
  	  cytoscape.use(coseBilkent);
    }
  
    this.$cy = cytoscape({
      // initial viewport state:
      zoom: 1, // 图表的初始缩放级别.可以设置options.minZoom和options.maxZoom设置缩放级别的限制.
      pan: {x: 0, y: 0}, // 图表的初始平移位置.
      // interaction options:
      minZoom: 1e-50, // 图表缩放级别的最小界限.视口的缩放比例不能小于此缩放级别.
      maxZoom: 1e50, // 图表缩放级别的最大界限.视口的缩放比例不能大于此缩放级别.
      zoomingEnabled: true, // 是否通过用户事件和编程方式启用缩放图形.
      userZoomingEnabled: true, // 是否允许用户事件(例如鼠标滚轮,捏合缩放)缩放图形.对此缩放的编程更改不受此选项的影响.
      panningEnabled: true, // 是否通过用户事件和编程方式启用平移图形.
      userPanningEnabled: true, // 是否允许用户事件(例如拖动图形背景)平移图形.平移的程序化更改不受此选项的影响.
      boxSelectionEnabled: true, // 是否启用了框选择(即拖动框叠加,并将其释放为选择).如果启用,则用户必须点击以平移图表.
      selectionType: 'single', // 一个字符串,指示用户输入的选择行为.对于'additive',用户进行的新选择将添加到当前所选元素的集合中.对于'single',用户做出的新选择成为当前所选元素的整个集合.
      touchTapThreshold: 8, // 非负整数,分别表示用户在轻击手势期间可以在触摸设备和桌面设备上移动的最大允许距离.这使得用户更容易点击.
                  // 这些值具有合理的默认值,因此建议不要更改这些选项,除非您有充分的理由这样做.大值几乎肯定会产生不良后果.
      desktopTapThreshold: 4, // 非负整数,分别表示用户在轻击手势期间可以在触摸设备和桌面设备上移动的最大允许距离.这使得用户更容易点击.
                  // 这些值具有合理的默认值,因此建议不要更改这些选项,除非您有充分的理由这样做.大值几乎肯定会产生不良后果.
      autolock: false, // 默认情况下是否应锁定节点(根本不可拖动,如果true覆盖单个节点状态).
      autoungrabify: false, // 默认情况下节点是否不允许被拾取(用户不可抓取,如果true覆盖单个节点状态).
      autounselectify: false, // 默认情况下节点是否允许被选择(不可变选择状态,如果true覆盖单个元素状态).
      // rendering options:
      headless: false, // true:空运行,不显示不需要容器容纳.false:显示需要容器容纳.
      styleEnabled: true, // 一个布尔值,指示是否应用样式.
      hideEdgesOnViewport: true, // 渲染提示,设置为true在渲染窗口时,不渲染边.例如,移动某个顶点时或缩放时,边信息会被临时隐藏,移动结束后,边信息会被执行一次渲染.由于性能增强,此选项现在基本上没有实际意义.
      hideLabelsOnViewport: true, // 渲染提示,当设置为true使渲染器在平移和缩放期间使用纹理而不是绘制元素时,使大图更具响应性.由于性能增强,此选项现在基本上没有实际意义.
      textureOnViewport: true, // 渲染提示,当设置为true使渲染器在平移和缩放期间使用纹理而不是绘制元素时,使大图更具响应性.由于性能增强,此选项现在基本上没有实际意义.
      motionBlur: true, // 渲染提示,设置为true使渲染器使用运动模糊效果使帧之间的过渡看起来更平滑.这可以增加大图的感知性能.由于性能增强,此选项现在基本上没有实际意义.
      motionBlurOpacity: 0.2, // 当motionBlur:true,此值控制运动模糊帧的不透明度.值越高,运动模糊效果越明显.由于性能增强,此选项现在基本上没有实际意义.
      wheelSensitivity: 0.3, // 缩放时更改滚轮灵敏度.这是一个乘法修饰符.因此,0到1之间的值会降低灵敏度(变焦较慢),而大于1的值会增加灵敏度(变焦更快).
      pixelRatio: 'auto', // 使用手动设置值覆盖屏幕像素比率(1.0建议,如果已设置).这可以通过减少需要渲染的有效区域来提高高密度显示器的性能,
                // 尽管在最近的浏览器版本中这是不太必要的.如果要使用硬件的实际像素比,可以设置pixelRatio: 'auto'(默认).
      // DOM容器,决定内容展示的位置,方式一(原生):document.getElementById('xx'),方式二(jQuery):$('#xx')
      container: document.getElementById('cytoscape_id'),
      // 一个指定布局选项的普通对象.
      layout: {name: 'random'},
    });
  },
</script>

配置Cytoscape实例对象样式

  • 需要先配置各类节点的样式, 再配置通用样式.
  mounted() {
    // ......此处省去$cy Cytoscape实例对象创建部分.
    // 不同节点的样式
    this.$cy
      .style()
      .selector('.classes-A')
      .style({'background-color': '#FF0000', 'border-color': '#FF0000', 'border-width': "1px",})
      .selector('.classes-B')
      .style({'background-color': '#00FF00', 'border-color': '#00FF00', 'border-width': "1px",})
      .selector('.classes-C')
      .style({'background-color': '#0000FF', 'border-color': '#0000FF', 'border-width': "1px",})
      .selector('.classes-D')
      .style({'background-color': '#E0E0E0', 'border-color': '#E0E0E0', 'border-width': "1px",})
    ;
    // 通用的样式
    this.$cy.style()
      /*未选择节点样式*/
      .selector('node')
      .style({'label': 'data(name)', 'font-size': '10pt', 'width': '8pt', 'height': '8pt'})
      /*已选择节点样式*/
      .selector('node:selected')
      .style({'border-color': '#c84e40', 'border-width': "1px",})
      /*未选择节点样式*/
      .selector('edge')
      .style({
        'label': 'data(name)',
        'target-arrow-shape': 'triangle-backcurve', /*箭头样式*/
        'target-arrow-size': '1px', /*箭头大小*/
        'target-arrow-color': '#999999', /*箭头颜色*/
        'curve-style': 'bezier', /*线条样式曲线*/
        'line-color': '#999999', /*线条颜色*/
        'width': '1px', /*线条宽度*/
        'font-size': '10px', /*标签字体大小*/
        'color': '#000000', /*标签字体大小*/
        'text-outline-color': 'white', /*文本轮廓颜色*/
        'text-outline-width': '1px', /*文本轮廓宽度*/
        'text-rotation': 'autorotate', /*标签方向*/
      })
      /*已选择节点样式*/
      .selector('edge:selected')
      .style({
        'color': '#3165fc', /*标签字体大小*/
        'target-arrow-color': '#61bffc', /*箭头颜色*/
        'line-color': '#61bffc', /*线条颜色*/
      })
    ;
  },

配置Cytoscape实例对象添加删除动作

  • 所有方法均采用异步风格进行操作.
  • cy.startBatch() // 手动开始批处理(对异步情况很有用)
  • cy.batch(() => { to do something! }) // 手动批处理内容(对异步情况很有用)
  • cy.endBatch() // 手动结束批处理(对异步情况很有用)
    methods: {
      /**
       * eles : Array or Map.
       * node_eg: {group: 'nodes', data: {id: 'nid1', name: 'name1', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       * edge_eg: {group: 'edges', data: {id: 'eid1', name: 'name1', source: 'A', target: 'B', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       * node_eg: [
       *   {group: 'nodes', data: {id: 'nid1', name: 'name1', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       *   {group: 'nodes', data: {id: 'nid2', name: 'name2', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       * ];
       * edge_eg: [
       *   {group: 'edges', data: {id: 'eid1', name: 'name1', source: 'nid1', target: 'nid2', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       *   {group: 'edges', data: {id: 'eid2', name: 'name1', source: 'nid2', target: 'nid3', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       * ];
       * @param eles 元素集合.
       */
      addEles(eles) {
        if (eles) {
          this.$cy.startBatch();
          this.$cy.batch(() => {
            let elements = ((Array.isArray ? Array.isArray(eles) : null != eles && eles instanceof Array) ? eles : [eles]);
            let filterElements = elements.filter(__ => !this.$cy.getElementById(__.data.id).length)
            this.$cy.add(filterElements);
          });
          this.$cy.endBatch();
        }
      },
      /**
       * 删除选择的内容(可能是顶点, 也可能是关系)
       */
      delEles() {
        this.$cy.startBatch();
        this.$cy.batch(() => {
          let selectedEles = this.$cy.elements(':selected');
          // 未选择不进行操作
          if (!selectedEles || 1 > selectedEles.length) {
            return false;
          }
          selectedEles.remove();
        });
        this.$cy.endBatch();
      },
    },

完整的Cytoscape组件代码

<style scoped>
</style>

<template>
  <div style="position: relative; height: 100%; width: 100%; z-index: 0;">
    <div id="cytoscape_id" style="height: 100%; width: 100%; z-index: 1;"></div>
  </div>
</template>

<script>
  import cytoscape from 'cytoscape';
  import cxtmenu from 'cytoscape-cxtmenu';
  import cola from 'cytoscape-cola';
  import avsdf from 'cytoscape-avsdf';
  import coseBilkent from 'cytoscape-cose-bilkent';


  export default {
    name: "CJS",
    beforeCreate() {
      this.$cy && this.$cy.destroyed() && this.$cy.destroy();
      delete this.$cy;
    },
    beforeDestroy() {
      this.$cy && this.$cy.destroyed() && this.$cy.destroy();
      delete this.$cy;
    },
    watch: {},
    props: {},
    mounted() {
      if (!cytoscape().cxtmenu) {
        cytoscape.use(cxtmenu);
        cytoscape.use(cola);
        cytoscape.use(avsdf);
        cytoscape.use(coseBilkent);
      }

      this.$cy = cytoscape({
        // initial viewport state:
        zoom: 1, // 图表的初始缩放级别.可以设置options.minZoom和options.maxZoom设置缩放级别的限制.
        pan: {x: 0, y: 0}, // 图表的初始平移位置.
        // interaction options:
        minZoom: 1e-50, // 图表缩放级别的最小界限.视口的缩放比例不能小于此缩放级别.
        maxZoom: 1e50, // 图表缩放级别的最大界限.视口的缩放比例不能大于此缩放级别.
        zoomingEnabled: true, // 是否通过用户事件和编程方式启用缩放图形.
        userZoomingEnabled: true, // 是否允许用户事件(例如鼠标滚轮,捏合缩放)缩放图形.对此缩放的编程更改不受此选项的影响.
        panningEnabled: true, // 是否通过用户事件和编程方式启用平移图形.
        userPanningEnabled: true, // 是否允许用户事件(例如拖动图形背景)平移图形.平移的程序化更改不受此选项的影响.
        boxSelectionEnabled: true, // 是否启用了框选择(即拖动框叠加,并将其释放为选择).如果启用,则用户必须点击以平移图表.
        selectionType: 'single', // 一个字符串,指示用户输入的选择行为.对于'additive',用户进行的新选择将添加到当前所选元素的集合中.对于'single',用户做出的新选择成为当前所选元素的整个集合.
        touchTapThreshold: 8, // 非负整数,分别表示用户在轻击手势期间可以在触摸设备和桌面设备上移动的最大允许距离.这使得用户更容易点击.
                              // 这些值具有合理的默认值,因此建议不要更改这些选项,除非您有充分的理由这样做.大值几乎肯定会产生不良后果.
        desktopTapThreshold: 4, // 非负整数,分别表示用户在轻击手势期间可以在触摸设备和桌面设备上移动的最大允许距离.这使得用户更容易点击.
                                // 这些值具有合理的默认值,因此建议不要更改这些选项,除非您有充分的理由这样做.大值几乎肯定会产生不良后果.
        autolock: false, // 默认情况下是否应锁定节点(根本不可拖动,如果true覆盖单个节点状态).
        autoungrabify: false, // 默认情况下节点是否不允许被拾取(用户不可抓取,如果true覆盖单个节点状态).
        autounselectify: false, // 默认情况下节点是否允许被选择(不可变选择状态,如果true覆盖单个元素状态).
        // rendering options:
        headless: false, // true:空运行,不显示不需要容器容纳.false:显示需要容器容纳.
        styleEnabled: true, // 一个布尔值,指示是否应用样式.
        hideEdgesOnViewport: true, // 渲染提示,设置为true在渲染窗口时,不渲染边.例如,移动某个顶点时或缩放时,边信息会被临时隐藏,移动结束后,边信息会被执行一次渲染.由于性能增强,此选项现在基本上没有实际意义.
        hideLabelsOnViewport: true, // 渲染提示,当设置为true使渲染器在平移和缩放期间使用纹理而不是绘制元素时,使大图更具响应性.由于性能增强,此选项现在基本上没有实际意义.
        textureOnViewport: true, // 渲染提示,当设置为true使渲染器在平移和缩放期间使用纹理而不是绘制元素时,使大图更具响应性.由于性能增强,此选项现在基本上没有实际意义.
        motionBlur: true, // 渲染提示,设置为true使渲染器使用运动模糊效果使帧之间的过渡看起来更平滑.这可以增加大图的感知性能.由于性能增强,此选项现在基本上没有实际意义.
        motionBlurOpacity: 0.2, // 当motionBlur:true,此值控制运动模糊帧的不透明度.值越高,运动模糊效果越明显.由于性能增强,此选项现在基本上没有实际意义.
        wheelSensitivity: 0.3, // 缩放时更改滚轮灵敏度.这是一个乘法修饰符.因此,0到1之间的值会降低灵敏度(变焦较慢),而大于1的值会增加灵敏度(变焦更快).
        pixelRatio: 'auto', // 使用手动设置值覆盖屏幕像素比率(1.0建议,如果已设置).这可以通过减少需要渲染的有效区域来提高高密度显示器的性能,
                            // 尽管在最近的浏览器版本中这是不太必要的.如果要使用硬件的实际像素比,可以设置pixelRatio: 'auto'(默认).
        // DOM容器,决定内容展示的位置,方式一(原生):document.getElementById('xx'),方式二(jQuery):$('#xx')
        container: document.getElementById('cytoscape_id'),
        // 一个指定布局选项的普通对象.
        layout: {name: 'random'},
      });
      // 不同节点的样式
      this.$cy
        .style()
        .selector('.classes-A')
        .style({'background-color': '#FF0000', 'border-color': '#FF0000', 'border-width': "1px",})
        .selector('.classes-B')
        .style({'background-color': '#00FF00', 'border-color': '#00FF00', 'border-width': "1px",})
        .selector('.classes-C')
        .style({'background-color': '#0000FF', 'border-color': '#0000FF', 'border-width': "1px",})
        .selector('.classes-D')
        .style({'background-color': '#E0E0E0', 'border-color': '#E0E0E0', 'border-width': "1px",})
      ;
      // 通用的样式
      this.$cy.style()
        /*未选择节点样式*/
        .selector('node')
        .style({'label': 'data(name)', 'font-size': '10pt', 'width': '8pt', 'height': '8pt'})
        /*已选择节点样式*/
        .selector('node:selected')
        .style({'border-color': '#c84e40', 'border-width': "1px",})
        /*未选择节点样式*/
        .selector('edge')
        .style({
          'label': 'data(name)',
          'target-arrow-shape': 'triangle-backcurve', /*箭头样式*/
          'target-arrow-size': '1px', /*箭头大小*/
          'target-arrow-color': '#999999', /*箭头颜色*/
          'curve-style': 'bezier', /*线条样式曲线*/
          'line-color': '#999999', /*线条颜色*/
          'width': '1px', /*线条宽度*/
          'font-size': '10px', /*标签字体大小*/
          'color': '#000000', /*标签字体大小*/
          'text-outline-color': 'white', /*文本轮廓颜色*/
          'text-outline-width': '1px', /*文本轮廓宽度*/
          'text-rotation': 'autorotate', /*标签方向*/
        })
        /*已选择节点样式*/
        .selector('edge:selected')
        .style({
          'color': '#3165fc', /*标签字体大小*/
          'target-arrow-color': '#61bffc', /*箭头颜色*/
          'line-color': '#61bffc', /*线条颜色*/
        })
      ;
    },
    data() {
      return {}
    },
    methods: {
      /**
       * eles : Array or Map.
       * node_eg: {group: 'nodes', data: {id: 'nid1', name: 'name1', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       * edge_eg: {group: 'edges', data: {id: 'eid1', name: 'name1', source: 'A', target: 'B', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       * node_eg: [
       *   {group: 'nodes', data: {id: 'nid1', name: 'name1', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       *   {group: 'nodes', data: {id: 'nid2', name: 'name2', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       * ];
       * edge_eg: [
       *   {group: 'edges', data: {id: 'eid1', name: 'name1', source: 'nid1', target: 'nid2', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       *   {group: 'edges', data: {id: 'eid2', name: 'name1', source: 'nid2', target: 'nid3', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
       * ];
       * @param eles 元素集合.
       */
      addEles(eles) {
        if (eles) {
          this.$cy.startBatch();
          this.$cy.batch(() => {
            let elements = ((Array.isArray ? Array.isArray(eles) : null != eles && eles instanceof Array) ? eles : [eles]);
            let filterElements = elements.filter(__ => !this.$cy.getElementById(__.data.id).length)
            this.$cy.add(filterElements);
          });
          this.$cy.endBatch();
        }
      },
      /**
       * 删除选择的内容(可能是顶点, 也可能是关系)
       */
      delEles() {
        this.$cy.startBatch();
        this.$cy.batch(() => {
          let selectedEles = this.$cy.elements(':selected');
          // 未选择不进行操作
          if (!selectedEles || 1 > selectedEles.length) {
            return false;
          }
          selectedEles.remove();
        });
        this.$cy.endBatch();
      },
    },
  }
</script>

Cytoscape组件的使用

创建Cytoscape测试模板

<template>
  <div style="height: 100%; width: 100%; border: 1px solid #00F;">
    <div style="position: fixed; left: 20pt; top: 20pt; z-index: 99999;">
      <Button size="small" @click="addEles">添加</Button>
      <Button size="small" @click="delEles">删除</Button>
    </div>
    <CJS ref="ref_CJS"></CJS>
  </div>
</template>
  • 样式如下
    cytoscape.js初级篇

Cytoscape组件引用

  • 测试模板引用Cytoscape组件, 并命名为CJS.
<script>
  import CJS from './components/cjs';
  
  export default {
    name: "Test",
    components: {CJS,},
    // ......
  }
</script>

Cytoscape测试模板方法

methods: {
  addEles() {
	this.$refs['ref_CJS'].addEles([
	  {group: 'nodes', data: {'id': '鲁A123456', 'name': '鲁A123456',}, classes: 'classes-A', position: {x: 200, y: 50}},
	  {group: 'nodes', data: {'id': '鲁B123456', 'name': '鲁B123456',}, classes: 'classes-A', position: {x: 500, y: 50}},
	  {group: 'nodes', data: {'id': '鲁C123456', 'name': '鲁C123456',}, classes: 'classes-A', display: 'hide', position: {x: 200, y: 150}},
	  {group: 'nodes', data: {'id': '鲁D123456', 'name': '鲁D123456',}, classes: 'classes-A', position: {x: 500, y: 150}},
	  {group: 'nodes', data: {'id': '小王', 'name': '小王',}, classes: 'classes-B', position: {x: 100, y: 100}},
	  {group: 'nodes', data: {'id': '小赵', 'name': '小赵',}, classes: 'classes-B', position: {x: 400, y: 100}},
	  {group: 'nodes', data: {'id': '川川某公司', 'name': '川川某公司',}, classes: 'classes-C', display: 'hide', position: {x: 300, y: 100}},
	  {group: 'nodes', data: {'id': '京京某单位', 'name': '京京某单位',}, classes: 'classes-D', position: {x: 300, y: 200}},
	  {group: 'edges', data: {id: 'e0', name: '拥有', source: '小王', target: '鲁A123456'}},
	  {group: 'edges', data: {id: 'e1', name: '拥有', source: '小赵', target: '鲁B123456'}},
	  {group: 'edges', data: {id: 'e2', name: '拥有', source: '小王', target: '鲁C123456'}},
	  {group: 'edges', data: {id: 'e3', name: '拥有', source: '小赵', target: '鲁D123456'}},
	  {group: 'edges', data: {id: 'e4', name: '就职', source: '小王', target: '川川某公司'}},
	  {group: 'edges', data: {id: 'e5', name: '就职', source: '小赵', target: '川川某公司'}},
	  {group: 'edges', data: {id: 'e6', name: '租用', source: '川川某公司', target: '鲁A123456'}},
	  {group: 'edges', data: {id: 'e7', name: '租用', source: '川川某公司', target: '鲁B123456'}}
	]);
  },
  delEles() {
	this.$refs['ref_CJS'].delEles();
  },
},

完整的Cytoscape测试模板代码

<template>
  <div style="height: 100%; width: 100%; border: 1px solid #00F;">
    <div style="position: fixed; left: 20pt; top: 20pt; z-index: 99999;">
      <Button size="small" @click="addEles">添加</Button>
      <Button size="small" @click="delEles">删除</Button>
    </div>
    <CJS ref="ref_CJS"></CJS>
  </div>
</template>

<script>
  import CJS from './components/cjs';

  export default {
    name: "Test",
    components: {CJS,},
    watch: {},
    mounted() {
      this.addEles();
    },
    methods: {
      addEles() {
        this.$refs['ref_CJS'].addEles([
          {group: 'nodes', data: {'id': '鲁A123456', 'name': '鲁A123456',}, classes: 'classes-A', position: {x: 200, y: 50}},
          {group: 'nodes', data: {'id': '鲁B123456', 'name': '鲁B123456',}, classes: 'classes-A', position: {x: 500, y: 50}},
          {group: 'nodes', data: {'id': '鲁C123456', 'name': '鲁C123456',}, classes: 'classes-A', display: 'hide', position: {x: 200, y: 150}},
          {group: 'nodes', data: {'id': '鲁D123456', 'name': '鲁D123456',}, classes: 'classes-A', position: {x: 500, y: 150}},
          {group: 'nodes', data: {'id': '小王', 'name': '小王',}, classes: 'classes-B', position: {x: 100, y: 100}},
          {group: 'nodes', data: {'id': '小赵', 'name': '小赵',}, classes: 'classes-B', position: {x: 400, y: 100}},
          {group: 'nodes', data: {'id': '川川某公司', 'name': '川川某公司',}, classes: 'classes-C', display: 'hide', position: {x: 300, y: 100}},
          {group: 'nodes', data: {'id': '京京某单位', 'name': '京京某单位',}, classes: 'classes-D', position: {x: 300, y: 200}},
          {group: 'edges', data: {id: 'e0', name: '拥有', source: '小王', target: '鲁A123456'}},
          {group: 'edges', data: {id: 'e1', name: '拥有', source: '小赵', target: '鲁B123456'}},
          {group: 'edges', data: {id: 'e2', name: '拥有', source: '小王', target: '鲁C123456'}},
          {group: 'edges', data: {id: 'e3', name: '拥有', source: '小赵', target: '鲁D123456'}},
          {group: 'edges', data: {id: 'e4', name: '就职', source: '小王', target: '川川某公司'}},
          {group: 'edges', data: {id: 'e5', name: '就职', source: '小赵', target: '川川某公司'}},
          {group: 'edges', data: {id: 'e6', name: '租用', source: '川川某公司', target: '鲁A123456'}},
          {group: 'edges', data: {id: 'e7', name: '租用', source: '川川某公司', target: '鲁B123456'}}
        ]);
      },
      delEles() {
        this.$refs['ref_CJS'].delEles();
      },
    },
  }
</script>

<style scoped>
</style>

完整截图

cytoscape.js初级篇

注意事项

  • 在删除节点时, 可以删除一个节点顶点或一个关系, 删除一个顶点时, 该顶点有所关联的关系也会一起删除.
  • 若要删除多个顶点, 可以按住Shift键, 然后鼠标左键拖动框选, 然后删除, 选择顶点有所关联的所有关系会一同删除.