map = {
const width = 1200; const height = 700;
const projection = d3Geo.geoEqualEarth()
.center([0,20])
.scale(250)
.translate([ 550, 250 ]);
const path = d3.geoPath(projection);
const svg = d3.create("svg")
.attr("class", "map")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height]);
const valueExtent = d3.extent(chronoData, d => +d["Total Number of Dead and Missing"])
const size = d3.scaleSqrt()
.domain(valueExtent)
.range([ 1, 40])
svg.append("g")
.selectAll("path")
.data(land.features)
.enter()
.append("path")
.attr("fill", "#b8b8b8")
.attr("d", d3.geoPath()
.projection(projection)
)
.style("stroke", "none")
.style("opacity", .3)
svg.append("path")
.datum(countrymesh)
.attr("fill", "none")
.attr("stroke", "white")
.attr("d", path);
// Add circles:
svg.selectAll("myCircles")
//.data(chronoData.sort((a,b) => (+b["Total Number of Dead and Missing"] - +a["Total Number of Dead and Missing"] )).filter((d,i) => i<1000 ))
.data(chronoData)
.enter()
.append("circle")
.attr("class", d => ("bubble year-" + d["Incident Year"]) )
.attr("cx", d => projection([+d["Coordinates"].split(", ")[1], +d["Coordinates"].split(", ")[0]])[0] )
.attr("cy", d => projection([+d["Coordinates"].split(", ")[1], +d["Coordinates"].split(", ")[0]])[1] )
.attr("r", d => size(+d["Total Number of Dead and Missing"]) )
.style("fill", "#8B2323" )
.attr("stroke", "#D08770" )
.attr("stroke-width", 1)
.attr("fill-opacity", .3)
.append("title") // Tooltips
.text(d => `${d["Incident Date"]}\n${d["Incident Type"]} in ${d["Country of Incident"]}\n${d["Total Number of Dead and Missing"]} victims`);
// Add title and explanation
svg
.append("text")
.attr("text-anchor", "end")
.style("fill", "#8B2323")
.attr("x", width/3.1)
.attr("y", 30)
.attr("width", 150)
.html("WHERE MIGRANTS DIED OR WENT MISSING")
.attr("font-size", 18);
const duration = "between " + yearExtent[0] + " and " + yearExtent[1];
const totalNumber = d3.format(",.5r")(totalMigrantsDiedMissing);
svg
.append("text")
.attr("text-anchor", "end")
.style("fill", "#0F1012")
.attr("x", width/1.3)
.attr("y", height-150)
.attr("width", 100)
.html(totalNumber + " migrants died or went missing " + duration)
.attr("font-size", 20)
.attr("font-style", "italic");
// --------------- //
// ADD LEGEND //
// --------------- //
// Construct the radius scale.
// Add legend: circles
const valuesToShow = [10,100, 500, 1000];
const xCircle = 70;
const xLabel = 120;
svg
.selectAll("legend")
.data(valuesToShow)
.enter()
.append("circle")
.attr("cx", xCircle)
.attr("cy", d => (height/1.055 - size(d)) )
.attr("r", d => size(d) )
.style("fill", "none")
.attr("stroke", "#D08770");
// Add legend: segments
svg
.selectAll("legend")
.data(valuesToShow)
.enter()
.append("line")
.attr('x1', d => (xCircle + size(d)) )
.attr('x2', xLabel)
.attr('y1', d => (height/1.055 - size(d)*1.5) )
.attr('y2', d => (height/1.055 - size(d)*1.5) )
.attr('stroke', 'black')
.style('stroke-dasharray', ('2,2'));
// Add legend: labels
svg
.selectAll("legend")
.data(valuesToShow)
.enter()
.append("text")
.attr('x', xLabel + 5)
.attr('y', d => (height/1.055 - size(d)*1.5 + 1) )
.text( d => d + " people")
.style("font-size", 5)
.attr('alignment-baseline', 'middle');
return svg.node();
}