refactor process topology

This commit is contained in:
Fine 2022-09-13 22:18:09 +08:00
parent 22f3a4cd5f
commit df42b263f4
3 changed files with 52 additions and 75 deletions

View File

@ -109,7 +109,6 @@ export const networkProfilingStore = defineStore({
}, []); }, []);
this.calls = calls; this.calls = calls;
this.nodes = data.nodes; this.nodes = data.nodes;
console.log(calls);
}, },
async createNetworkTask(param: { async createNetworkTask(param: {
serviceId: string; serviceId: string;

View File

@ -17,64 +17,6 @@
import icons from "@/assets/img/icons"; import icons from "@/assets/img/icons";
import { Call } from "@/types/topology"; import { Call } from "@/types/topology";
export const linkElement = (graph: any) => {
const linkEnter = graph
.append("path")
.attr("class", "topo-call")
.attr("marker-end", "url(#arrow)")
.attr("stroke", "#97B0F8")
.attr("d", (d: Call) => linkPath(d));
return linkEnter;
};
export const anchorElement = (graph: any, funcs: any, tip: any) => {
const linkEnter = graph
.append("g")
.attr("class", "topo-line-anchor")
.on("mouseover", function (event: unknown, d: unknown) {
tip.html(funcs.tipHtml).show(d, this);
})
.on("mouseout", function () {
tip.hide(this);
})
.on("click", (event: unknown, d: unknown) => {
funcs.handleLinkClick(event, d);
});
linkEnter
.append("image")
.attr("width", 15)
.attr("height", 15)
.attr("x", (d: Call) => {
const p = getMidpoint(d);
return p[0] - 8;
})
.attr("y", (d: Call) => {
const p = getMidpoint(d);
return p[1] - 13;
})
.attr("xlink:href", (d: Call) => {
return getAnchor(d);
});
return linkEnter;
};
export const arrowMarker = (graph: any) => {
const defs = graph.append("defs");
const arrow = defs
.append("marker")
.attr("id", "arrow")
.attr("class", "topo-line-arrow")
.attr("markerUnits", "strokeWidth")
.attr("markerWidth", "8")
.attr("markerHeight", "8")
.attr("viewBox", "0 0 12 12")
.attr("refX", "10")
.attr("refY", "6")
.attr("orient", "auto");
const arrowPath = "M2,2 L10,6 L2,10 L6,6 L2,2";
arrow.append("path").attr("d", arrowPath).attr("fill", "#97B0F8");
return arrow;
};
// Control Point coordinates of quadratic Bezier curve // Control Point coordinates of quadratic Bezier curve
function computeControlPoint(ps: number[], pe: number[], arc = 0.5) { function computeControlPoint(ps: number[], pe: number[], arc = 0.5) {
const deltaX = pe[0] - ps[0]; const deltaX = pe[0] - ps[0];
@ -106,13 +48,18 @@ function quadraticBezier(
return [x, y]; return [x, y];
} }
export function getMidpoint(d: Call) { export function getMidpoint(d: Call) {
if (isNaN(d.source.x) || isNaN(d.source.y)) {
return [0, 0];
}
if (isNaN(d.target.x) || isNaN(d.target.y)) {
return [0, 0];
}
const controlPos = computeControlPoint( const controlPos = computeControlPoint(
[d.source.x, d.source.y], [d.source.x, d.source.y],
[d.target.x, d.target.y], [d.target.x, d.target.y],
0.5 0.5
); );
if (d.lowerArc) { if (d.lowerArc) {
console.log(true);
controlPos[1] = -controlPos[1]; controlPos[1] = -controlPos[1];
} }
const p = quadraticBezier( const p = quadraticBezier(
@ -124,6 +71,12 @@ export function getMidpoint(d: Call) {
return p; return p;
} }
export function linkPath(d: Call) { export function linkPath(d: Call) {
if (isNaN(d.source.x) || isNaN(d.source.y)) {
return;
}
if (isNaN(d.target.x) || isNaN(d.target.y)) {
return;
}
const controlPos = computeControlPoint( const controlPos = computeControlPoint(
[d.source.x, d.source.y - 5], [d.source.x, d.source.y - 5],
[d.target.x, d.target.y - 5], [d.target.x, d.target.y - 5],

View File

@ -33,7 +33,13 @@ limitations under the License. -->
</text> </text>
</g> </g>
<g class="nodes"> <g class="nodes">
<g v-for="(node, index) in nodeList" :key="index"> <g
v-for="(node, index) in nodeList"
:key="index"
class="topo-node"
@mouseover="showNodeTip(node)"
@mouseout="hideNodeTip"
>
<image <image
:href="icons.CUBE" :href="icons.CUBE"
style="cursor: 'move'" style="cursor: 'move'"
@ -56,7 +62,7 @@ limitations under the License. -->
v-for="(call, index) in networkProfilingStore.calls" v-for="(call, index) in networkProfilingStore.calls"
:key="index" :key="index"
class="topo-call" class="topo-call"
markerEnd="url(#arrow)" marker-end="url(#arrow)"
stroke="#97B0F8" stroke="#97B0F8"
:d="linkPath(call)" :d="linkPath(call)"
/> />
@ -71,16 +77,13 @@ limitations under the License. -->
height="15" height="15"
:x="getMidpoint(call)[0] - 8" :x="getMidpoint(call)[0] - 8"
:y="getMidpoint(call)[1] - 13" :y="getMidpoint(call)[1] - 13"
@click="handleLinkClick($event, call)"
/> />
</g> </g>
<g class="arrows"> <g class="arrows">
<defs <defs v-for="(_, index) in networkProfilingStore.calls" :key="index">
v-for="(call, index) in networkProfilingStore.calls"
:key="index"
>
<marker <marker
id="arrow" id="arrow"
class="topo-line-arrow"
markerUnits="strokeWidth" markerUnits="strokeWidth"
markerWidth="8" markerWidth="8"
markerHeight="8" markerHeight="8"
@ -95,6 +98,7 @@ limitations under the License. -->
</g> </g>
</g> </g>
</svg> </svg>
<div id="tooltip">test tooltip</div>
</div> </div>
<el-popover placement="bottom" :width="295" trigger="click"> <el-popover placement="bottom" :width="295" trigger="click">
<template #reference> <template #reference>
@ -145,12 +149,10 @@ const networkProfilingStore = useNetworkProfilingStore();
const height = ref<number>(100); const height = ref<number>(100);
const width = ref<number>(100); const width = ref<number>(100);
const chart = ref<Nullable<HTMLDivElement>>(null); const chart = ref<Nullable<HTMLDivElement>>(null);
const tip = ref<Nullable<HTMLDivElement>>(null); const tooltip = ref<Nullable<any>>(null);
const graph = ref<any>(null); const svg = ref<Nullable<any>>(null);
const node = ref<any>(null); const graph = ref<Nullable<any>>(null);
const link = ref<any>(null); const tip = ref<Nullable<any>>(null);
const anchor = ref<any>(null);
const arrow = ref<any>(null);
const oldVal = ref<{ width: number; height: number }>({ width: 0, height: 0 }); const oldVal = ref<{ width: number; height: number }>({ width: 0, height: 0 });
const config = ref<any>(props.config || {}); const config = ref<any>(props.config || {});
const diff = ref<number[]>([220, 200]); const diff = ref<number[]>([220, 200]);
@ -167,10 +169,12 @@ onMounted(() => {
}); });
async function init() { async function init() {
// svg.value = d3.select(chart.value).append("svg").attr("class", "process-svg");
if (!networkProfilingStore.nodes.length) { if (!networkProfilingStore.nodes.length) {
return; return;
} }
svg.value = d3.select(".process-svg");
graph.value = d3.select(".svg-graph");
tooltip.value = d3.select("#tooltip");
freshNodes(); freshNodes();
useThrottleFn(resize, 500)(); useThrottleFn(resize, 500)();
} }
@ -182,6 +186,10 @@ function drawGraph() {
}; };
height.value = (dom.height || 40) - 20; height.value = (dom.height || 40) - 20;
width.value = dom.width; width.value = dom.width;
diff.value[0] = (dom.width - radius * 2) / 2 + radius;
tip.value = (d3tip as any)().attr("class", "d3-tip").offset([-8, 0]);
graph.value.call(tip.value);
svg.value.call(zoom(d3, graph.value, diff.value));
} }
function clickTopology(event: any) { function clickTopology(event: any) {
@ -418,7 +426,7 @@ function resize() {
} }
async function freshNodes() { async function freshNodes() {
d3.select("svg-graph").remove(); // d3.select(".svg-graph").remove();
if (!networkProfilingStore.nodes.length) { if (!networkProfilingStore.nodes.length) {
return; return;
} }
@ -426,6 +434,18 @@ async function freshNodes() {
createLayout(); createLayout();
} }
function showNodeTip(d: any) {
const tipHtml = ` <div class="mb-5"><span class="grey">name: </span>${d.name}</div>`;
tooltip.value
.style("top", d.y + diff.value[1] - 30 + "px")
.style("left", d.x + diff.value[0] - 20 + "px");
tooltip.value.style("visibility", "visible");
}
function hideNodeTip() {
tooltip.value.style("visibility", "hidden");
}
watch( watch(
() => networkProfilingStore.nodes, () => networkProfilingStore.nodes,
() => { () => {
@ -495,4 +515,9 @@ watch(
.query { .query {
margin-left: 510px; margin-left: 510px;
} }
#tooltip {
position: absolute;
visibility: hidden;
}
</style> </style>