Bubblemap template for d3.js





A template for bubblemaps in d3.js. This example uses all the concept described in the bubblemap section. It has a color scale highlighting continents, bubble size are mapped to frequency, a legend is provided. This example works with d3.js v4 and v6


Bubble map section

Steps:

  • This is the template I start with to build a bubblemap.

  • Data are based on my #surf project where I harvested tweets containing the #surf hashtag for a year. More about it here.

  • This template just uses all the concepts described in the bubblemap section.
|
<!DOCTYPE html> <meta charset="utf-8"> <!-- Load d3.js and the geo projection plugin --> <script src="https://d3js.org/d3.v4.js"></script> <script src="https://d3js.org/d3-geo-projection.v2.min.js"></script> <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> <!-- Create an element where the map will take place --> <svg id="my_dataviz" width="630" height="350"></svg> 
<!DOCTYPE html> <meta charset="utf-8"> <!-- Load d3.js --> <script src="https://d3js.org/d3.v6.js"></script> <!-- Create an element where the map will take place --> <svg id="my_dataviz" width="630" height="350"></svg> 
<script>// The svgvar svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height");// Map and projectionvar projection = d3.geoMercator() .center([0,20]) // GPS of location to zoom on .scale(99) // This is like the zoom .translate([ width/2, height/2 ])d3.queue() .defer(d3.json, "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson") // World shape .defer(d3.csv, "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_gpsLocSurfer.csv") // Position of circles .await(ready);function ready(error, dataGeo, data) { // Create a color scale var allContinent = d3.map(data, function(d){return(d.homecontinent)}).keys() var color = d3.scaleOrdinal() .domain(allContinent) .range(d3.schemePaired); // Add a scale for bubble size var valueExtent = d3.extent(data, function(d) { return +d.n; }) var size = d3.scaleSqrt() .domain(valueExtent) // What's in the data .range([ 1, 50]) // Size in pixel // Draw the map svg.append("g") .selectAll("path") .data(dataGeo.features) .enter() .append("path") .attr("fill", "#b8b8b8") .attr("d", d3.geoPath() .projection(projection) ) .style("stroke", "none") .style("opacity", .3) // Add circles: svg .selectAll("myCircles") .data(data.sort(function(a,b) { return +b.n - +a.n }).filter(function(d,i){ return i<1000 })) .enter() .append("circle") .attr("cx", function(d){ return projection([+d.homelon, +d.homelat])[0] }) .attr("cy", function(d){ return projection([+d.homelon, +d.homelat])[1] }) .attr("r", function(d){ return size(+d.n) }) .style("fill", function(d){ return color(d.homecontinent) }) .attr("stroke", function(d){ if(d.n>2000){return "black"}else{return "none"} }) .attr("stroke-width", 1) .attr("fill-opacity", .4) // Add title and explanation svg .append("text") .attr("text-anchor", "end") .style("fill", "black") .attr("x", width - 10) .attr("y", height - 30) .attr("width", 90) .html("WHERE SURFERS LIVE") .style("font-size", 14) // --------------- // // ADD LEGEND // // --------------- // // Add legend: circles var valuesToShow = [100,4000,15000] var xCircle = 40 var xLabel = 90 svg .selectAll("legend") .data(valuesToShow) .enter() .append("circle") .attr("cx", xCircle) .attr("cy", function(d){ return height - size(d) } ) .attr("r", function(d){ return size(d) }) .style("fill", "none") .attr("stroke", "black") // Add legend: segments svg .selectAll("legend") .data(valuesToShow) .enter() .append("line") .attr('x1', function(d){ return xCircle + size(d) } ) .attr('x2', xLabel) .attr('y1', function(d){ return height - size(d) } ) .attr('y2', function(d){ return height - size(d) } ) .attr('stroke', 'black') .style('stroke-dasharray', ('2,2')) // Add legend: labels svg .selectAll("legend") .data(valuesToShow) .enter() .append("text") .attr('x', xLabel) .attr('y', function(d){ return height - size(d) } ) .text( function(d){ return d } ) .style("font-size", 10) .attr('alignment-baseline', 'middle')}</script>
<script>// The svgconst svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height");// Map and projectionconst projection = d3.geoMercator() .center([0,20]) // GPS of location to zoom on .scale(99) // This is like the zoom .translate([ width/2, height/2 ])Promise.all([d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson"),d3.csv("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_gpsLocSurfer.csv")]).then(function (initialize) { let dataGeo = initialize[0] let data = initialize[1] // Create a color scale const color = d3.scaleOrdinal() .domain(data.map(d => d.homecontinent)) .range(d3.schemePaired); // Add a scale for bubble size const valueExtent = d3.extent(data, d => +d.n) const size = d3.scaleSqrt() .domain(valueExtent) // What's in the data .range([ 1, 50]) // Size in pixel // Draw the map svg.append("g") .selectAll("path") .data(dataGeo.features) .join("path") .attr("fill", "#b8b8b8") .attr("d", d3.geoPath() .projection(projection) ) .style("stroke", "none") .style("opacity", .3) // Add circles: svg .selectAll("myCircles") .data(data.sort((a,b) => +b.n - +a.n).filter((d,i) => i<1000)) .join("circle") .attr("cx", d => projection([+d.homelon, +d.homelat])[0]) .attr("cy", d => projection([+d.homelon, +d.homelat])[1]) .attr("r", d => size(+d.n)) .style("fill", d => color(d.homecontinent)) .attr("stroke", d=> {if (d.n>2000) {return "black"} else {return "none"} }) .attr("stroke-width", 1) .attr("fill-opacity", .4) // Add title and explanation svg .append("text") .attr("text-anchor", "end") .style("fill", "black") .attr("x", width - 10) .attr("y", height - 30) .attr("width", 90) .html("WHERE SURFERS LIVE") .style("font-size", 14) // --------------- // // ADD LEGEND // // --------------- // // Add legend: circles const valuesToShow = [100,4000,15000] const xCircle = 40 const xLabel = 90 svg .selectAll("legend") .data(valuesToShow) .join("circle") .attr("cx", xCircle) .attr("cy", d => height - size(d)) .attr("r", d => size(d)) .style("fill", "none") .attr("stroke", "black") // Add legend: segments svg .selectAll("legend") .data(valuesToShow) .join("line") .attr('x1', d => xCircle + size(d)) .attr('x2', xLabel) .attr('y1', d => height - size(d)) .attr('y2', d => height - size(d)) .attr('stroke', 'black') .style('stroke-dasharray', ('2,2')) // Add legend: labels svg .selectAll("legend") .data(valuesToShow) .join("text") .attr('x', xLabel) .attr('y', d => height - size(d)) .text(d => d) .style("font-size", 10) .attr('alignment-baseline', 'middle')})</script>

Related blocks →