Based on Mike Bostok's force talk.
Last active
October 9, 2018 04:18
-
-
Save jwilber/9e882b3058aeab83901fe2fde5085793 to your computer and use it in GitHub Desktop.
collision hover
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } | |
</style> | |
</head> | |
<body> | |
<script> | |
const width = window.innerWidth | |
const height = window.innerHeight | |
const nodes = d3.range(150).map(function() { return {r: Math.random() * 12 + 4, s:"hello"}; }), | |
root = nodes[0]; | |
var color = d3.scaleOrdinal().range(['#e54b4b', '#ffa987', '#f7ebe8']) | |
//root is the first node, makes an invisible fixed point in the center of the group | |
root.radius = 0; | |
root.fixed = true; | |
const forceX = d3.forceX(width / 2).strength(0.015) | |
const forceY = d3.forceY(height / 2).strength(0.015) | |
//forceSimulation is a d3 method that is well described here: https://d3indepth.com/force-layout/ | |
var force = d3.forceSimulation() | |
.velocityDecay(0.15) | |
.force("x", forceX) | |
.force("y", forceY) | |
.force("collide", d3.forceCollide().radius(function(d){ | |
// this if loop creates the empty circle in the center, by giving the first node (root), | |
// which is invisible because it has a radius of 0 from above, | |
// a huge repulsion force. Try removing the 100 and making the 50, 500. The empty circle | |
// will change sizes on each refresh. | |
if(d === root){ | |
return Math.random() * 50 + 50; | |
} | |
return d.r + 0.5; | |
}).iterations(5)) //without this line the circles will bounce as they are pulled | |
// together and then repelled continuously. This line limits that process to 5 times. | |
.nodes(nodes).on("tick", ticked); //listens for the "tick" event ? | |
// select the body and creating a new element of the SVG, and setting the height | |
// and width attributes | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
// this is where the circles are created | |
svg.selectAll("circle") | |
//this applies the nodes array for the data but cuts the root out (takes out the first | |
// node). creates a copy of the array and creates a new one with 199 elements | |
.data(nodes.slice(1)) | |
.enter().append("circle") | |
//iterates through nodes and sets the radius of each circle | |
.attr("r", function(d) { return d.r * 2; }) | |
//this sets the color as i mod 3, i increments from 0-199 | |
.style("fill", function(d, i) { return color(i % 3); }) | |
.attr('stroke-width', 1) | |
.attr('stroke', 'black') | |
function ticked(e) { | |
svg.selectAll("circle") | |
.attr("cx", function(d) { return d.x; }) | |
.attr("cy", function(d) { return d.y; }); | |
}; | |
//this section controls what happens when the mouse moves over the graphic | |
svg.on("mousemove", function() { | |
//p1 is an array that contains the x and y coordinates of the mouse | |
var p1 = d3.mouse(this); | |
// these set the first node (root) to the x and y coordinates of the mouse | |
// which causes the empty circle in the center to follow the mouse | |
root.fx = p1[0]; | |
root.fy = p1[1]; | |
//this sets how quickly the graphic resets upon each move the mouse | |
force.alphaTarget(0.5).restart();//reheat the simulation | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment