vue2 antv x6 注册vue组件 人工dag图 vue组件传值监听

实现效果~,主要使用,注意 结构解析值 !!! ,当前节点没有node属性

如果: node.on('change:data', ({ node }) => {})  错!!! ,为了少掉几个头发。。。。。。

 打印看看~

this.curNode.on('change:data', (current) => {})
 

 

 

正确: node.on('change:data', ({ current }) => {})

 

 

 

官网  人工dag图

人工dag图,节点使用vue组件 ,在节点组件  change:data 事件,监听节点变化

 

父组件官网代码:

<template>
  <div
    id="container"
    style="width: 800px; border: 1px solid #ccc; height: 500px"
  >
  </div>
</template>

<script>
import { Graph, Path, Cell } from '@antv/x6'
import { Selection } from '@antv/x6-plugin-selection'

import { register, getTeleport } from '@antv/x6-vue-shape'
import dataJSON from './dag.json'
import AlgoNode from './node1.vue'

export default {
  components: {
    AlgoNode
  },
  name: 'dagView',
  provide() {
    return {
      getNode: () => this.getNode
    }
  },
  data() {
    return {
      grpah: null,
      curNodes: null, // 当前-节点信息包括对象
      imglist: {
        logo: 'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*evDjT5vjkX0AAAAAAAAAAAAAARQnAQ',
        success:
          'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*6l60T6h8TTQAAAAAAAAAAAAAARQnAQ',
        failed:
          'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*SEISQ6My-HoAAAAAAAAAAAAAARQnAQ',
        running:
          'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*t8fURKfgSOgAAAAAAAAAAAAAARQnAQ'
      }
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      let _this = this
      const graph = new Graph({
        container: document.getElementById('container'),
        grid: true,

        panning: {
          enabled: true,
          eventTypes: ['leftMouseDown', 'mouseWheel']
        },
        mousewheel: {
          enabled: true,
          modifiers: 'ctrl',
          factor: 1.1,
          maxScale: 1.5,
          minScale: 0.5
        },
        highlighting: {
          magnetAdsorbed: {
            name: 'stroke',
            args: {
              attrs: {
                fill: '#fff',
                stroke: '#31d0c6',
                strokeWidth: 4
              }
            }
          }
        },
        connecting: {
          snap: true,
          allowBlank: false,
          allowLoop: false,
          highlight: true,
          connector: 'algo-connector',
          connectionPoint: 'anchor',
          anchor: 'center',
          validateMagnet({ magnet }) {
            return magnet.getAttribute('port-group') !== 'top'
          },
          createEdge() {
            return graph.createEdge({
              shape: 'dag-edge',
              attrs: {
                line: {
                  strokeDasharray: '5 5'
                }
              },
              zIndex: -1
            })
          }
        }
      })

      register({
        shape: 'dag-node',
        width: 180,
        height: 36,
        // component: AlgoNode,
        component: {
          // 使用vue3的render渲染组件,并添加自定义事件
          render(h) {
            return h(AlgoNode, {
              props: {
                curNodes: _this.curNodes,
                imgs: _this.imglist
              }
            })
          }
        },

        ports: {
          groups: {
            top: {
              position: 'top',
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  stroke: '#C2C8D5',
                  strokeWidth: 1,
                  fill: '#fff'
                }
              }
            },
            bottom: {
              position: 'bottom',
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  stroke: '#C2C8D5',
                  strokeWidth: 1,
                  fill: '#fff'
                }
              }
            }
          }
        }
      })

      Graph.registerEdge(
        'dag-edge',
        {
          inherit: 'edge',
          attrs: {
            line: {
              stroke: '#C2C8D5',
              strokeWidth: 1,
              targetMarker: null
            }
          }
        },
        true
      )

      Graph.registerConnector(
        'algo-connector',
        (s, e) => {
          const offset = 4
          const deltaY = Math.abs(e.y - s.y)
          const control = Math.floor((deltaY / 3) * 2)

          const v1 = { x: s.x, y: s.y + offset + control }
          const v2 = { x: e.x, y: e.y - offset - control }

          return Path.normalize(
            `M ${s.x} ${s.y}
       L ${s.x} ${s.y + offset}
       C ${v1.x} ${v1.y} ${v2.x} ${v2.y} ${e.x} ${e.y - offset}
       L ${e.x} ${e.y}
      `
          )
        },
        true
      )

      const nodeStatusList = [
        [
          {
            id: '1',
            status: 'running'
          },
          {
            id: '2',
            status: 'default'
          },
          {
            id: '3',
            status: 'default'
          },
          {
            id: '4',
            status: 'default'
          }
        ],
        [
          {
            id: '1',
            status: 'success'
          },
          {
            id: '2',
            status: 'running'
          },
          {
            id: '3',
            status: 'default'
          },
          {
            id: '4',
            status: 'default'
          }
        ],
        [
          {
            id: '1',
            status: 'success'
          },
          {
            id: '2',
            status: 'success'
          },
          {
            id: '3',
            status: 'running'
          },
          {
            id: '4',
            status: 'running'
          }
        ],
        [
          {
            id: '1',
            status: 'success'
          },
          {
            id: '2',
            status: 'success'
          },
          {
            id: '3',
            status: 'success'
          },
          {
            id: '4',
            status: 'failed'
          }
        ]
      ]

      graph.use(
        new Selection({
          multiple: true,
          rubberEdge: true,
          rubberNode: true,
          modifiers: 'shift',
          rubberband: true
        })
      )

      graph.on('edge:connected', ({ edge }) => {
        edge.attr({
          line: {
            strokeDasharray: ''
          }
        })
      })

      graph.on('node:change:data', ({ node }) => {
        const edges = graph.getIncomingEdges(node)
        const { status } = node.getData()
        edges?.forEach((edge) => {
          if (status === 'running') {
            edge.attr('line/strokeDasharray', 5)
            edge.attr(
              'line/style/animation',
              'running-line 30s infinite linear'
            )
          } else {
            edge.attr('line/strokeDasharray', '')
            edge.attr('line/style/animation', '')
          }
        })
      })

      // 初始化节点 / 边
      const init = (data) => {
        const cells = []
        data.forEach((item) => {
          if (item.shape === 'dag-node') {
            cells.push(graph.createNode(item))
          } else {
            cells.push(graph.createEdge(item))
          }
        })
        graph.resetCells(cells)
      }
      // TODO
      // 显示节点状态
      let _time = null
      const showNodeStatus = async (statusList) => {
        const status = statusList.shift()
        if (!status) {
          clearTimeout(_time)
          return
        }
        // 当前要渲染---->节点信息


        status?.forEach((item) => {
          const { id, status } = item
          // 根据状态id 获取当前node节点
          const node = graph.getCellById(id)
          const data = node.getData()
          node.setData({
            ...data,
            status
          })
          console.log('node=====', node)

          // _this.curNodes = node.getData()
        })

        _time = setTimeout(() => {
          showNodeStatus(statusList)
        }, 3000)
      }

      console.log('dataJSON', dataJSON)
      init(dataJSON)
      showNodeStatus(nodeStatusList)
      graph.centerContent()
    }
  }
}
</script>
<style lang="scss">
.node {
  display: flex;
  align-items: center;
  width: 100%;
  height: 100%;
  background-color: #fff;
  border: 1px solid #c2c8d5;
  border-left: 4px solid #5f95ff;
  border-radius: 4px;
  box-shadow: 0 2px 5px 1px rgba(0, 0, 0, 0.06);
}
.node img {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  margin-left: 8px;
}
.node .label {
  display: inline-block;
  flex-shrink: 0;
  width: 104px;
  margin-left: 8px;
  color: #666;
  font-size: 12px;
}
.node .status {
  flex-shrink: 0;
}
.node.success {
  border-left: 4px solid #52c41a;
}
.node.failed {
  border-left: 4px solid #ff4d4f;
}
.node.running .status img {
  animation: spin 1s linear infinite;
}
.x6-node-selected .node {
  border-color: #1890ff;
  border-radius: 2px;
  box-shadow: 0 0 0 4px #d4e8fe;
}
.x6-node-selected .node.success {
  border-color: #52c41a;
  border-radius: 2px;
  box-shadow: 0 0 0 4px #ccecc0;
}
.x6-node-selected .node.failed {
  border-color: #ff4d4f;
  border-radius: 2px;
  box-shadow: 0 0 0 4px #fedcdc;
}
.x6-edge:hover path:nth-child(2) {
  stroke: #1890ff;
  stroke-width: 1px;
}

