|
@@ -0,0 +1,101 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container" ref="svgContainer"></div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import * as d3 from 'd3';
|
|
|
+
|
|
|
+export default {
|
|
|
+ mounted() {
|
|
|
+ const svgContainer = this.$refs.svgContainer;
|
|
|
+ const width = svgContainer.clientWidth;
|
|
|
+ const height = svgContainer.clientHeight;
|
|
|
+
|
|
|
+ const links = [
|
|
|
+ { source: "A", target: "B", value: 1 },
|
|
|
+ { source: "A", target: "C", value: 2 },
|
|
|
+ { source: "B", target: "C", value: 3 },
|
|
|
+ { source: "B", target: "D", value: 4 },
|
|
|
+ { source: "C", target: "D", value: 5 },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const nodes = [
|
|
|
+ { id: "A", x: 100, y: 100 },
|
|
|
+ { id: "B", x: 200, y: 100 },
|
|
|
+ { id: "C", x: 150, y: 200 },
|
|
|
+ { id: "D", x: 250, y: 200 },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const svg = d3.select(svgContainer).append("svg")
|
|
|
+ .attr("width", width)
|
|
|
+ .attr("height", height);
|
|
|
+
|
|
|
+ const link = svg.selectAll("line")
|
|
|
+ .data(links)
|
|
|
+ .join("line")
|
|
|
+ .attr("stroke", "black")
|
|
|
+ .attr("stroke-width", d => d.value);
|
|
|
+
|
|
|
+ const node = svg.selectAll("circle")
|
|
|
+ .data(nodes)
|
|
|
+ .join("circle")
|
|
|
+ .attr("r", 20)
|
|
|
+ .attr("fill", "red")
|
|
|
+ .call(drag(simulation));
|
|
|
+
|
|
|
+ const label = svg.selectAll("text")
|
|
|
+ .data(nodes)
|
|
|
+ .join("text")
|
|
|
+ .text(d => d.id)
|
|
|
+ .attr("x", d => d.x)
|
|
|
+ .attr("y", d => d.y);
|
|
|
+
|
|
|
+ const simulation = d3.forceSimulation(nodes)
|
|
|
+ .force("link", d3.forceLink(links).id(d => d.id))
|
|
|
+ .force("charge", d3.forceManyBody())
|
|
|
+ .force("center", d3.forceCenter(width / 2, height / 2));
|
|
|
+
|
|
|
+ simulation.on("tick", () => {
|
|
|
+ link
|
|
|
+ .attr("x1", d => d.source.x)
|
|
|
+ .attr("y1", d => d.source.y)
|
|
|
+ .attr("x2", d => d.target.x)
|
|
|
+ .attr("y2", d => d.target.y);
|
|
|
+
|
|
|
+ node
|
|
|
+ .attr("cx", d => d.x)
|
|
|
+ .attr("cy", d => d.y);
|
|
|
+
|
|
|
+ label
|
|
|
+ .attr("x", d => d.x)
|
|
|
+ .attr("y", d => d.y - 25);
|
|
|
+ });
|
|
|
+
|
|
|
+ function drag(simulation) {
|
|
|
+
|
|
|
+ function dragstarted(event) {
|
|
|
+ if (!event.active) simulation.alphaTarget(0.3).restart();
|
|
|
+ event.subject.fx = event.subject.x;
|
|
|
+ event.subject.fy = event.subject.y;
|
|
|
+ }
|
|
|
+
|
|
|
+ function dragged(event) {
|
|
|
+ event.subject.fx = event.x;
|
|
|
+ event.subject.fy = event.y;
|
|
|
+ }
|
|
|
+
|
|
|
+ function dragended(event) {
|
|
|
+ if (!event.active) simulation.alphaTarget(0);
|
|
|
+ event.subject.fx = null;
|
|
|
+ event.subject.fy = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return d3.drag()
|
|
|
+ .on("start", dragstarted)
|
|
|
+ .on("drag",
|
|
|
+ dragged)
|
|
|
+ .on("end", dragended);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|