admin管理员组

文章数量:1573361

简介

AntV 是蚂蚁的一个数据可视化的工具平台。

X6快速上手

基础概念

画布Graph

在x6中,Graph是图的载体,它包含图上的所有元素(节点、边等),同时挂载了图的相关操作(如交互监听、元素操作等)。

const graph = new Graph({
  panning:true //支持平移
  selecting: {
    enabled: true, //支持选中
    multiple: true,
    movable: true, //支持拖动
  }
}
graph.zoom(0.2) //在原来缩放级别上增加0.2
graph.zoom(-0.2) //在原来缩放级别上减少0.2

基类Cell

基类Cell定义了节点和边共同属性和方法,如属性样式、可见性、业务数据。

节点Node

node是所有节点的基类,继承自Cell,并定义了节点的通用属性和方法。

边Edge

node是所有节点的基类,继承自Cell,并定义了节点的通用属性和方法。

使用

定义画布属性

export const garghProperty = {
  height: 600,
  grid: true,
  selecting: {
    enabled: true,
    multiple: true,
    // movable: true,
    // showNodeSelectionBox: true,
  },
  background: {
    color: '#f8f8f8', // 设置画布背景颜色
  },
  snapline: {
    enabled: true,
    sharp: true,
  },
  scroller: {
    enabled: true,
    pannable: true,
    pageVisible: false,
    pageBreak: false,
  },
  mousewheel: {
    enabled: true,
  },
  interacting: false,
}

定义节点属性

export const commonNode = {
  width: 180,
  height: 90,
  data: {
    fileList: [],
    tool: ''
  },
  markup: [
    {
      tagName: 'rect',
      attrs: {
        class: 'card',
      },
    },
    {
      tagName: 'text',
      attrs: {
        class: 'content',
      },
    },
    {
      tagName: 'g',
      attrs: {
        class: 'btn add',
      },
      children: [
        {
          tagName: 'rect',
          attrs: {
            class: 'add',
          },
        },
        {
          tagName: 'circle',
          attrs: {
            class: 'add',
          },
        },
        {
          tagName: 'text',
          attrs: {
            class: 'add',
          },
        },
      ],
    },
    {
      tagName: 'g',
      attrs: {
        class: 'btn del',
      },
      children: [
        {
          tagName: 'circle',
          attrs: {
            class: 'del',
          },
        },
        {
          tagName: 'text',
          attrs: {
            class: 'del',
          },
        },
      ],
    },
  ],
  attrs: {
    '.card': {
      rx: 10,
      ry: 10,
      refWidth: '100%',
      refHeight: '100%',
      fill: '#EFF4FF',
      stroke: '#5F95FF',
      strokeWidth: 1,
      pointerEvents: 'visiblePainted',
    },

    '.content': {
      refX: 0.05,
      refY: 0.1,
      fill: '#262626',
      fontFamily: 'Arial',
      fontSize: 14,
      fontWeight: '600',
      lineHeight: 20,
      textWrap: {
        width: 169,
        height: 79,
        ellipsis: true,
      },
    },
    '.btn.add': {
      refX: '32%',
      refY: '95%',
      refY2: 15,
      event: 'node:add',
    },
    '.btn.del': {
      refX: '100%',
      event: 'node:delete',
    },
    '.btn.add > rect': {
      rx: 10,
      ry: 10,
      refX: '-6%',
      refY: '-10%',
      width: '85px',
      height: '22px',
      fill: '#EFF4FF',
    },
    '.btn.add > circle': {
      r: 7,
      refX: '-0.5%',
      refY: '2%',
      fill: 'transparent',
      stroke: '#5F95FF',
      strokeWidth: 2,
    },
    '.btn.add > text': {
      fontSize: 16,
      fontWeight: 800,
      fill: '#5F95FF',
      x: -5.5,
      y: 7,
      fontFamily: 'Times New Roman',
      text: '+ 新增选项',
    },
    '.btn.del > circle': {
      r: 10,
      fill: '#fff',
      stroke: '#F56C6C',
      strokeWidth: 2,
    },
    '.btn.del > text': {
      fontSize: 28,
      fontWeight: 500,
      fill: '#F56C6C',
      x: -4.5,
      y: 6,
      fontFamily: 'Times New Roman',
      text: '-',
    },
  },
}

定义边属性

export const edge = {
  zIndex: -1,
  attrs: {
    line: {
      strokeWidth: 2,
      stroke: '#A2B1C3',
      sourceMarker: null,
    },
  },
}

初始化画布

      //普通节点
      Graph.registerNode(
        'common-node',
        {...commonNode},
        true
      )
      // 自定义边
      Graph.registerEdge(
        'org-edge',
        {...edge},
        true,
      )

      const graph = new Graph(
        {
          container: document.getElementById('container'),
          ...garghProperty
        }
      );

画布事件监听

      graph.on('node:add', ({e, node}) => {
        e.stopPropagation()
        const member = this.createNode(
          '新建节点',
        )
        graph.freeze()
        graph.addCell([member, this.createEdge(node, member)])
        graph.resetSelection(member)
        this.layout()
      })

      graph.on('node:delete', ({e, node}) => {
        e.stopPropagation()
        graph.freeze()
        graph.removeCell(node)
        this.layout()
      })

      graph.on('node:selected', ({node}) => {

        const data = node.getData()
        const form = {
          id: node.id,
          content: node.attrs['.content'].text,
          ...data
        }


        this.$emit('set-nodeForm', form)

      });

      graph.on('node:unselected', ({node}) => {
        this.$emit('set-nodeForm', {})
      });

      // 当 cell 为节点时触发
      graph.on('node:change:children', ({node}) => {
        if (node.getChildCount() !== 0) {
          node.setAttrs({
            '.btn.del > circle': {
              r: 0,
            },
            '.btn.del > text': {
              text: '',
            },
          })
        } else if (node.getParent() !== null) {
          node.setAttrs({
            '.btn.del > circle': {
              r: 10,
            },
            '.btn.del > text': {
              text: '-',
            },
          })
        }
      })

设置节点布局

//设置节点布局
    layout() {
      const graph = this.graph;
      const dir = 'TB';
      const nodes = graph.getNodes()
      const edges = graph.getEdges()
      const g = new dagre.graphlib.Graph()

      g.setGraph({rankdir: dir, nodesep: 16, ranksep: 50})
      g.setDefaultEdgeLabel(() => ({}))

      const width = 260
      const height = 90
      nodes.forEach((node) => {
        g.setNode(node.id, {width, height})
      })

      edges.forEach((edge) => {
        const source = edge.getSource()
        const target = edge.getTarget()
        g.setEdge(source.cell, target.cell)

        //新建节点时设置节点的父子关系
        const sourceNode = graph.getCellById(source.cell);
        const targetNode = graph.getCellById(target.cell);
        sourceNode.addChild(targetNode);
      })

      dagre.layout(g)

      graph.freeze()

      g.nodes().forEach((id) => {

        const node = graph.getCellById(id)
        node.setZIndex(100)
        if (node) {
          const pos = g.node(id)
          node.position(pos.x, pos.y)
        }
      })

      edges.forEach((edge) => {
        const source = edge.getSourceNode()
        const target = edge.getTargetNode()
        const sourceBBox = source.getBBox()
        const targetBBox = target.getBBox()

        console.log(sourceBBox, targetBBox)

        if ((dir === 'LR' || dir === 'RL') && sourceBBox.y !== targetBBox.y) {
          const gap =
            dir === 'LR'
              ? targetBBox.x - sourceBBox.x - sourceBBox.width
              : -sourceBBox.x + targetBBox.x + targetBBox.width
          const fix = dir === 'LR' ? sourceBBox.width : 0
          const x = sourceBBox.x + fix + gap / 2
          edge.setVertices([
            {x, y: sourceBBox.center.y},
            {x, y: targetBBox.center.y},
          ])
        } else if (
          (dir === 'TB' || dir === 'BT') &&
          sourceBBox.x !== targetBBox.x
        ) {
          const gap =
            dir === 'TB'
              ? targetBBox.y - sourceBBox.y - sourceBBox.height
              : -sourceBBox.y + targetBBox.y + targetBBox.height
          const fix = dir === 'TB' ? sourceBBox.height : 0
          const y = sourceBBox.y + fix + gap / 2
          edge.setVertices([
            {x: sourceBBox.center.x + 2, y},
            {x: targetBBox.center.x + 2, y},
          ])
        } else {
          edge.setVertices([])
        }
      })

      graph.unfreeze()
    },

本文标签: 简单AntV