// set the dimensions and margins of the graph
var width = 500
var height = 500
// append the svg object to the body of the page
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
// create dummy data -> just one element per circle
var data = [
{ "Asia": "Southeast Asia", "Burundi": 3.14 },
{ "Asia": "Southeast Asia", "South Sudan": 3.39 },
{ "Asia": "Southeast Asia", "Malawi": 7.63 },
{ "Asia": "Southeast Asia", "Mozambique": 14.22 },
{ "Asia": "Southeast Asia", "Democratic Republic of the Congo": 40.92 },
{ "Asia": "Southeast Asia", "Central African Republic": 2.32 },
{ "Asia": "Southeast Asia", "Afghanistan": 19.44 },
{ "Asia": "Southeast Asia", "Madagascar": 14.26 },
{ "Asia": "Southeast Asia", "Sierra Leone": 4.14},
{ "Asia": "Southeast Asia", "Niger": 12.97},
{ "Asia": "Southeast Asia", "Eritrea": 2.08},
{ "Asia": "Southeast Asia", "Chad": 10.51},
{ "Asia": "Southeast Asia", "Yemen": 19.24},
{ "Asia": "Southeast Asia", "Liberia": 3.31},
{ "Asia": "Southeast Asia", "Togo": 5.71},
{ "Asia": "Southeast Asia", "Haiti": 8.35},
{ "Asia": "Southeast Asia", "Sudan": 32.21},
{ "Asia": "Southeast Asia", "Gambia": 1.8},
{ "Asia": "Southeast Asia", "Guinea-Bissau": 1.51},
{ "Asia": "Southeast Asia", "Burkina Faso": 16.07},
{ "Americas": "Caribbean", "Jeff Bezos": 189.3},
{ "Americas": "Caribbean", "Elon Musk": 182.2},
{ "Americas": "Caribbean", "Bernard Arnault": 157.7},
{ "Americas": "Caribbean", "Bill Gates": 123.7},
{ "Americas": "Caribbean", "Mark Zuckerberg": 95.7},
{ "Americas": "Caribbean", "Warren Buffet": 91.7},
{ "Americas": "Caribbean", "Larry Page": 90.9},
{ "Americas": "Caribbean", "Zhong Shanshan": 89.8},
{ "Americas": "Caribbean", "Sergey Brin": 88.2},
{ "Americas": "Caribbean", "Larry Elison": 85.2},
{ "Americas": "Caribbean", "Steve Ballmer": 80.4},
{ "Americas": "Caribbean", "Mukesh Ambani": 78},
{ "Americas": "Caribbean", "Francois Bettencourt Meyers": 75.6},
{ "Americas": "Caribbean", "Armando Ortega": 74},
{ "Americas": "Caribbean", "Colin Zheng Huang": 69.1},
{ "Americas": "Caribbean", "Alice Walton": 65.1},
{ "Americas": "Caribbean", "Jim Walton": 64.9},
{ "Americas": "Caribbean", "Rob Walton": 64.6},
{ "Americas": "Caribbean", "Carlos Slim Helu": 64},
{ "Americas": "Caribbean", "Jack Ma": 62},
{ "Africa": "Western Africa", "Total of 20 Poorest Countries": 232.22},
{ "Europe": "Southern Europe", "Wealth Gained by American Billionaires during Coronavirus Pandemic": 1010}]
data = data.map(function(d) {
let entries = Object.entries(d);
return {region: entries[0][0] ,subregion: entries[0][1] ,country: entries[1][0], value: entries[1][1]}
})
var color = d3.scaleOrdinal()
.domain(["Asia", "Europe", "Africa", "Oceania", "Americas"])
.range(d3.schemeSet1);
// Size scale for countries
var size = d3.scaleLinear()
.domain([0, 1010])
.range([7,55])
// create a tooltip
var Tooltip = d3.select("#my_dataviz")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px")
// Three function that change the tooltip when user hover / move / leave a cell
var mouseover = function(d) {
Tooltip
.style("opacity", 1)
}
var mousemove = function(d) {
Tooltip
.html('<u>' + d.key + '</u>' + "<br>" + d.value + " billion dollars")
.style("left", (d3.mouse(this)[0]+20) + "px")
.style("top", (d3.mouse(this)[1]) + "px")
}
var mouseleave = function(d) {
Tooltip
.style("opacity", 0)
}
// Initialize the circle: all located at the center of the svg area
var node = svg.append("g")
.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("class", "node")
.attr("r", function(d){ return size(d.value)})
.attr("cx", width / 2)
.attr("cy", height / 2)
.style("fill", function(d){ return color(d.region)})
.style("fill-opacity", 0.8)
.attr("stroke", "black")
.style("stroke-width", 1)
.on("mouseover", mouseover) // What to do when hovered
.on("mousemove", mousemove)
.on("mouseleave", mouseleave)
.call(d3.drag() // call specific function when circle is dragged
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
// Features of the forces applied to the nodes:
var simulation = d3.forceSimulation()
.force("center", d3.forceCenter().x(width / 2).y(height / 2)) // Attraction to the center of the svg area
.force("charge", d3.forceManyBody().strength(0.5)) // Nodes are attracted one each other of value is > 0
.force("collide", d3.forceCollide().strength(0.5).radius(function(d){ return size(d.value)+5}).iterations(1)) // Force that avoids circle overlapping
// Apply these forces to the nodes and update their positions.
// Once the force algorithm is happy with positions ('alpha' value is low enough), simulations will stop.
simulation
.nodes(data)
.on("tick", function(d){
node
.attr("cx", function(d){ return d.x; })
.attr("cy", function(d){ return d.y; })
});
// What happens when a circle is dragged?
function dragstarted(d) {
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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>