Last active
March 6, 2017 22:16
-
-
Save cjhin/d42ff3d7ec991677c3e12e6a84347b70 to your computer and use it in GitHub Desktop.
D3-Force: Split Continuous
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
country | continent | gdp | |
---|---|---|---|
Egypt | Africa | 330765 | |
South Africa | Africa | 312957 | |
Malaysia | Asia | 296219 | |
Israel | Asia | 296073 | |
Denmark | Europe | 294951 | |
Colombia | South America | 293243 | |
Singapore | Asia | 292734 | |
Philippines | Asia | 291965 | |
Pakistan | Asia | 269971 | |
Chile | South America | 240222 | |
Venezuela | South America | 239572 | |
Ireland | Europe | 238031 | |
Finland | Europe | 229671 | |
Portugal | Europe | 199077 | |
New Zealand | Australia | 172248 |
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> | |
<meta charset="utf-8"> | |
<script src="//d3js.org/d3.v4.min.js"></script> | |
<script> | |
d3.csv("data.csv", function(data) { | |
//////////////////////// | |
//////////////////////// | |
// Everything unique to this bl.ock is in this function: | |
function continuousSplit() { | |
// Create a scale to translate from continuous (numeric) data value | |
// to a point on the screen (effectively an invisible axis) | |
var continuousScale = d3.scaleLinear() | |
.domain(d3.extent(data, function(d) { return d['gdp']; })) | |
.range([width * 0.1, width * 0.9]); // multiply to give some padding on edge of screen | |
// Add some labels to show whats happening with the continuous split | |
var labels = svg.selectAll("text") | |
.data(continuousScale.domain()) // heh, scales take care of the unique, so grab from there | |
.enter().append("text") | |
.attr("class", "label") | |
.text(function(d) { return d.toLocaleString(); }) // format | |
.attr("fill", "#DDD") | |
.attr("text-anchor", "middle") | |
.attr("x", function(d) { return continuousScale(d); }) | |
.attr("y", height / 2.0 - 100); | |
var xContinuousForce = d3.forceX(function(d) { | |
return continuousScale(d['gdp']); | |
}); | |
// Interaction with button | |
var splitState = false; | |
document.getElementById("split-button").onclick = function() { | |
if(!splitState) { | |
// push the nodes towards respective spots | |
simulation.force("x", xContinuousForce); | |
// emphasize labels | |
labels.attr("fill", "#000"); | |
} else { | |
// reset | |
simulation.force("x", centerXForce); | |
labels.attr("fill", "#DDD"); | |
} | |
// Toggle state | |
splitState = !splitState; | |
// NOTE: Very important to call both alphaTarget AND restart in conjunction | |
// Restart by itself will reset alpha (cooling of simulation) | |
// but won't reset the velocities of the nodes (inertia) | |
simulation.alpha(1).restart(); | |
}; | |
} | |
//////////////////////// | |
//////////////////////// | |
//////////////////////// | |
// The rest of this file is from: | |
// https://bl.ocks.org/cjhin/4c990c57b9b05e58d56b396751f9747d | |
var svg = d3.select("svg"), | |
width = +svg.attr("width"), | |
height = +svg.attr("height"); | |
// "Electric repulsive charge", prevents overlap of nodes | |
var chargeForce = d3.forceManyBody() | |
// Keep nodes centered on screen | |
var centerXForce = d3.forceX(width / 2); | |
var centerYForce = d3.forceY(height / 2); | |
// Apply default forces to simulation | |
var simulation = d3.forceSimulation() | |
.force("charge", chargeForce) | |
.force("x", centerXForce) | |
.force("y", centerYForce); | |
var node = svg.selectAll("circle") | |
.data(data) | |
.enter().append("circle") | |
.attr("r", 10) | |
.attr("fill", "#777"); | |
// Add the nodes to the simulation, and specify how to draw | |
simulation.nodes(data) | |
.on("tick", function() { | |
// The d3 force simulation updates the x & y coordinates | |
// of each node every tick/frame, based on the various active forces. | |
// It is up to us to translate these coordinates to the screen. | |
node.attr("cx", function(d) { return d.x; }) | |
.attr("cy", function(d) { return d.y; }); | |
}); | |
// Call the function unique to this block | |
continuousSplit(); | |
}); | |
</script> | |
<style> | |
html { | |
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; | |
} | |
#split-button{ | |
position: absolute; | |
bottom: 10px; | |
right: 10px; | |
padding: 10px 20px; | |
font-size: 2em; | |
text-align: center; | |
background: #FFF; | |
border-radius: 5px; | |
border: 1px solid #DDD; | |
} | |
#split-button:hover { | |
background: #CCC; | |
cursor: pointer; | |
} | |
</style> | |
<body> | |
<div id="split-button">Toggle Split</div> | |
<svg width="960" height="500"></svg> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment