This demonstrates forceLink.iterations, which strengthens d3-force’s link constraint by applying the constraint multiple times per simulation step.
forked from mbostock's block: Force-Directed Lattice
created in blockbuilder.
| license: gpl-3.0 | |
| height: 960 |
This demonstrates forceLink.iterations, which strengthens d3-force’s link constraint by applying the constraint multiple times per simulation step.
forked from mbostock's block: Force-Directed Lattice
created in blockbuilder.
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <canvas width="960" height="960"></canvas> | |
| <script src="https://d3js.org/d3.v4.min.js"></script> | |
| <script> | |
| var n = 20; | |
| var nodes = d3.range(n * n).map(function(i) { | |
| return { | |
| index: i, | |
| x: 20*(i % n), | |
| y: 20*Math.floor(i / n)-450 | |
| }; | |
| }); | |
| var links = []; | |
| for (var y = 0; y < n; ++y) { | |
| for (var 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}); | |
| } | |
| } | |
| var simulation = d3.forceSimulation(nodes) | |
| // .force("charge", d3.forceManyBody().strength(-30)) | |
| .force("link", d3.forceLink(links).strength(1).distance(20).iterations(10)) | |
| .on("tick", ticked); | |
| var canvas = document.querySelector("canvas"), | |
| context = canvas.getContext("2d"), | |
| width = canvas.width, | |
| height = canvas.height; | |
| d3.select(canvas) | |
| .call(d3.drag() | |
| .container(canvas) | |
| .subject(dragsubject) | |
| .on("start", dragstarted) | |
| .on("drag", dragged) | |
| .on("end", dragended)); | |
| function ticked() { | |
| context.clearRect(0, 0, width, height); | |
| context.save(); | |
| context.translate(width / 2, height / 2); | |
| context.beginPath(); | |
| links.forEach(drawLink); | |
| context.strokeStyle = "#aaa"; | |
| context.stroke(); | |
| context.beginPath(); | |
| nodes.forEach(drawNode); | |
| context.fill(); | |
| context.strokeStyle = "#fff"; | |
| context.stroke(); | |
| context.restore(); | |
| } | |
| function dragsubject() { | |
| return simulation.find(d3.event.x - width / 2, d3.event.y - height / 2); | |
| } | |
| function dragstarted() { | |
| if (!d3.event.active) simulation.alphaTarget(0.3).restart(); | |
| d3.event.subject.fx = d3.event.subject.x; | |
| d3.event.subject.fy = d3.event.subject.y; | |
| } | |
| function dragged() { | |
| d3.event.subject.fx = d3.event.x; | |
| d3.event.subject.fy = d3.event.y; | |
| } | |
| function dragended() { | |
| if (!d3.event.active) simulation.alphaTarget(0); | |
| d3.event.subject.fx = null; | |
| d3.event.subject.fy = null; | |
| } | |
| function drawLink(d) { | |
| context.moveTo(d.source.x, d.source.y); | |
| context.lineTo(d.target.x, d.target.y); | |
| } | |
| function drawNode(d) { | |
| context.moveTo(d.x + 3, d.y); | |
| context.arc(d.x, d.y, 3, 0, 2 * Math.PI); | |
| } | |
| </script> |
| �PNG | |