|
var tip = d3.tip() |
|
.attr('class', 'd3-tip') |
|
.offset([-10, 0]) |
|
.html(function(d) { |
|
return d.NAME+ ': '+ |
|
d.murder +' ('+ Math.round(d.murder_rate)+' per 100k)'+ |
|
'<div>2015 Population: '+ d.pop_2015+ '</div>'; |
|
}); |
|
|
|
|
|
var svg = d3.select('.svg-container').append('svg') |
|
.attr('xmlns', 'http://www.w3.org/2000/svg') |
|
.attr('version', '1.1') |
|
.attr('viewBox', '0 0 900 500') |
|
.attr('preserveAspectRatio', 'xMidYMid meet'); |
|
|
|
svg.call(tip); |
|
|
|
var projection = d3.geoAlbersUsa(); |
|
var path = d3.geoPath().projection(projection); |
|
|
|
d3.queue() |
|
.defer(d3.csv, 'cities-over-250k.csv') |
|
.defer(d3.json, 'us-states-simplified.json') |
|
.defer(d3.csv, 'crime-in-us-2015.csv') |
|
.await(dataReady); |
|
|
|
var _cities = {}, _states = {}, _crime = {}; |
|
|
|
const color = d3.scaleThreshold() |
|
.domain([1,4,8,15,20,30,40,50,60]) |
|
.range([ |
|
'rgb(255,245,240)', |
|
'rgb(254,224,210)', |
|
'rgb(252,187,161)', |
|
'rgb(252,146,114)', |
|
'rgb(251,106,74)', |
|
'rgb(239,59,44)', |
|
'rgb(203,24,29)', |
|
'rgb(165,15,21)', |
|
'rgb(103,0,13)', |
|
]); |
|
|
|
function dataReady(error, cities, states, crime) { |
|
if (error) throw error; |
|
_crime = crime; |
|
_cities = cities; |
|
_states = states; |
|
|
|
cities.map(function (row) { |
|
var crimeCity = crime.find(function (item) { |
|
return row.NAME === item.city; |
|
}); |
|
|
|
if (crimeCity) { |
|
row.pop_2015 = crimeCity.pop_2015; |
|
row.murder = crimeCity.murder; |
|
row.murder_rate = crimeCity.murder_rate; |
|
} |
|
|
|
return row; |
|
}); |
|
|
|
renderMap(_cities, _states, _crime); |
|
} |
|
|
|
function drawMapCircles(cities) { |
|
var circleGroup = svg.selectAll('circle') |
|
.data(cities) |
|
.enter() |
|
.append('g') |
|
.attr('transform', function(d) { |
|
return 'translate('+ projection([d.longitude, d.latitude])+')'; |
|
}) |
|
.attr('class', 'city'); |
|
|
|
circleGroup |
|
.append('circle') |
|
.style('fill', d => color(d.murder_rate)) |
|
.style("stroke", "grey") |
|
.style('fill-opacity', .8) |
|
.attr('r', function (d) { |
|
return d.murder_rate ? d.murder_rate * 0.5 : 0; |
|
}) |
|
.on('mouseover', tip.show) |
|
.on('mouseout', tip.hide) |
|
.append('title') |
|
.text(function(d) { |
|
return d.NAME+ ' -'+ |
|
'\nMurders: '+d.murder+' ('+Math.round(d.murder_rate)+' for every 100k),'+ |
|
'\n2015 Population: '+ d.pop_2015; |
|
}); |
|
} |
|
|
|
function renderMap(cities, states, crime) { |
|
svg.selectAll('*').remove(); // clear for re-render |
|
cities = cities.filter(function(d) { |
|
return projection([d.longitude, d.latitude]); |
|
}); |
|
|
|
svg.selectAll('.states') |
|
.data(topojson.feature(states, states.objects.states).features) |
|
.enter() |
|
.append('path') |
|
.attr('class', 'states') |
|
.attr('d', path) |
|
|
|
drawMapCircles(cities); |
|
} |