antv g6右击节点自定义上下文菜单实现

效果图展示

请添加图片描述

方案一

<template>
  <div ref="graphContent" class="graph-page" @contextmenu.prevent=""></div>
</template>

<script>
import G6 from '@antv/g6'
export default {
  mounted() {
    const data = {
      nodes: [
        {
          id: 'node1',
          label: 'node1',
          x: 200,
          y: 100,
          type: 'rect',
        },
        {
          id: 'node2',
          label: 'node2',
          x: 250,
          y: 250,
          type: 'rect',
        },
        {
          id: 'node3',
          label: 'node3',
          x: 350,
          y: 100,
          type: 'rect',
        },
      ],
      edges: [
        {
          source: 'node1',
          target: 'node2',
          label: 'Test Label',
        },
        {
          source: 'node1',
          target: 'node3',
          label: 'Test Label 2',
        },
      ],
    }
    this.init(data)
  },
  methods: {
    init(nodeData) {
      const container = this.$refs.graphContent
      const width = container.scrollWidth
      const height = container.scrollHeight || 500
      const graph = new G6.Graph({
        container: container,
        width,
        height,
        defaultNode: {
          size: [80, 40],
          type: 'rect',
          style: {
            fill: '#DEE9FF',
            stroke: '#5B8FF9',
          },
        },
        defaultEdge: {
          style: {
            stroke: '#b5b5b5',
            lineAppendWidth: 3, // Enlarge the range the edge to be hitted
          },
          labelCfg: {
            autoRotate: true,
            style: {
              stroke: 'white',
              lineWidth: 5,
            },
          },
        },
        modes: {
          default: ['drag-canvas', 'zoom-canvas', 'click-select', 'drag-node'],
        },
        fitView: false,
        fitCenter: true,
      })
      graph.data(nodeData)
      graph.render()

      graph.on('node:click', (item) => {
        console.log(item)
      })

	  // 1、菜单列表数据写死版本
      let conextMenuContainer = document.createElement('ul')
      conextMenuContainer.id = 'contextMenu'
      // 创建li
      let firstLi = document.createElement('li')
      firstLi.innerText = '指标详情'
      conextMenuContainer.appendChild(firstLi)
      this.$refs.graphContent.appendChild(conextMenuContainer)

      let menu = document.getElementById('contextMenu')
      graph.on('node:contextmenu', function (event) {
        self.currentNodeInfo = event.item._cfg.model
        menu.style.display = 'block'
        menu.style.left = event.canvasX + 20 + 'px'
        menu.style.top = event.canvasY + 'px'
        document.body.addEventListener('click', function () {
          menu.style.display = 'none'
        })
        event.stopPropagation() //阻止事件向上冒泡
      })
      firstLi.addEventListener('click', function (event) {
        // console.log(`详情事件---`, event.target.innerHTML)
        event.stopPropagation() //阻止事件向上冒泡
      })
    },

    // 2、接口返回数据创建右击菜单
    /* let conextMenuContainer = document.createElement('ul')
    conextMenuContainer.id = 'contextMenu'
    this.$refs.graphContent.appendChild(conextMenuContainer)

    let menu = document.getElementById('contextMenu')
    graph.on('node:contextmenu', function (event) {
      // 清空ul下全部li
      conextMenuContainer.innerHTML = ''

      // setTimout模拟接口, list模拟返回数据
      setTimeout(() => {
        let list = [111, 222, 333, 444]
        let itemList
        list.forEach((item) => {
          itemList = document.createElement('li')
          itemList.innerText = item
          conextMenuContainer.appendChild(itemList)

          itemList.addEventListener('click', function (event) {
            console.log(`详情事件---`, event.target.innerHTML)
          })
        })

        self.currentNodeInfo = event.item._cfg.model
        menu.style.display = 'block'
        menu.style.left = event.canvasX + 20 + 'px'
        menu.style.top = event.canvasY + 'px'
        document.body.addEventListener('click', function () {
          menu.style.display = 'none'
        })
        event.stopPropagation() //阻止事件向上冒泡
      }, 1000)
    }) */

  },
}
</script>

<style lang="less" scoped>
.graph-page {
  position: relative;
  height: 100%;
}
/deep/ #contextMenu {
  position: absolute;
  box-shadow: 1px 2px 5px #aaaaaa;
  border: 1px solid #c6c6c6;
  li {
    padding: 4px 14px;
    background: white;
    cursor: pointer;
    color: #444444;
  }
}
</style>

方案二

<template>
  <div ref="graphContent" class="graph-page" @contextmenu.prevent=""></div>
</template>

<script>
import G6 from '@antv/g6'
import insertCss from 'insert-css'
insertCss(`
  .g6-component-contextmenu {
    padding: 0
  }
  .g6-component-contextmenu ul {
    margin: 0;
    text-align: center;
  }
  .g6-component-contextmenu ul li {
    padding: 6px 20px;
    cursor: pointer;
  }
  .g6-component-contextmenu ul li:hover {
    background: #b4b4b4;
  }
`)
export default {
  mounted() {
    const data = {
      nodes: [
        {
          id: 'node1',
          label: 'node1',
          x: 200,
          y: 100,
          type: 'rect',
        },
        {
          id: 'node2',
          label: 'node2',
          x: 250,
          y: 250,
          type: 'rect',
        },
        {
          id: 'node3',
          label: 'node3',
          x: 350,
          y: 100,
          type: 'rect',
        },
      ],
      edges: [
        {
          source: 'node1',
          target: 'node2',
          label: 'Test Label',
        },
        {
          source: 'node1',
          target: 'node3',
          label: 'Test Label 2',
        },
      ],
    }
    this.init(data)
  },
  methods: {
    init(nodeData) {
      const contextMenu = new G6.Menu({
        getContent() {
          return `
          <ul>
            <li>指标详情</li>
            <li>计算日志</li>
          </ul>`
        },
        handleMenuClick: (target, item) => {
          console.log(target, item, target.innerHTML)
        },
        offsetX: 10,
        offsetY: -25,
        // 在哪些类型的元素上响应
        itemTypes: ['node'],
      })

      const container = this.$refs.graphContent
      const width = container.scrollWidth
      const height = container.scrollHeight || 500
      const graph = new G6.Graph({
        container: container,
        width,
        height,
        plugins: [contextMenu],
        defaultNode: {
          size: [80, 40],
          type: 'rect',
          style: {
            fill: '#DEE9FF',
            stroke: '#5B8FF9',
          },
        },
        defaultEdge: {
          style: {
            stroke: '#b5b5b5',
            lineAppendWidth: 3, // Enlarge the range the edge to be hitted
          },
          labelCfg: {
            autoRotate: true,
            style: {
              stroke: 'white',
              lineWidth: 5,
            },
          },
        },
        modes: {
          default: ['drag-canvas', 'zoom-canvas', 'click-select', 'drag-node'],
        },
        fitView: false,
        fitCenter: true,
      })
      graph.data(nodeData)
      graph.render()

      graph.on('node:click', (item) => {
        console.log(item)
      })
    },
  },
}
</script>

<style lang="less" scoped>
.graph-page {
  position: relative;
  height: 100%;
}
</style>
  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值