【VUEv2.6.11引入antv/g6】

@案例1
在这里插入图片描述

VUEv2.6.11引入antv/g6

在这里插入图片描述
在这里插入图片描述

1. 安装antv/g6@3.x

npm install @antv/g6@3.x --save

2. vue2.6.11使用antv/g6案例1

<template>
  <div class="topo-container">
    <!-- 左侧控制面板 -->
    <div class="left-panel">
      <div class="panel-header">
        <h3>控制面板</h3>
      </div>
      <div class="panel-content">
        <div class="control-group">
          <h4>节点操作</h4>
          <button @click="addNode" class="control-btn">添加节点</button>
          <button @click="removeNode" class="control-btn">删除节点</button>
        </div>
        
        <div class="control-group">
          <h4>布局控制</h4>
          <button @click="changeLayout('force')" class="control-btn">力导向布局</button>
          <button @click="changeLayout('circular')" class="control-btn">环形布局</button>
          <button @click="changeLayout('grid')" class="control-btn">网格布局</button>
          <button @click="changeLayout('radial')" class="control-btn">径向布局</button>
        </div>
        
        <div class="control-group">
          <h4>方向布局</h4>
          <button @click="changeLayout('next')" class="control-btn">下个布局</button>
        </div>
        
        <div class="control-group">
          <h4>链路布局</h4>
         
        </div>
        
        <div class="control-group">
          <h4>视图控制</h4>
          <button @click="fitView" class="control-btn">适应视图</button>
          <button @click="zoomIn" class="control-btn">放大</button>
          <button @click="zoomOut" class="control-btn">缩小</button>
        </div>
        
        <div class="control-group">
          <h4>节点信息</h4>
          <div class="node-info">
            <p>总节点数: {{ nodeCount }}</p>
            <p>总边数: {{ edgeCount }}</p>
          </div>
        </div>
      </div>
    </div>
    
    <!-- 右侧图表显示区域 -->
    <div class="right-panel">
      <div id="g6-container" class="g6-chart"></div>
    </div>
  </div>
</template>

<script>
import G6 from '@antv/g6';

