Skip to content

Instantly share code, notes, and snippets.

@sbrreed
Last active October 4, 2018 03:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sbrreed/7723975174f9e958c2cf4ea25ce49a0b to your computer and use it in GitHub Desktop.
Save sbrreed/7723975174f9e958c2cf4ea25ce49a0b to your computer and use it in GitHub Desktop.
Force Simulation V4- Fully Commented
license: mit
country gdp continent
Afghanistan 18.4 Asia
Albania 12.14 Europe
Algeria 168.32 Africa
Angola 91.94 Africa
Antigua and Barbuda 1.3 Americas
Argentina 541.75 Americas
Armenia 10.75 Asia
Austria 387.3 Europe
Bahrain 31.82 Asia
Bangladesh 226.76 Asia
Barbados 4.47 Americas
Belarus 48.13 Europe
Belgium 470.18 Europe
Belize 1.77 Americas
Benin 8.93 Africa
Bhutan 2.09 Asia
Bolivia 35.7 Americas
Bosnia and Herzegovina 16.53 Europe
Botswana 10.95 Africa
Brazil 1769.6 Americas
Bulgaria 50.45 Europe
Burkina Faso 12.01 Africa
Burundi 2.74 Africa
Cabo Verde 1.68 Africa
Cambodia 19.37 Asia
Cameroon 30.87 Africa
Canada 1532.34 Americas
Central African Republic 1.78 Africa
Chad 10.44 Africa
Chile 234.9 Americas
China 11391.62 Asia
Colombia 274.14 Americas
Comoros 0.62 Africa
Costa Rica 57.69 Americas
Croatia 49.86 Europe
Czech Republic 193.54 Europe
Democratic Republic of the Congo 39.82 Africa
Denmark 302.57 Europe
Djibouti 1.89 Africa
Dominica 0.52 Americas
Dominican Republic 71.46 Americas
Ecuador 99.12 Americas
El Salvador 26.61 Americas
Equatorial Guinea 11.64 Africa
Eritrea 5.35 Africa
Estonia 23.48 Europe
Ethiopia 69.22 Africa
Fiji 4.56 Oceania
Finland 239.19 Europe
France 2488.28 Europe
Gabon 14.56 Africa
Germany 3494.9 Europe
Ghana 42.76 Africa
Greece 195.88 Europe
Grenada 1.03 Americas
Guatemala 68.39 Americas
Guinea 6.75 Africa
Guinea-Bissau 1.17 Africa
Guyana 3.46 Americas
Haiti 8.26 Americas
Honduras 20.93 Americas
Hungary 117.07 Europe
Iceland 19.44 Europe
India 2250.99 Asia
Indonesia 940.95 Asia
Iraq 156.32 Asia
Ireland 307.92 Europe
Israel 311.74 Asia
Italy 1852.5 Europe
Jamaica 13.78 Americas
Japan 4730.3 Asia
Jordan 39.45 Asia
Kazakhstan 128.11 Asia
Kenya 69.17 Africa
Kiribati 0.17 Oceania
Kuwait 110.46 Asia
Latvia 27.95 Europe
Lebanon 51.82 Asia
Lesotho 1.81 Africa
Liberia 2.17 Africa
Libya 39.39 Africa
Lithuania 42.78 Europe
Luxembourg 60.98 Europe
Madagascar 9.74 Africa
Malawi 5.47 Africa
Malaysia 302.75 Asia
Maldives 3.27 Asia
Mali 14.1 Africa
Malta 10.46 Europe
Marshall Islands 0.19 Oceania
Mauritania 4.72 Africa
Mauritius 11.74 Africa
Mexico 1063.61 Americas
Mongolia 11.16 Asia
Montenegro 4.24 Europe
Morocco 104.91 Africa
Mozambique 12.05 Africa
Myanmar 68.28 Asia
Namibia 10.18 Africa
Nepal 21.15 Asia
Netherlands 769.93 Europe
New Zealand 179.36 Oceania
Nicaragua 13.41 Americas
Niger 7.57 Africa
Nigeria 415.08 Africa
Norway 376.27 Europe
Oman 59.68 Asia
Palau 0.3 Oceania
Panama 55.23 Americas
Papua New Guinea 19.92 Oceania
Paraguay 27.32 Americas
Peru 180.29 Americas
Philippines 311.69 Asia
Poland 467.35 Europe
Portugal 205.86 Europe
Puerto Rico 100.85 Americas
Qatar 156.6 Asia
Romania 186.51 Europe
Russia 1267.75 Europe
Rwanda 8.34 Africa
Samoa 0.88 Oceania
San Marino 1.56 Europe
Saudi Arabia 637.79 Asia
Senegal 14.87 Africa
Seychelles 1.42 Africa
Sierra Leone 4.29 Africa
Singapore 296.64 Asia
Slovenia 44.12 Europe
Solomon Islands 1.22 Oceania
South Africa 280.37 Africa
South Sudan 2.63 Africa
Spain 1252.16 Europe
Sri Lanka 82.24 Asia
Sudan 94.3 Africa
Suriname 4.14 Americas
Swaziland 3.43 Africa
Sweden 517.44 Europe
Switzerland 662.48 Europe
Tajikistan 6.61 Asia
Thailand 390.59 Asia
Timor-Leste 2.5 Asia
Togo 4.52 Africa
Tonga 0.43 Oceania
Trinidad and Tobago 22.81 Americas
Tunisia 42.39 Africa
Turkey 735.72 Asia
Turkmenistan 36.57 Asia
Tuvalu 0.03 Oceania
Uganda 25.61 Africa
Ukraine 87.2 Europe
United Arab Emirates 375.02 Asia
United Kingdom 2649.89 Europe
United States 18561.93 Americas
Uruguay 54.37 Americas
Uzbekistan 66.8 Asia
Vanuatu 0.77 Oceania
Venezuela 333.72 Americas
Vietnam 200.49 Asia
Yemen 31.33 Asia
Zambia 20.57 Africa
Zimbabwe 14.19 Africa
<!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; }
.node circle {
stroke: #3a403d;
stroke-width: .5px;
}
</style>
</head>
<body>
<script>
// This block is heavily commented with the purpose of helping people learning D3 to understand each aspect of the code. There are probably more elegant ways to lay out the code but here goes.
//----------------------------------------------------------------------
//setting variables width and height to the browser window inner Width
// this is a DOM object- innerWidth is the width of browser window, window.width is the width of the device screen
// sizeDivisor will later effect the radius of each circle
// nodePadding will later effect how far apart each circle is to its neighbor
var width = window.innerWidth, height = window.innerHeight, sizeDivisor = 100, nodePadding = 2.5;
// select the body and create a new element of the SVG, set the height
// and width attributes
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
//setting up the colors, scaleOrdinal will take a discrete input and assign it colors
// according to this array
var color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb", "#e78ac3", "#a6d854", "#ffd92f", "#e5c494", "#b3b3b3"]);
//There's a good explanation of this method here: https://d3indepth.com/force-layout/
var simulation = d3.forceSimulation()
// .strength controls how close together they are pulled, unequal values will cause
// the bunch to pull at one axis or the other (try setting one to a different value)
//.x and .y control where the graphic starts originally on refresh and how the
// circles move when they are pulled on by the mouse
.force("forceX", d3.forceX().strength(.2).x(width * 0.1))
.force("forceY", d3.forceY().strength(.2).y(height * 0.1))
// this sets the center of the graphic to the center of the browser
.force("center", d3.forceCenter().x(width * .5).y(height * .5))
//this controls how quickly the circles settle down, more positive numbers make it
// more frantic and settle slower. more negative numbers make it settle faster
// forceManyBody applies the same strength force to all elements equally
// without this the circles move much faster at the beginning
.force("charge", d3.forceManyBody().strength(-50));
//pull in the csv data and check for an error and set the name of the
// data to "graph", types is a function that appears later and is being passed here
d3.csv("forceSimulation.csv", types, function(error,graph){
if (error) throw error;
originalgraph = graph
console.log("original graph", originalgraph)
// sort the nodes so that the bigger ones are at the back
// size is set later by taking the gdp of each country and dividing it by the sizeDivisor
// I think this starts by calculating the difference in size between the first two elements,
// then sorts those two. the smaller is then compared to the next element and sorted and so on
graph = graph.sort(function(a,b){return b.size - a.size; });
//update the simulation based on the data
simulation
//applies the data in graph to the nodes of simulation defined above
.nodes(graph)
//this collision control could be up in the original simulation declaration
.force("collide", d3.forceCollide()
// this strength controls how much overlap there is at the
//beginning of the simulation, bigger # = less overlap (more bounce )
.strength(1)
//d.radius is defined below where d.size is defined, the
// circles are repelled just to the point of their own radius +
// the node padding
.radius(function(d){ return d.radius + nodePadding; })
//more iterations causes it to settle down faster
.iterations(1))
// not sure what this does?
.on("tick", function(d){
node
.attr("cx", function(d){ return d.x; })
.attr("cy", function(d){ return d.y; })
});
// here we create the circles for each node in "graph"
var node = svg.append("g")
.attr("class", "node")
.selectAll("circle")
.data(graph)
.enter().append("circle")
.attr("r", function(d) { return d.radius; })
// there are a descrete number of continents so each one is assigned a color
.attr("fill", function(d) { return color(d.continent); })
.attr("cx", function(d){ return d.x; })
.attr("cy", function(d){ return d.y; })
//this calls the three drag functions below
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
});
function dragstarted(d) {
// the alphaTarget parameter controls how frantic simulation is
// both when the dragging starts and when the dragging ends. bigger # = more frantic
// not sure how this parameter works exactly?
if (!d3.event.active) simulation.alphaTarget(.03).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(.03);
d.fx = null;
d.fy = null;
}
function types(d){
//makes gdp into an integer
d.gdp = +d.gdp;
//defines d.size
d.size = +d.gdp / sizeDivisor;
//without this line a lot of the countries are so small they don't show up at all
// this sets a minimum size of 3 for everything
d.size < 3 ? d.radius = 3 : d.radius = d.size;
return d;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment