// configuration const colorVariable = 'population' const geoIDVariable = 'id' const format = d3.format(',') // Set tooltips const tip = d3 .tip() .attr('class', 'd3-tip') .offset([-10, 0]) .html( d => `Country: ${ d.properties.name }
Population: ${format( d[colorVariable] )}` ) tip.direction(function(d) { if (d.properties.name === 'Antarctica') return 'n' // Americas if (d.properties.name === 'Greenland') return 's' if (d.properties.name === 'Canada') return 'e' if (d.properties.name === 'USA') return 'e' if (d.properties.name === 'Mexico') return 'e' // Europe if (d.properties.name === 'Iceland') return 's' if (d.properties.name === 'Norway') return 's' if (d.properties.name === 'Sweden') return 's' if (d.properties.name === 'Finland') return 's' if (d.properties.name === 'Russia') return 'w' // Asia if (d.properties.name === 'China') return 'w' if (d.properties.name === 'Japan') return 's' // Oceania if (d.properties.name === 'Indonesia') return 'w' if (d.properties.name === 'Papua New Guinea') return 'w' if (d.properties.name === 'Australia') return 'w' if (d.properties.name === 'New Zealand') return 'w' // otherwise if not specified return 'n' }) tip.offset(function(d) { // [top, left] if (d.properties.name === 'Antarctica') return [0, 0] // Americas if (d.properties.name === 'Greenland') return [10, -10] if (d.properties.name === 'Canada') return [24, -28] if (d.properties.name === 'USA') return [-5, 8] if (d.properties.name === 'Mexico') return [12, 10] if (d.properties.name === 'Chile') return [0, -15] // Europe if (d.properties.name === 'Iceland') return [15, 0] if (d.properties.name === 'Norway') return [10, -28] if (d.properties.name === 'Sweden') return [10, -8] if (d.properties.name === 'Finland') return [10, 0] if (d.properties.name === 'France') return [-9, 66] if (d.properties.name === 'Italy') return [-8, -6] if (d.properties.name === 'Russia') return [5, 385] // Africa if (d.properties.name === 'Madagascar') return [-10, 10] // Asia if (d.properties.name === 'China') return [-16, -8] if (d.properties.name === 'Mongolia') return [-5, 0] if (d.properties.name === 'Pakistan') return [-10, 13] if (d.properties.name === 'India') return [-11, -18] if (d.properties.name === 'Nepal') return [-8, 1] if (d.properties.name === 'Myanmar') return [-12, 0] if (d.properties.name === 'Laos') return [-12, -8] if (d.properties.name === 'Vietnam') return [-12, -4] if (d.properties.name === 'Japan') return [5, 5] // Oceania if (d.properties.name === 'Indonesia') return [0, -5] if (d.properties.name === 'Papua New Guinea') return [-5, -10] if (d.properties.name === 'Australia') return [-15, 0] if (d.properties.name === 'New Zealand') return [-15, 0] // otherwise if not specified return [-10, 0] }) d3.select('body').style('overflow', 'hidden') const parentWidth = d3 .select('body') .node() .getBoundingClientRect().width const margin = { top: 0, right: 0, bottom: 0, left: 0 } const width = 960 - margin.left - margin.right const height = 500 - margin.top - margin.bottom const color = d3 .scaleQuantile() .range([ 'rgb(247,251,255)', 'rgb(222,235,247)', 'rgb(198,219,239)', 'rgb(158,202,225)', 'rgb(107,174,214)', 'rgb(66,146,198)', 'rgb(33,113,181)', 'rgb(8,81,156)', 'rgb(8,48,107)', 'rgb(3,19,43)' ]) const svg = d3 .select('body') .append('svg') .attr('width', width) .attr('height', height) .append('g') .attr('class', 'map') const projection = d3 .geoRobinson() .scale(148) .rotate([352, 0, 0]) .translate([width / 2, height / 2]) const path = d3.geoPath().projection(projection) svg.call(tip) queue() .defer(d3.json, 'world_countries.json') .defer(d3.tsv, 'world_population.tsv') .await(ready) function ready(error, geography, data) { data.forEach(d => { d[colorVariable] = Number(d[colorVariable].replace(',', '')) }) const colorVariableValueByID = {} data.forEach(d => { colorVariableValueByID[d[geoIDVariable]] = d[colorVariable] }) geography.features.forEach(d => { d[colorVariable] = colorVariableValueByID[d.id] }) // calculate ckmeans clusters // then use the max value of each cluster // as a break const numberOfClasses = color.range().length - 1 const ckmeansClusters = ss.ckmeans( data.map(d => d[colorVariable]), numberOfClasses ) const ckmeansBreaks = ckmeansClusters.map(d => d3.min(d)) console.log('numberOfClasses', numberOfClasses) console.log('ckmeansClusters', ckmeansClusters) console.log('ckmeansBreaks', ckmeansBreaks) // set the domain of the color scale based on our data color.domain(ckmeansBreaks) // // .domain(jenksNaturalBreaks) // // .domain(d3.extent(data, d => d[colorVariable])); // // .domain([ // 10000, // 100000, // 500000, // 1000000, // 5000000, // 10000000, // 50000000, // 100000000, // 500000000, // 1500000000 // ]); svg .append('g') .attr('class', 'countries') .selectAll('path') .data(geography.features) .enter() .append('path') .attr('d', path) .style('fill', d => { if (typeof colorVariableValueByID[d.id] !== 'undefined') { return color(colorVariableValueByID[d.id]) } return 'white' }) .style('fill-opacity', 0.8) .style('stroke', d => { if (d[colorVariable] !== 0) { return 'white' } return 'lightgray' }) .style('stroke-width', 1) .style('stroke-opacity', 0.5) // tooltips .on('mouseover', function(d) { tip.show(d) d3.select(this) .style('fill-opacity', 1) .style('stroke-opacity', 1) .style('stroke-width', 2) }) .on('mouseout', function(d) { tip.hide(d) d3.select(this) .style('fill-opacity', 0.8) .style('stroke-opacity', 0.5) .style('stroke-width', 1) }) svg .append('path') .datum(topojson.mesh(geography.features, (a, b) => a.id !== b.id)) .attr('class', 'names') .attr('d', path) }