Reputation: 21
I am trying to run This Code with a different set of data that I am manually adding. Below is my script, but I am turning up a blank screen when I open the file. What is wrong with my code? I think there is something wrong with how I am inputting the data. I was able to have uniform bubbles appear on my screen, but when I tried to add the functions that will change the size to match the variable, the code ceased working. The first two variables in the data are placeholders to match the original code's csv file to obtain similar style results, but they don't necessarily matter. I just need the final code to output the data on a mouseover and change the size and shape of the bubbles when viewed.
<script>
// 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("#my_dataviz")
.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 },
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])
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)
Upvotes: 2
Views: 56
Reputation: 38221
You see no circles because the radius of the circle is undefined: inspecting the page will show your circles are there, but as they do not have a valid radius, they do not render.
You set the radius here:
.attr("r", function(d){ return size(d.value)})
But the items in your data array don't have a property named value
. The d
represents a single item in the data array. The linked code parses a csv with a column named value
, which creates an array where each item has a property named `value. We will need to process your data to give our data that property, maybe something like:
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]}
})
Personally, I'd generate the data with consistent field names originally rather than rely on after the fact processing that depends on ordering of key/object pairs with JavaScript object methods as that might introduce some cross browser issues, something I'm not the most familiar with.
// 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>
I've updated the radius property of the force layout to reflect the radius (and tampered with the strength to generate a better result)
Upvotes: 2