An attempt to replicate Mike's General Update Pattern, III with a force layout. The update has four parts: (1) Join, (2) Exit, (3) Update, (4) Enter.
See also: Voronoi Update Pattern II, Voronoi Update Pattern, and Modifying a Force Layout
| license: gpl-3.0 |
An attempt to replicate Mike's General Update Pattern, III with a force layout. The update has four parts: (1) Join, (2) Exit, (3) Update, (4) Enter.
See also: Voronoi Update Pattern II, Voronoi Update Pattern, and Modifying a Force Layout
| <html> | |
| <head> | |
| </head> | |
| <body> | |
| <script src="https://d3js.org/d3.v4.min.js"></script> | |
| <script src="https://unpkg.com/[email protected]/lib/jeezy.min.js"></script> | |
| <script> | |
| var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); | |
| var width = window.innerWidth, | |
| height = window.innerHeight; | |
| var nodes = randomizeData(); | |
| var simulation = d3.forceSimulation(nodes) | |
| .force("charge", d3.forceManyBody().strength(-150)) | |
| .force("forceX", d3.forceX().strength(.1)) | |
| .force("forceY", d3.forceY().strength(.1)) | |
| .force("center", d3.forceCenter()) | |
| .alphaTarget(1) | |
| .on("tick", ticked); | |
| var svg = d3.select("body").append("svg").attr("width", width).attr("height", height) | |
| g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"), | |
| node = g.append("g").attr("stroke", "#fff").attr("stroke-width", 1.5).selectAll(".node"); | |
| d3.interval(function(){ | |
| restart(randomizeData()) | |
| }, 2000); | |
| function restart(nodes) { | |
| // transition | |
| var t = d3.transition() | |
| .duration(750); | |
| // Apply the general update pattern to the nodes. | |
| node = node.data(nodes, function(d) { return d.name;}); | |
| node.exit() | |
| .style("fill", "#b26745") | |
| .transition(t) | |
| .attr("r", 1e-6) | |
| .remove(); | |
| node | |
| .transition(t) | |
| .style("fill", "#3a403d") | |
| .attr("r", function(d){ return d.size; }); | |
| node = node.enter().append("circle") | |
| .style("fill", "#45b29d") | |
| .attr("r", function(d){ return d.size }) | |
| .merge(node); | |
| // Update and restart the simulation. | |
| simulation.nodes(nodes) | |
| .force("collide", d3.forceCollide().strength(1).radius(function(d){ return d.size + 10; }).iterations(1)); | |
| } | |
| function ticked() { | |
| node.attr("cx", function(d) { return d.x; }) | |
| .attr("cy", function(d) { return d.y; }) | |
| } | |
| function randomizeData(){ | |
| var d0 = jz.arr.shuffle(alphabet), | |
| d1 = [], | |
| d2 = []; | |
| for (var i = 0; i < jz.num.randBetween(1, alphabet.length); i++){ | |
| d1.push(d0[i]); | |
| } | |
| d1.forEach(function(d){ | |
| d2.push({name: d, size: jz.num.randBetween(0, 50)}) | |
| }); | |
| return d2; | |
| } | |
| </script> | |
| </body> | |
| </html> |