.x6-edge-selected path:nth-child(2) {
  stroke: #1890ff;
  stroke-width: 1.5px !important;
}

@keyframes running-line {
  to {
    stroke-dashoffset: -1000;
  }
}
@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>
View Code

 

子组件   node1.vue

<template>
  <div class="node" :class="[status]">
    <img :src="imgs.logo" alt="logo" />
    <span class="label">{{ nodeData?.label }}</span>
    <span class="status">
      <img v-if="status === 'success'" :src="imgs.success" alt="success" />
      <img v-if="status === 'failed'" :src="imgs.failed" alt="failed" />
      <img v-if="status === 'running'" :src="imgs.running" alt="running" />
    </span>
  </div>
</template>
<script>
export default {
  name: 'nodeView',
  props: {
    imgs: {
      type: Object
    },
    curNodes: {
      type: Object | Array
    }
  },
  inject: ['getNode'],

  data() {
    return {
      status: '',
      curNode: null,
      nodeData: {
        label: ''
      }
    }
  },
  mounted() {
    this.curNode = this.getNode()
    this.changeNode()

//注意~ current结构解析值 不确定情况下把返回值打印,不需要解构
this.curNode.on('change:data', ({ current }) => { // 监听节点数据变化~~~~~~~ this.changeNode() }) }, methods: { changeNode() { this.curNode = this.getNode() this.nodeData = this.curNode?.data ?? {} this.status = this.curNode.data.status } } } </script>

 

 

 

 

posted on 2024-09-29 10:33  Mc525  阅读(30)  评论(0编辑  收藏  举报

导航