diff --git a/plugins/insight/client/index.vue b/plugins/insight/client/index.vue index 9a27951a..768b5e1b 100644 --- a/plugins/insight/client/index.vue +++ b/plugins/insight/client/index.vue @@ -4,9 +4,7 @@ (null) const nodes = reactive(store.insight.nodes as any) const links = computed(() => store.insight.edges as any) -const forceLink = d3 - .forceLink(links.value) - .id(node => node.uid) - .distance(100) +const svgAttrs = computed(() => { + // fix all the nodes in the root element + let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity + for (const node of nodes) { + minX = Math.min(minX, node.x) + minY = Math.min(minY, node.y) + maxX = Math.max(maxX, node.x) + maxY = Math.max(maxY, node.y) + } + const vpWidth = maxX - minX + 200 + const vpHeight = maxY - minY + 200 + let transform: string + if (width.value / vpWidth > height.value / vpHeight) { + const scale = height.value / vpHeight + const realWidth = vpWidth * scale + transform = `scale(${scale}) translateX(${(width.value - realWidth) / 2 / scale}px)` + } else { + const scale = width.value / vpWidth + const realHeight = vpHeight * scale + transform = `scale(${scale}) translateY(${(height.value - realHeight) / 2 / scale}px)` + } + return { + width: vpWidth + 'px', + height: vpHeight + 'px', + viewBox: `${minX - 100} ${minY - 100} ${vpWidth} ${vpHeight}`, + style: { + transform, + transformOrigin: 'top left', + }, + } +}) + +const forceLink = d3.forceLink(links.value).id(node => node.uid) +const forceManyBody = d3.forceManyBody().strength(-200) +const forceX = d3.forceX() +const forceY = d3.forceY() const simulation = d3 .forceSimulation(nodes) .force('link', forceLink) - .force('charge', d3.forceManyBody().strength(-200)) - .force('x', d3.forceX().strength(0.05)) - .force('y', d3.forceY().strength(0.05)) + .force('charge', forceManyBody) + .force('x', forceX) + .force('y', forceY) .stop() +function resetForce() { + forceLink.distance(100) // (config.value.link.distance) + forceManyBody.strength(-200) // (-config.value.strengh.repulsion) + forceX.strength(0.1 * (height.value / (width.value + height.value) || 1)) // (config.value.strengh.centering) + forceY.strength(0.1 * (width.value / (width.value + height.value) || 1)) // (config.value.strengh.centering) + + const alphaMin = Math.exp(-6) // (-config.value.simulation.logMin) + const alphaTicks = Math.exp(7) // (config.value.simulation.logTicks) + simulation + .alpha(1) // config.value.simulation.initial) + .alphaMin(alphaMin) + .alphaDecay(1 - Math.pow(alphaMin, 1 / alphaTicks)) +} + +onMounted(() => { + resetForce() + simulation.restart() + + watchThrottled(() => [ + // config.value.link.distance, + // config.value.cluster, + // config.value.strengh, + // config.value.simulation, + width.value, + height.value, + ], () => { + resetForce() + simulation.restart() + }, { deep: true, throttle: 100, trailing: true }) +}) + watch(() => store.insight, (value) => { if (!value) return nodes.slice().forEach((source, index) => { @@ -92,17 +153,6 @@ watch(() => store.insight, (value) => { simulation.alpha(0.3).restart() }) -const ticks = 500 -const alphaMin = 0.001 - -onMounted(() => { - simulation - .alpha(1) - .alphaMin(alphaMin) - .alphaDecay(1 - Math.pow(alphaMin, 1 / ticks)) - .restart() -}) - useEventListener('mousemove', onDragMove) useEventListener('touchmove', onDragMove) useEventListener('mouseup', onDragEnd) @@ -153,12 +203,6 @@ function onDragMove(event: MouseEvent | TouchEvent) { node.fy += point.clientY - node.lastY node.lastX = point.clientX node.lastY = point.clientY - // const dist2 = node.fx ** 2 + node.fy ** 2 - // if (dist2 > this.DRAGGABLE_RADIUS ** 2) { - // const scale = this.DRAGGABLE_RADIUS / Math.sqrt(dist2) - // node.fx *= scale - // node.fy *= scale - // } } function onDragEnd(event: MouseEvent | TouchEvent) { diff --git a/plugins/insight/package.json b/plugins/insight/package.json index 0f6a8d9d..8b8674f1 100644 --- a/plugins/insight/package.json +++ b/plugins/insight/package.json @@ -1,7 +1,7 @@ { "name": "@koishijs/plugin-insight", "description": "Show plugin dependency graph for Koishi", - "version": "3.4.5", + "version": "3.5.0", "main": "lib/index.cjs", "types": "lib/index.d.ts", "exports": {