1
0
mirror of https://github.com/d3/d3.git synced 2025-12-08 19:46:24 +00:00
d3/docs/components/ExampleLinkForce.vue
2024-09-20 18:59:04 +00:00

90 lines
2.4 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import * as d3 from "d3";
import {ref, onMounted, onUnmounted} from "vue";
const container = ref();
const width = 688;
const height = 540;
const n = 20;
const nodes = Array.from({length: n * n}, (_, i) => ({index: i}));
const links = [];
for (let y = 0; y < n; ++y) {
for (let x = 0; x < n; ++x) {
if (y > 0) links.push({source: (y - 1) * n + x, target: y * n + x});
if (x > 0) links.push({source: y * n + (x - 1), target: y * n + x});
}
}
let simulation;
const drag = d3.drag()
.subject(({x, y}) => simulation.find(x - width / 2, y - height / 2, 40))
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
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;
}
onMounted(() => {
const svg = d3.select(container.value)
.call(drag);
simulation = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-40))
.force("link", d3.forceLink(links).strength(1).distance(10).iterations(10))
.force("x", d3.forceX())
.force("y", d3.forceY())
.on("tick", ticked);
const link = svg.append("g")
.attr("stroke", "currentColor")
.attr("stroke-opacity", 0.3)
.selectAll()
.data(links)
.join("line");
const node = svg.append("g")
.attr("fill", "currentColor")
.attr("stroke", "var(--vp-c-bg-alt)")
.selectAll()
.data(nodes)
.join("circle")
.attr("r", 2.5);
function ticked() {
node.attr("cx", (d) => d.x).attr("cy", (d) => d.y);
link.attr("x1", (d) => d.source.x).attr("y1", (d) => d.source.y);
link.attr("x2", (d) => d.target.x).attr("y2", (d) => d.target.y);
}
});
onUnmounted(() => {
simulation?.stop();
});
</script>
<template>
<div style="margin: 1em 0;">
<svg :width="width" :height="height" :viewBox="[-width / 2, -height / 2, width, height].join(' ')" fill="currentColor" style="overflow: visible; position: relative; z-index: 2; max-width: 100%; height: auto;" ref="container"></svg>
<a href="https://observablehq.com/@d3/force-directed-lattice" style="font-size: smaller;" target="_blank">Fork </a>
</div>
</template>