Bootstrap

vue3使用AntV X6 (图可视化引擎)历程[一]

一、案例效果

在这里插入图片描述

二、案例代码及组件抽离

  • 父组件 BloodTopology.vue
<template>
  <div>
    <TopologyCompact>
      <template #main-board-box>
        <TopologyDependent domId="featureBloodContainer" :nodeData="originalNodeData" />
      </template>

      <template #right-drawer-box>
        <RightDrawer :width="350">
          <template #rightContent> rightContent </template>
        </RightDrawer>
      </template>
    </TopologyCompact>
  </div>
</template>

<script lang="ts" setup>
import RightDrawer from '@/common/components/topologyToolKit/RightDrawer.vue';
import TopologyCompact from '@/common/components/topologyToolKit/TopologyCompact.vue';
import TopologyDependent from '@/common/components/topologyToolKit/TopologyDependent.vue';
import { onMounted, ref } from 'vue';

const originalNodeData = ref<any>({
  nodes: [],
  edges: [],
});

const edges = [
  ['1', '2'],
  ['2', '3'],
  ['2', '4'],
  ['4', '5'],
  ['4', '6'],
  ['4', '7'],
  ['4', '8'],
  ['5', '9'],
  ['6', '10'],
  ['7', '11'],
  ['8', '12'],
];
const initNodeData = () => {
  for (let i = 1; i <= 12; i++) {
    originalNodeData.value.nodes!.push({
      id: `${i}`,
      shape: 'vue-shape',
      width: 32,
      height: 32,
      label: i,
      attrs: {
        body: {
          fill: '#5F95FF',
          stroke: 'transparent',
        },
        label: {
          fill: '#ffffff',
        },
      },
    });
  }

  edges.forEach((edge: [string, string]) => {
    originalNodeData.value.edges!.push({
      source: edge[0],
      target: edge[1],
      attrs: {
        line: {
          stroke: '#A2B1C3',
          strokeWidth: 2,
        },
      },
    });
  });
};
onMounted(() => {
  initNodeData();
});
</script>

  • 子组件 TopologyDependent.vue
<template>
  <div :id="domId" class="w-full h-[95%]"></div>
</template>
<script setup lang="ts">
import { registerOption } from '@/views/featureManage/featureList/topologyToolKit/attrConfig';
import { DagreLayout, DagreLayoutOptions } from '@antv/layout';
import { Graph } from '@antv/x6';
import { register } from '@antv/x6-vue-shape';
import { nextTick, onMounted, ref } from 'vue';
import { initDependOption } from './initDependConfig';

const props = defineProps({
  domId: {
    type: String,
    default: '',
  },
  nodeData: {
    type: Object,
  },
  targetIdData: {
    type: Array as () => number[],
    required: false,
  },
});

const container = ref<any>();

register({ ...registerOption });
const initGraph = (data: any) => {
  console.log('-8888---data', data);

  container.value = document.getElementById(props.domId);
  const width = container.value?.scrollWidth;
  const height = container.value?.scrollHeight || 800;

  const graph = new Graph({
    container: container.value,
    width, // 设置图形的宽度
    height, // 设置图形的高度
    ...initDependOption.option,
  });

  const dagreLayout = new DagreLayout({ ...(initDependOption.layout as DagreLayoutOptions) });
  const model = dagreLayout.layout(data);

  console.log('111==data', data, model);

  graph.fromJSON(model);

  graph.on('node:click', ({ e, x, y, node, view }) => {
    console.log('---115-e, x, y, node, view', e, x, y, node, view);
  });
};

onMounted(() => {
  nextTick(() => {
    if (props.domId && document.getElementById(props.domId)) {
      initGraph(props.nodeData);
    }
  });
});
</script>

  • 自定义节点展示 NodeHtml.vue
<template>
  <div class="status-node">
    <div class="content" @click="handleClick">这是一段文字</div>
  </div>
</template>

<script lang="ts" setup>
const handleClick = () => {
  console.log('---handleClick');
};
</script>
<style lang="less" scoped>
.status-node {
  background-color: purple;
  height: 50px;
  width: 100px;
  border-radius: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.content {
  color: white;
  font-size: 14px;
}
</style>

  • 相关常量信息
    initDependConfig.ts
/**
 * x6初始化配置option
 */
export const initDependOption = {
  option: {
    panning: true, // 启用画布平移功能
    autoResize: true, // 启用自动调整画布大小功能
    interacting: {
      nodeMovable: false, // 禁止节点移动
    },
    mousewheel: {
      enabled: true, // 启用鼠标滚轮缩放功能
      factor: 1.1, // 缩放因子,每次滚动时缩放的比例
      maxScale: 1.5, // 最大缩放比例
      minScale: 0.5, // 最小缩放比例
    },
    background: {
      color: '#F2F7FA',
    },
  },
  layout: {
    type: 'dagre',
    rankdir: 'TB',
    align: 'UR',
    ranksep: 50,
    nodesep: 48,
  },
};

attrConfig.ts

import NodeElement from '@/views/featureManage/featureList/topologyToolKit/NodeHtml.vue';
/**
 * 自定义注册节点配置
 */
export const registerOption = {
  shape: 'vue-shape',
  width: 100,
  height: 100,
  component: NodeElement,
};

三、控制台打印效果

在这里插入图片描述

;