export default {
  name: 'G6Chart',
  data() {
    return {
      graph: null,
      nodeCount: 18,
      edgeCount: 17,
      nodeIdCounter: 19,
      layoutIndex: 0,
      graphOpt:{},
      topoData:null
    };
  },
  methods: {
    initGraph() {
      const container = document.getElementById('g6-container');
      const width = container.scrollWidth;
      const height = container.scrollHeight || 500;

      this.graphOpt={
        container: 'g6-container',
        width,
        height,
        modes: {
          default: ['drag-canvas', 'zoom-canvas', 'drag-node'],
        },
        animate: true,
        defaultNode: {
          type: 'rect',// circle
          size: [50],
          style: {
            fill: '#9ca9e8',
            stroke: '#5b6c9f',
          },
          labelCfg: {
            style: {
              fill: '#fff',
            },
          },
        },
        defaultEdge: {
          type: 'line',
        },
      };

      this.graph = new G6.Graph(this.graphOpt);
     
      this.topoData = {
        nodes: [
          { id: '1', label: '节点1' },
          { id: '2', label: '节点2' },
          { id: '3', label: '节点3' },
          { id: '4', label: '节点4' },
          { id: '5', label: '节点5' },
          { id: '6', label: '节点6' },
          { id: '7', label: '节点7' },
          { id: '8', label: '节点8' },
          { id: '9', label: '节点9' },
          { id: '10', label: '节点10' },
          { id: '11', label: '节点11' },
          { id: '12', label: '节点12' },
          { id: '13', label: '节点13' },
          { id: '14', label: '节点14' },
          { id: '15', label: '节点15' },
          { id: '16', label: '节点16' },
          { id: '17', label: '节点17' },
          { id: '18', label: '节点18' },
        ],
        edges: [
          { source: '1', target: '2' },
          { source: '2', target: '3' },
          { source: '3', target: '4' },
          { source: '4', target: '3' },
          { source: '5', target: '4' },
          { source: '6', target: '3' },
          { source: '6', target: '7' },
          { source: '7', target: '8' },
          { source: '8', target: '9' },
          { source: '9', target: '10' },
          { source: '10', target: '11' },
          { source: '11', target: '12' },
          { source: '12', target: '13' },
          { source: '13', target: '14' }, 
          { source: '14', target: '15' },
          { source: '15', target: '2' },
          { source: '16', target: '4' },
          { source: '17', target: '5' },
          { source: '18', target: '6' },
        ],
      };
      
      this.graph.data(this.topoData);
      this.graph.render();
    },
    
    addNode() {
      const newNodeId = `node${this.nodeIdCounter}`;
      const newNode = {
        id: newNodeId,
        label: `节点${this.nodeIdCounter}`
      };
      
      this.graph.addItem('node', newNode);
      this.nodeIdCounter++;
      this.nodeCount++;
      
      // 如果有节点,连接到第一个节点
      const nodes = this.graph.getNodes();
      if (nodes.length > 1) {
        const firstNode = nodes[0];
        this.graph.addItem('edge', {
          source: firstNode.getID(),
          target: newNodeId
        });
        this.edgeCount++;
      }
    },
    
    removeNode() {
      const nodes = this.graph.getNodes();
      if (nodes.length > 0) {
        const lastNode = nodes[nodes.length - 1];
        this.graph.removeItem(lastNode);
        this.nodeCount--;
        
        // 删除相关的边
        const edges = this.graph.getEdges();
        edges.forEach(edge => {
          if (edge.getModel().source === lastNode.getID() || 
              edge.getModel().target === lastNode.getID()) {
            this.graph.removeItem(edge);
            this.edgeCount--;
          }
        });
      }
    },
     
    changeLayout(layoutType) {
      let layoutConfig = {};
      let layoutArr = ['random', 'force', 'dagre', 'circular', 'grid', 'radial', 'mds', 'fruchterman'];
      
      // random, radial, mds, circular, fruchterman, force, dagre
      switch(layoutType) {
        case 'next':
          if(layoutArr[(this.layoutIndex%10)] === 'dagre'){
            layoutConfig = {
              type: 'dagre',
              rankdir: 'LR',
              align: 'LR',
              ranksep: 50,
              nodesep: 5, 
            };
          }else{
              layoutConfig = {
                type: layoutArr[(this.layoutIndex%10)],
                nodesep: 30,
                ranksep: 10,
              };
          }
          console.log(layoutArr[(this.layoutIndex%10)])
          this.layoutIndex++;
          break;
        case 'force':
          layoutConfig = {
            type: 'force',
            preventOverlap: true,
            linkDistance: 100,
            nodeStrength: 30,
            edgeStrength: 0.1,
          };
          break;
        case 'dagre':
          layoutConfig = {
            type: 'dagre',
            rankdir: 'TB',
            nodesep: 30,
            ranksep: 50,
          };
          break;
        case 'circular':
          layoutConfig = {
            type: 'circular',
            radius: 200,
          };
          break;
        case 'grid':
          layoutConfig = {
            type: 'grid',
            rows: 4,
            cols: 5,
            nodeSize: 50,
            preventOverlap: true,
          };
          break;
        case 'radial':
          layoutConfig = {
            type: 'radial',
            unitRadius: 100,
            preventOverlap: true,
            nodeSize: 50,
          };
          break; 
     
      }
      
      this.graph.updateLayout(layoutConfig);
    },
    
    fitView() {
      this.graph.fitView();
    },
    
    zoomIn() {
      const current = this.graph.getZoom();
      this.graph.zoomTo(current * 1.2);
    },
    
    zoomOut() {
      const current = this.graph.getZoom();
      this.graph.zoomTo(current * 0.8);
    },
    
    changeEdgeLayout(layoutType) {
      let edgeConfig = {};
      
      switch(layoutType) {
        case 'horizontal':
          // 设置边为曲线,使链路呈现水平方向的弯曲效果
          edgeConfig = {
            type: 'quadratic',
            style: {
              lineWidth: 2,
              stroke: '#888'
            }
          };
          // 更新所有边的类型和样式
          const edges = this.graph.getEdges();
          edges.forEach(edge => {
            this.graph.updateItem(edge, {
              type: 'quadratic',
              style: {
                lineWidth: 2,
                stroke: '#888'
              }
            });
          });
          break;
          
        case 'vertical':
          // 设置边为垂直方向的曲线
          edgeConfig = {
            type: 'cubic-horizontal',  // 或者使用其他类型的曲线
            style: {
              lineWidth: 2,
              stroke: '#888'
            }
          };
          // 更新所有边的类型和样式
          const edgesVertical = this.graph.getEdges();
          edgesVertical.forEach(edge => {
            this.graph.updateItem(edge, {
              type: 'cubic-horizontal',
              style: {
                lineWidth: 2,
                stroke: '#888'
              }
            });
          });
          break;
          
        case 'polyline':
          // 折线样式
          const edgesPolyline = this.graph.getEdges();
          edgesPolyline.forEach(edge => {
            this.graph.updateItem(edge, {
              type: 'polyline',
              style: {
                lineWidth: 2,
                stroke: '#888'
              }
            });
          });
          break;
          
        case 'orthogonal':
          // 正交边样式
          const edgesOrthogonal = this.graph.getEdges();
          edgesOrthogonal.forEach(edge => {
            this.graph.updateItem(edge, {
              type: 'cubic',
              style: {
                lineWidth: 2,
                stroke: '#888'
              }
            });
          });
          break;
      }
      
      // 重新绘制图形
      this.graph.refresh();
    }
  },
  mounted() {
    this.initGraph();
  },
  beforeDestroy() {
    if (this.graph) {
      this.graph.destroy();
    }
  }
};
</script>

<style scoped>
.topo-container {
  display: flex;
  width: 100%;
  height: 100vh; 
}

.left-panel {
  width: 250px;
  background-color: #ffffff;
  border-right: 1px solid #e0e0e0;
  box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
}

.panel-header {
  padding: 20px;
  background-color: #4a90e2;
  color: white;
  text-align: center;
}

.panel-header h3 {
  margin: 0;
  font-size: 18px;
}

.panel-content {
  flex: 1;
  padding: 20px;
  overflow-y: auto;
}

.control-group {
  margin-bottom: 25px;
}

.control-group h4 {
  margin: 0 0 15px 0;
  color: #333;
  font-size: 16px;
  border-bottom: 1px solid #eee;
  padding-bottom: 8px;
}

.control-btn {
  display: block;
  width: 100%;
  padding: 10px 15px;
  margin-bottom: 10px;
  background-color: #4a90e2;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s;
}

.control-btn:hover {
  background-color: #357abd;
}

.control-btn:last-child {
  margin-bottom: 0;
}

.node-info {
  background-color: #9ca9e8;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #9ca9e8;
}

.node-info p {
  margin: 8px 0;
  font-size: 14px;
  color: #555;
}

.right-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.g6-chart {
  flex: 1;
  width: 100%;
  height: 100%; 
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值