<template>
<div
v-if="reRender"
id="container"
v-loading="loading"
:element-loading-text="$t('public.please_wait')"
element-loading-spinner="el-icon-loading"
/>
</div>
</template>
<script>
import G6 from "@antv/g6";
import { getTopology } from "@/api/getTopology";
export default {
data() {
return {
reRender: true,
loading: false,
};
},
watch: {
// 切换到其他拓扑图时重新渲染
$route(n) {
this.reRender = false;
this.$nextTick(() => {
this.reRender = true;
});
this.getData(n.query.id);
},
},
mounted() {
this.$nextTick(() => {
this.getData(this.$route.query.id);
});
},
methods: {
async getData(id) {
// 自定义节点
G6.registerNode(
// 自定义节点名称
"rect-auto",
{
draw(cfg, group) {
const { label, style } = cfg;
// 画一个默认矩形
const rect = group.addShape("rect", {
attrs: {
width: 1,
height: 1,
x: 0,
y: 0,
radius: 4,
lineWidth: 1,
stroke: "#409eff",
fill: "#f0f7ff",
// 来自实例配置defaultNode选项的style
...style,
},
name: "rect-shape",
});
// 画一个文本
const text = group.addShape("text", {
attrs: {
x: 0,
y: 0,
text: label,
textAlign: "left",
textBaseline: "middle",
...style,
...style.labelCfg.style,
},
name: "text-shape",
});
const labelBox = text.getBBox();
// 矩形左右留白各10px,上下留白各6px
rect.attr({
width: labelBox.width + 20,
height: labelBox.height + 12,
});
// 文本位置,以矩形左上角为原点
text.attr({
x: 10,
y: labelBox.height / 2 + 6,
});
// 返回该矩形
return rect;
},
},
// 继承自已有rect图形
"rect"
);
this.loading = true;
// 后端返回标准的数据格式
const res = await getTopology(id);
const data = res.data;
const container = document.getElementById("container");
const width = container.scrollWidth;
const height = container.scrollHeight || 500;
// 实例配置,搜索关键字查看具体释义
const graph = new G6.Graph({
container: "container",
width,
height,
controlPoints: false,
fitView: true,
fitViewPadding: 10,
modes: {
default: [
{
type: "activate-relations",
trigger: "click",
activeState: "active",
inactiveState: "inactive",
},
{
type: "zoom-canvas",
},
{
type: "drag-canvas",
},
{
type: "click-select",
},
],
},
layout: {
type: "dagre",
preventOverlap: true,
nodeSize: 100,
nodesep: 50,
ranksep: 10,
},
animate: true,
defaultNode: {
type: "rect-auto",
anchorPoints: [
[0.5, 0],
[0.5, 1],
],
style: {
cursor: "pointer",
labelCfg: {
style: {
fill: "#000",
},
},
},
},
defaultEdge: {
size: 1,
color: "#ccc",
type: "line",
style: {
endArrow: {
path: G6.Arrow.triangle(6, 6, 0),
// path: "M 0,0 L 8,4 L 8,-4 Z",
fill: "#ccc",
},
},
},
nodeStateStyles: {
active: {
fill: "#fff",
stroke: "#409eff",
lineWidth: 1,
shadowColor: "#409eff",
shadowBlur: 10,
shadowOffsetX: 1,
shadowOffsetY: 1,
"text-shape": {
fill: "#000",
},
},
inactive: {
opacity: 0.6,
},
hover: {
fill: "#fff",
lineWidth: 1,
stroke: "#409eff",
shadowColor: "#409eff",
shadowBlur: 10,
shadowOffsetX: 1,
shadowOffsetY: 1,
"text-shape": {
fill: "#000",
},
},
selected: {
fill: "#fff",
lineWidth: 1,
stroke: "#f56c6c",
shadowColor: "#f56c6c",
shadowBlur: 10,
shadowOffsetX: 1,
shadowOffsetY: 1,
"text-shape": {
fill: "#000",
},
},
},
edgeStateStyles: {
active: {
stroke: "#409eff",
endArrow: {
path: G6.Arrow.triangle(6, 6, 0),
fill: "#409eff",
},
},
inactive: {
opacity: 0.6,
endArrow: {
path: G6.Arrow.triangle(6, 6, 0),
fill: "#ccc",
opacity: 0.6,
},
},
},
});
graph.data(data);
graph.render();
// 节点只有一个时太大,缩放一下
graph.on("afterrender", () => {
if (data.nodes.length === 1) {
graph.zoom(0.2, { x: width / 2, y: height / 2 });
}
});
// 双击节点进行跳转
graph.on("dblclick", (evt) => {
const itemData = evt.item._cfg.model;
const { level, id } = itemData;
this.$emit("changeState", [id]);
if (level === 2) {
this.$router.push({
name: "groupDetail",
query: {
id,
},
});
} else if (level === 3) {
this.$router.push({
name: "serviceInfo",
query: {
id,
},
});
}
});
// 触发hover样式配置
graph.on("node:mouseenter", (evt) => {
const { item } = evt;
graph.setItemState(item, "hover", true);
});
// 关闭hover样式
graph.on("node:mouseleave", (evt) => {
const { item } = evt;
graph.setItemState(item, "hover", false);
});
this.$nextTick(() => {
this.loading = false;
});
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 - 30);
};
}
},
},
};
</script>
<style lang="scss" scoped>
#container {
height: calc(100vh - 310px);
}
</style>
网友评论