AntV G6自定义树状图TreeGraph

AntV G6自定义树状图TreeGraph

只是为了记录下自己写的G6组件成果AntV G6自定义树状图TreeGraph_第1张图片

G6去除生成图的动画效果animate
 const graph = new G6.TreeGraph({
        animate: false, // 切换布局时是否使用动画过度
        })
G6拓扑图刷新页面按钮事件(刷新按钮根据页面变化展示不同的图片)

AntV G6自定义树状图TreeGraph_第2张图片

    
    <div class="reset-fitView"
         id="reset-button">
      <img :src="resetViewUrl"
           style="margin: 4px;">
    div>

// 设置复原按钮图片默认值
export default {
  data () {
    return {
      resetViewUrl: require('./img/original.svg'), // 复位按钮根据画布调整改变展示图片 
    }
  },

以下这段代码结合下面,标题“还有各种鼠标事件(G6拓扑图缩放事件等)”里的,根据数据创建树状图节createNode () 方法里的页面缩放操作,可以官方文档搜viewportchange属性了解页面事件

	 // 监听画布缩放
      let originalView = graph.getZoom()
      let number = graph.getZoom()
      graph.on('viewportchange', e => {
        if (e.action == 'translate') { // 画布被拖动
          this.resetViewUrl = require('./img/change.svg')
        }
        if (e.action !== 'zoom') return; // 画布未被缩放
        const currentZoom = graph.getZoom();
        number = currentZoom;
        this.resetViewUrl = require('./img/change.svg')
        if (originalView == number) {
          this.resetViewUrl = require('./img/original.svg')
        }
      });
      // 画布里数据展示复位
      var resetView = document.getElementById('reset-button')
      resetView.onclick = function () {
        graph.render();
        graph.fitView();
      };

还有各种鼠标事件(G6拓扑图缩放事件等)
<template>
  <div class="topology-diagram">
    <div id="containerBox"
         style="background: #F7F8FA;border-radius: 4px;">
    div>
    
    <div v-if="show"
         class="img-annotation">
      <div class="annotation-icon1">div>
      <span class="annotation-text1">允许出入span>
      <div class="annotation-icon2">div>
      <span class="annotation-text2">无权限span>
      <img class="annotation-icon3"
           src="./img/disable.svg" />
      <span class="annotation-text3">禁止出入span>
    div>
    
    <div class="operation-button"
         :style="show ? 'margin-top: -48px;margin-left: 262px;':'position: absolute;right: 12px;top: 380px;'">
      <img src="./img/zoom-out-button.svg"
           style="margin-left: 16px;margin-top: 11px;"
           id="zoom-out-button" />
      <img src="./img/zoom-in-button.svg"
           style="margin-left: 16px;margin-top: 11px;"
           id="zoom-in-button" />
    div>

    
    <drawer :title="title"
            :display.sync="display"
            :inner="true"
            :width="drawerWidth"
            :height="drawerHeight"
            :regionType="regionType"
            :mask="false">
    drawer>
  div>
template>
<script>
import G6 from '@antv/g6'
import drawer from '@/components/drawer/drawer'
export default {
  data () {
    return {
      title: '',
      title_id: '',// 用于判断右边浮窗关闭弹出效果
      drawerHeight: '557px',
      display: false,
      drawerWidth: '220px',
      regionType: -1,
      // 根据通行点类型展示不同图片、以及不同的鼠标悬浮图标
      imgPath: '',
      imgHoverPath: '',
      imgDisablePath: '',
      imgNoPermissionPath: '',
    }
  },
  props: {
    // 宽度
    topologyMapWidth: {
      type: String,
      default: '1121'
    },
    // 高度H
    topologyMapHeight: {
      type: String,
      default: '570'
    },
    topologyMapData: { // 拓扑图数据
      type: Object,
      default: () => {
        return {}
      }
    },
    // 判断是否需要鼠标数据、放大缩小点击按钮再左下还是右下、图左下注解是否展示
    show: {
      type: Boolean,
      default: true
    }
  },
  components: {
    drawer
  },
  mounted () {
    this.customNode()
    this.createNode()
  },
  methods: {
    // 自定义节点方法
    customNode () {
      // 文本超出隐藏 (字段, 最大长度, 字体大小)
      const fittingString = (str, maxWidth, fontSize) => {
        const ellipsis = '...';
        const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
        let currentWidth = 0;
        let res = str;
        const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
        str.split('').forEach((letter, i) => {
          if (currentWidth > maxWidth - ellipsisLength) return;
          if (pattern.test(letter)) {
            // Chinese charactors
            currentWidth += fontSize;
          } else {
            // get the width of single letter according to the fontSize
            currentWidth += G6.Util.getLetterWidth(letter, fontSize);
          }
          if (currentWidth > maxWidth - ellipsisLength) {
            res = `${str.substr(0, i)}${ellipsis}`;
          }
        });
        return res;
      };
      // 节点缩放点击事件,根据不同场所展示不同样式
      const marker = (hasChildren, group, cfg, rect) => {
        if (hasChildren) {
          if (cfg.category == 0) {
            group.addShape('image', {
              attrs: {
                x: rect.getBBox().width - 80,
                y: rect.getBBox().height / 2 - 84.5,
                cursor: 'pointer',
                width: 20,
                height: 20,
                img: cfg.collapsed ? require('./img/close1.svg') : require('./img/open1.svg'),
              },
              name: 'collapse-icon0',
              modelId: cfg.id,
            })
          } if (cfg.category == 1) {
            group.addShape('image', {
              attrs: {
                x: rect.getBBox().width - 80,
                y: rect.getBBox().height / 2 - 84.5,
                cursor: 'pointer',
                width: 20,
                height: 20,
                img: cfg.collapsed ? require('./img/close2.svg') : require('./img/open2.svg'),
              },
              name: 'collapse-icon1',
              modelId: cfg.id,
            })
          } if (cfg.category == 2) {
            group.addShape('image', {
              attrs: {
                x: rect.getBBox().width - 80,
                y: rect.getBBox().height / 2 - 84.5,
                cursor: 'pointer',
                width: 20,
                height: 20,
                img: cfg.collapsed ? require('./img/close3.svg') : require('./img/open3.svg'),
              },
              name: 'collapse-icon2',
              modelId: cfg.id,
            })
          } if (cfg.category == 3) {
            group.addShape('image', {
              attrs: {
                x: rect.getBBox().width - 80,
                y: rect.getBBox().height / 2 - 84.5,
                cursor: 'pointer',
                width: 20,
                height: 20,
                img: cfg.collapsed ? require('./img/close4.svg') : require('./img/open4.svg'),
              },
              name: 'collapse-icon3',
              modelId: cfg.id,
            })
          }
        }
      }
      const _this = this
      G6.registerNode(
        'tree-node',
        {
          drawShape: function drawShape (cfg, group) {

            const rect = group.addShape('rect', {
              attrs: {
                fill: '#E9EBF5',
                stroke: '#E9EBF5',
                cursor: 'pointer',
                x: 0,
                y: 0,
                width: 1,
                height: 1,
                radius: 8
              },
              name: 'rect-shape',
            });
            let textX = -24
            let textY = 0
            let iconLength = cfg.units ? cfg.units.length : 0 // 节点里的图标个数 
            // let iconLength = cfg.iconLength
            // const content = cfg.name;
            let number = 10 // 两个图标换行
            let textArray = []
            for (let i = 0; i < iconLength; i++) {
              if (i != 0) {
                if ((i + 1) % number === 1) {
                  textY = textY + 50 + 17
                  textX = -24
                } else if ((i + 1) % number != 1) {
                  textX = textX + 41 + 30
                }
              }
              const content = cfg.units[i].name;
              textArray[i] = group.addShape('text', {
                attrs: {
                  text: fittingString(content, 66, 11),
                  x: textX,
                  y: textY,
                  cursor: 'pointer',
                  textAlign: 'center',
                  textBaseline: 'middle',
                  fill: '#424874',
                  fontSize: 11,
                  fontWeight: 400,
                  fontFamily: 'PingFangSC-Regular, PingFang SC',
                  lineHeight: 17,
                  width: 66
                },
                name: 'text-shape' + i,
              });
              // 判断门禁状态 .units.permission    出入点权限 0 允许 1 禁止 为空时无权限
              if (cfg.units[i].permission === '' || cfg.units[i].permission === 1) {
                textArray[i].attr('fill', '#C3C5D9')
                continue
              }
              console.log('1111111111111111111111!_this.show', !_this.show);
              if (!_this.show) continue
              // 判断通行点类型(只判断出入点、电梯厅)unitTypeCode 通行点类型 pass 通行点 elevator 电剃厅
              textArray[i].on('mouseenter', e => {
                imgArray[i].attr('img', cfg.units[i].unitTypeCode === 'pass' ? require('./img/passHover.svg') : require('./img/elevatorHover.svg'))
                textArray[i].attr('fill', '#6373FF')
              })
              textArray[i].on('mouseleave', e => {
                imgArray[i].attr('img', cfg.units[i].unitTypeCode === 'pass' ? require('./img/pass.svg') : require('./img/elevator.svg'))
                textArray[i].attr('fill', '#424874')
              })
              textArray[i].on('click', e => {
                // 根据门禁id判断是否重复点击同一个门禁
                if (_this.title_id !== cfg.id) {
                  _this.display = _this.display ? !_this.display : _this.display
                  setTimeout(() => {
                    _this.title = content
                    _this.title_id = cfg.id
                    _this.regionType = cfg.category
                    _this.display = !_this.display

                  }, 500)
                } else {
                  _this.title = content
                  _this.title_id = cfg.id
                  _this.regionType = cfg.category
                  _this.display = true
                }
              })
            }
            // 无门禁时
            let NoIcon
            if (iconLength === 0) {
              NoIcon = group.addShape('text', {
                attrs: {
                  text: fittingString('无门禁', 61, 12),
                  x: textX,
                  y: textY,
                  textAlign: 'center',
                  textBaseline: 'middle',
                  fill: '#424874',
                  fontSize: 12,
                  fontWeight: 400,
                  fontFamily: 'PingFangSC-Regular, PingFang SC',
                  lineHeight: 17,
                  width: 61
                },
                name: 'text-shape0',
              });
            }
            const text = textArray[0] ? textArray[0] : NoIcon
            const bbox = text.getBBox();
            const hasChildren = cfg.children && cfg.children.length > 0;
            let nodeHeight = iconLength === 0 ? 0 : iconLength % number > 0 ? Math.ceil(iconLength / number) : iconLength / number // 节点根据图标换行相应高度
            rect.attr({
              x: -66 / 2 - 20 - 28,
              y: -24 - 50, // 节点框根据图标上移
              width: NoIcon ? 250 : nodeHeight === 0 ? ((32 + 51) * (number - 1)) : number > iconLength ? ((32 + 45) * iconLength) : ((32 + 51) * (number - 1)),
              height: NoIcon ? bbox.height + 120 : number >= iconLength ? bbox.height + 120 : 80 * nodeHeight,
            });
            const rectBox = rect.getBBox();
            let imgX = rectBox.x + 30
            let imgY = rectBox.y + 30
            let imgArray = []
            for (let i = 0; i < iconLength; i++) {
              if (i != 0) { // 图标移动间隔距离
                if ((i + 1) % number === 1) {
                  imgY = imgY + 32 + 35
                  imgX = rectBox.x + 32
                } else if ((i + 1) % number != 1) {
                  imgX = imgX + 32 + 40
                }
              }
              // 判断通行点类型(只判断出入点、电梯厅)unitTypeCode 通行点类型 pass 通行点 elevator 电剃厅
              imgArray[i] = group.addShape('image', {
                attrs: {
                  x: imgX,
                  y: imgY,
                  width: 32,
                  height: 32,
                  cursor: 'pointer',
                  img: cfg.units[i].unitTypeCode === 'pass' ? require('./img/pass.svg') : require('./img/elevator.svg'),
                  shadowBlur: 20,
                  // shadowColor: '#C7CBF6',
                  shadowColor: '#C6C9EA'
                },
                name: 'image-shape' + i,
              });
              textArray[i].attr({
                x: imgX + 16, // 文字根据图片宽度居中
                y: imgY + 32 + 12, // 32图片宽度12文字图片间距
              });
              // 判断门禁状态 .units.permission    出入点权限 0 允许 1 禁止 为空时无权限
              if (cfg.units[i].permission === '') {
                imgArray[i].attr('img', cfg.units[i].unitTypeCode === 'pass' ? require('./img/passNoPermission.svg') : require('./img/elevatorNoPermission.svg'))
                continue
              }
              if (cfg.units[i].permission === 1) {
                imgArray[i].attr('img', cfg.units[i].unitTypeCode === 'pass' ? require('./img/passDisable.svg') : require('./img/elevatorDisable.svg'))
                continue
              }
              if (!_this.show) continue
              // const imageBox = group.find((element) => element.get('name') === 'image-shape' + i);
              imgArray[i].on('mouseenter', e => {
                imgArray[i].attr('img', cfg.units[i].unitTypeCode === 'pass' ? require('./img/passHover.svg') : require('./img/elevatorHover.svg'))
                textArray[i].attr('fill', '#6373FF')
              })
              imgArray[i].on('mouseleave', e => {
                imgArray[i].attr('img', cfg.units[i].unitTypeCode === 'pass' ? require('./img/pass.svg') : require('./img/elevator.svg'))
                textArray[i].attr('fill', '#424874')
              })
              imgArray[i].on('click', e => {
                // 根据门禁id判断是否重复点击同一个门禁
                if (_this.title_id !== cfg.id) {
                  _this.display = _this.display ? !_this.display : _this.display
                  setTimeout(() => {
                    _this.title = cfg.units[i].name
                    _this.title_id = cfg.id
                    _this.regionType = cfg.category
                    _this.display = !_this.display
                  }, 500)
                } else {
                  _this.title = cfg.units[i].name
                  _this.title_id = cfg.id
                  _this.regionType = cfg.category
                  _this.display = true

                }
              })
            }
            // 文件头****************************************************************************************
            // 文件头文字
            let fileText = cfg.name
            const imageLeft = group.addShape('image', {
              attrs: {
                x: rectBox.x + 36,
                y: rectBox.y - 23.5,
                width: 36,
                height: 24,
                img: require('./img/left.svg'),
              },
              name: 'image-left',
            });
            const rectFile = group.addShape('rect', {
              attrs: {
                x: rectBox.x + 36 + 36,
                y: rectBox.y - 23,
                height: 24,
                width: 36,
                stroke: '#E9EBF5',
                fill: '#E9EBF5',
              },
              name: 'rect-file',
            });
            const imageRight = group.addShape('image', {
              attrs: {
                x: rectFile.getBBox().x + rectFile.getBBox().width,
                y: rectFile.getBBox().y,
                width: 36,
                height: 24,
                img: require('./img/right.svg'),
              },
              name: 'image-right',
            });
            // 图标不固定要做判断,判断0:园区 1:楼栋 2:楼层 3:办公区*************************
            let fileIconUrl = require('./img/fileIcon1.svg')
            if (cfg.category == 0) {
              fileIconUrl = require('./img/fileIcon1.svg')
            } if (cfg.category == 1) {
              fileIconUrl = require('./img/fileIcon2.svg')
            } if (cfg.category == 2) {
              fileIconUrl = require('./img/fileIcon3.svg')
            } if (cfg.category == 3) {
              fileIconUrl = require('./img/fileIcon4.svg')
            }
            const fileIcon = group.addShape('image', {
              attrs: {
                x: rectFile.getBBox().x - 8,
                y: rectFile.getBBox().y + 5,
                width: 20,
                height: 20,
                img: fileIconUrl,
              },
              name: 'file-icon',
            });
            const textFile = group.addShape('text', {
              attrs: {
                text: fileText,
                x: fileIcon.getBBox().x + 20 + 8,
                y: fileIcon.getBBox().y + 12,
                textAlign: 'left',
                textBaseline: 'middle',
                fill: '#202340',
                fontSize: 16,
                fontWeight: 400,
                fontFamily: 'PingFangSC-Regular, PingFang SC',
                lineHeight: 22,
              },
              name: 'text-file',
            });
            // 文件文字宽度重新渲染文件头样式宽度度
            rectFile.attr({
              width: textFile.getBBox().width + fileIcon.getBBox().width + 8,
            });
            imageRight.attr({
              x: rectFile.getBBox().x + rectFile.getBBox().width,
              y: rectFile.getBBox().y,
            });
            // 节点宽度根据文件头宽度来判断
            let fileWidth = rectFile.getBBox().width + 36 + 36 + 24 + 24
            if (fileWidth > rectBox.width) {
              rect.attr({
                width: fileWidth + 36,
              });
            }
            // 无门禁时,文字定位在节点的中心
            if (NoIcon) {
              NoIcon.attr({
                x: (rect.getBBox().width) / 2 - 36 - 40,
              });
            }
            // 节点后面加号位置,判断0:园区 1:楼栋 2:楼层 3:办公区
            marker(hasChildren, group, cfg, rect)
            // 整个节点悬浮时节点+文件头悬浮样式*****************************************************
            if (_this.show) {
              rect.on('mouseenter', e => {
                imageLeft.attr('img', require('./img/leftHover.svg'))
                imageRight.attr('img', require('./img/rightHover.svg'))
                rect.attr({
                  stroke: '#DFE0ED',
                  fill: '#DFE0ED',
                })
                rectFile.attr({
                  stroke: '#DFE0ED',
                  fill: '#DFE0ED',
                })

              })
              rect.on('mouseleave', e => {
                imageLeft.attr('img', require('./img/left.svg'))
                imageRight.attr('img', require('./img/right.svg'))
                rect.attr({
                  fill: '#E9EBF5',
                  stroke: '#E9EBF5',
                })
                rectFile.attr({
                  stroke: '#E9EBF5',
                  fill: '#E9EBF5',
                })

              })
              // 节点整体点击释放样式*********************************************************
              rect.on('mousedown', e => {
                imageLeft.attr('img', require('./img/leftSelect.svg'))
                imageRight.attr('img', require('./img/rightSelect.svg'))
                rect.attr({
                  fill: '#DEE3FA',
                  stroke: '#DEE3FA',
                })
                rectFile.attr({
                  fill: '#DEE3FA',
                  stroke: '#DEE3FA',
                })
              })
              rect.on('mouseup', e => {
                imageLeft.attr('img', require('./img/leftHover.svg'))
                imageRight.attr('img', require('./img/rightHover.svg'))
                rect.attr({
                  stroke: '#DFE0ED',
                  fill: '#DFE0ED',
                })
                rectFile.attr({
                  stroke: '#DFE0ED',
                  fill: '#DFE0ED',
                })
              })
              // 节点整体点击事件*********************************************************
              rect.on('click', e => {
                _this.regionType = cfg.category // 需判断是0:园区 1:楼栋 2:楼层 3:办公区
                // 根据节点id判断是否重复点击同一个门禁
                if (_this.title_id !== cfg.id) {
                  _this.display = _this.display ? !_this.display : _this.display
                  setTimeout(() => {
                    _this.title = cfg.name
                    _this.title_id = cfg.id
                    _this.display = !_this.display
                  }, 500)
                } else {
                  _this.display = true
                  _this.title = cfg.name
                  _this.title_id = cfg.id
                }
              })
            }
            return rect;
          },
          // 节点展开收起点击事件,判断0:园区 1:楼栋 2:楼层 3:办公区
          setState (name, value, item) {
            // 四个不同节点点击缩放颜色转换
            if (name === 'collapse') {
              const group = item.getContainer();
              const collapseIcon = group.find((e) => e.get('name') === 'collapse-icon0');
              if (collapseIcon) {
                if (!value) {
                  collapseIcon.attr({
                    img: require('./img/open1.svg')
                  });
                } else {
                  collapseIcon.attr({
                    img: require('./img/close1.svg')
                  });
                }
              }
              const collapseIcon1 = group.find((e) => e.get('name') === 'collapse-icon1');
              if (collapseIcon1) {
                if (!value) {
                  collapseIcon1.attr({
                    img: require('./img/open2.svg')
                  });
                } else {
                  collapseIcon1.attr({
                    img: require('./img/close2.svg')
                  });
                }
              }
              const collapseIcon2 = group.find((e) => e.get('name') === 'collapse-icon2');
              if (collapseIcon2) {
                if (!value) {
                  collapseIcon2.attr({
                    img: require('./img/open3.svg')
                  });
                } else {
                  collapseIcon2.attr({
                    img: require('./img/close3.svg')
                  });
                }
              }
              const collapseIcon3 = group.find((e) => e.get('name') === 'collapse-icon3');
              if (collapseIcon3) {
                if (!value) {
                  collapseIcon3.attr({
                    img: require('./img/open4.svg')
                  });
                } else {
                  collapseIcon3.attr({
                    img: require('./img/close4.svg')
                  });
                }
              }
            }
          },
        },
        'single-node',
      );
    },
    // 根据数据创建树状图节点
    createNode () {
      const container = document.getElementById('containerBox');
      const width = container.scrollWidth - 8;
      //  const width = this.topologyMapWidth;
      const height = container.scrollHeight || this.topologyMapHeight;
      // 实例化 minimap 插件
      // const minimap = new G6.Minimap({
      //   container: 'minimapBox',
      //   size: [100, 100],
      //   className: 'minimap',
      //   type: 'default',
      // });
      const graph = new G6.TreeGraph({
        container: 'containerBox',
        // plugins: [minimap],
        width,
        height,
        modes: {
          default: [
            'drag-canvas',
            'zoom-canvas',
          ],
        },
        defaultNode: {
          type: 'tree-node',
          anchorPoints: [
            [0, 0.5],
            [1, 0.5],
          ],
        },
        // nodeStateStyles: {
        //   hover: {
        //     fill: '#fff',
        //     stroke: '#fff',
        //     // shadowBlur: 20,
        //     // shadowColor: '#5666de',
        //   }
        // },
        defaultEdge: {
          type: 'flow-line',// type: 'cubic-horizontal'
          style: {
            stroke: '#C3C5D9',
          },
        },
        layout: {
          type: 'compactBox',
          direction: 'LR',
          getId: function getId (d) {
            return d.id;
          },
          getHeight: function getHeight () {
            return 260;
          },
          getWidth: function getWidth () {
            return 260;
          },
          getVGap: function getVGap () {
            return 120;
          },
          getHGap: function getHGap () {
            return 380;
          },
        },
      });
      // 设置线条样式-------------------------------------------
      G6.registerEdge('flow-line', {
        draw (cfg, group) {
          const startPoint = cfg.startPoint;
          const endPoint = cfg.endPoint;

          const { style } = cfg;
          const shape = group.addShape('path', {
            attrs: {
              stroke: style.stroke,
              endArrow: style.endArrow,
              // lineWidth: 1,
              path: [
                ['M', startPoint.x + 22, startPoint.y],
                ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, startPoint.y], // 三分之一处
                ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, endPoint.y], // 三分之二处
                ['L', endPoint.x, endPoint.y]
              ],
            },
          });

          return shape;
        },
      });
      // 节点缩放点击事件
      const handleCollapse = (e) => {
        const target = e.target;
        const id = target.get('modelId');
        const item = graph.findById(id);
        graph.setItemState(item, 'collapse', true); // 数据collapsed默认为true时,第一次点击不触发+变为-,故加上此行,
        const nodeModel = item.getModel();
        nodeModel.collapsed = !nodeModel.collapsed;
        graph.layout();
        graph.setItemState(item, 'collapse', nodeModel.collapsed);
      };
      graph.on('collapse-icon0:click', (e) => {
        handleCollapse(e);
      });
      graph.on('collapse-icon1:click', (e) => {
        handleCollapse(e);
      });
      graph.on('collapse-icon2:click', (e) => {
        handleCollapse(e);
      });
      graph.on('collapse-icon3:click', (e) => {
        handleCollapse(e);
      });
      // graph.on('node:mouseenter', e => {
      //   graph.setItemState(e.item, 'hover', true);
      // })
      // graph.on('node:mouseleave', e => {
      //   graph.setItemState(e.item, 'hover', false);
      // });
      // fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/modeling-methods.json')
      //   .then((res) => res.json())
      //   .then((data) => {
      G6.Util.traverseTree(this.topologyMapData, function (item) {
        item.id = item._id;
      });
      graph.data(this.topologyMapData);
      graph.render();
      graph.fitView();
      // });
      // 监听画布缩放
      let number = graph.getZoom()
      graph.on('viewportchange', e => {
        if (e.action !== 'zoom') return;
        const currentZoom = graph.getZoom();
        number = currentZoom;
      });
      // 获取缩小放大按钮
      var zoomOut = document.getElementById('zoom-out-button');
      var zoomIn = document.getElementById('zoom-in-button');
      // 根据目前画布的缩放比例调整缩放比例
      zoomOut.onclick = function () {
        number = number - 0.2
        if (number < 0.2) number = 0.2
        graph.zoomTo(number, { x: 300, y: 300 });
      };
      zoomIn.onclick = function () {
        number = number + 0.2
        graph.zoomTo(number, { x: 300, y: 300 });
      };
      if (typeof window !== 'undefined')
        window.onresize = () => {
          if (!graph || graph.get('destroyed')) return;
          if (!container || !container.scrollWidth || !container.scrollHeight) return;
          graph.changeSize(container.scrollWidth, container.scrollHeight);
        };
    }
  }
}
script>
<style>
.topology-diagram {
  width: 100%;
  height: 100%;
}
.topology-diagram .img-annotation {
  width: 233px;
  height: 36px;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: 0px 0px 4px 0px #e2e3ee;
  border-radius: 4px;
  /* margin-top: -48px;
  margin-left: 12px; */
  display: inline-block;
  position: absolute;
  margin-left: 12px;
  margin-top: -48px;
}
.topology-diagram .annotation-icon1 {
  width: 10px;
  height: 10px;
  background: #6271f0;
  border-radius: 2px;
  margin-top: 13px;
  margin-left: 12px;
  display: inline-block;
}
.topology-diagram .annotation-icon2 {
  width: 10px;
  height: 10px;
  background: #c3c5d9;
  border-radius: 2px;
  display: inline-block;
  margin-left: 16px;
  margin-top: 13px;
}
.topology-diagram .annotation-icon3 {
  display: inline-block;
  margin-left: 16px;
  margin-top: 13px;
}
.topology-diagram .annotation-text1 {
  width: 48px;
  height: 17px;
  font-size: 12px;
  font-family: PingFangSC-Regular, PingFang SC;
  font-weight: 400;
  color: #202340;
  line-height: 17px;
  margin-top: 9px;
  margin-left: 5px;
}
.topology-diagram .annotation-text2 {
  width: 36px;
  height: 17px;
  font-size: 12px;
  font-family: PingFangSC-Regular, PingFang SC;
  font-weight: 400;
  color: #202340;
  line-height: 17px;
  margin-left: 5px;
  margin-top: 9px;
}
.topology-diagram .annotation-text3 {
  width: 48px;
  height: 17px;
  font-size: 12px;
  font-family: PingFangSC-Regular, PingFang SC;
  font-weight: 400;
  color: #202340;
  line-height: 17px;
  margin-left: 5px;
  margin-top: 9px;
}
.topology-diagram .operation-button {
  width: 76px;
  height: 36px;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: 0px 0px 4px 0px #e2e3ee;
  border-radius: 4px;
  display: inline-block;
  position: absolute;
}
style>

你可能感兴趣的:(javascript,vue,前端,决策树,html)