|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<meta name="viewport" content="width=device-width"> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<title>2016 Presedential Votes</title> |
|
<style> |
|
|
|
@import url(//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.2/leaflet.css); |
|
body { |
|
margin: 0px; |
|
} |
|
.domain { |
|
display: none; |
|
} |
|
.tick line { |
|
stroke: #C0C0BB; |
|
} |
|
.tick text { |
|
fill: #8E8883; |
|
font-size: 10pt; |
|
font-family: sans-serif; |
|
} |
|
.axis-label { |
|
fill: #635F5D; |
|
font-size: 16pt; |
|
font-family: sans-serif; |
|
} |
|
.topcorner{ |
|
position:absolute; |
|
top:0; |
|
right:0; |
|
height: 250px; |
|
width: 480px; |
|
z-index: 100; |
|
background:white; |
|
} |
|
#map { |
|
width: 960px; |
|
height: 500px; |
|
} |
|
|
|
path { |
|
fill: #000; |
|
fill-opacity: .2; |
|
stroke: #fff; |
|
stroke-width: 1.5px; |
|
} |
|
|
|
path:hover { |
|
fill: brown; |
|
fill-opacity: .7; |
|
} |
|
|
|
</style> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.js"></script> |
|
<script src="http://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.2/leaflet.js"></script> |
|
<body> |
|
<div class="topcorner"> |
|
<svg width="480" height="250"></svg> |
|
</div> |
|
<div id="map"</div> |
|
<script> |
|
|
|
//**************************chart***************************************** |
|
var barChart = function(countyFP){ |
|
const xValue = d => d.value; |
|
const xLabel = 'Votes'; |
|
const yValue = d => d.name; |
|
const yLabel = 'Candidate'; |
|
const margin = { left: 150, right: 30, top: 5, bottom: 75 }; |
|
|
|
|
|
const svg = d3.select('svg'); |
|
const svgRemove = svg.selectAll('*').remove(); |
|
const width = svg.attr('width'); |
|
const height = svg.attr('height'); |
|
const innerWidth = width - margin.left - margin.right; |
|
const innerHeight = height - margin.top - margin.bottom; |
|
|
|
const g = svg.append('g') |
|
.attr('transform', `translate(${margin.left},${margin.top})`); |
|
const xAxisG = g.append('g') |
|
.attr('transform', `translate(0, ${innerHeight})`); |
|
const yAxisG = g.append('g'); |
|
|
|
xAxisG.append('text') |
|
.attr('class', 'axis-label') |
|
.attr('x', innerWidth / 2) |
|
.attr('y', 55) |
|
.text(xLabel); |
|
|
|
const xScale = d3.scaleLinear(); |
|
const yScale = d3.scaleBand() |
|
.paddingInner(0.3) |
|
.paddingOuter(0); |
|
|
|
const xTicks = 5; |
|
const xAxis = d3.axisBottom() |
|
.scale(xScale) |
|
.ticks(xTicks) |
|
.tickPadding(5) |
|
.tickFormat(d3.format('.0s')) |
|
.tickSize(-innerHeight); |
|
|
|
const yAxis = d3.axisLeft() |
|
.scale(yScale) |
|
.tickPadding(5) |
|
.tickSize(-innerWidth); |
|
|
|
const row = d => { |
|
return { |
|
county: d.countyfp10, |
|
attributes:[ |
|
{ |
|
name: 'Clinton', |
|
value: Number(d.pres_clinton) |
|
}, |
|
{ |
|
name: 'Trump', |
|
value: Number(d.pres_trump) |
|
}, |
|
{ |
|
name: 'Johnson', |
|
value: Number(d.pres_johnson) |
|
}, |
|
{ |
|
name: 'Stein', |
|
value: Number(d.pres_stein) |
|
}, |
|
{ |
|
name: 'Lariva', |
|
value: Number(d.pres_lariva) |
|
}, |
|
{ |
|
name: 'Other', |
|
value: Number(d.pres_other) |
|
} |
|
] |
|
}; |
|
}; |
|
|
|
const top5 = data => data.slice(0, 5); |
|
|
|
//function filterCriteria(d) { |
|
// return d.county === '037'; |
|
//}; |
|
function filterCriteria(d) { |
|
return d.county === countyFP; |
|
}; |
|
|
|
d3.csv('california-2016-county-results.csv', row, data => { |
|
//data = top5(data); |
|
data = data.filter(filterCriteria); |
|
data = data[0]['attributes']; |
|
//console.log(data); |
|
//console.log(Object.keys(data)[0]); |
|
|
|
yScale |
|
.domain(data.map(yValue).reverse()) |
|
.range([innerHeight, 0]); |
|
|
|
xScale |
|
.domain([0, d3.max(data, xValue)]) |
|
.range([0, innerWidth]) |
|
.nice(xTicks); |
|
|
|
g.selectAll('rect').data(data) |
|
.enter().append('rect') |
|
.attr('x', 0) |
|
.attr('y', d => yScale(yValue(d))) |
|
.attr('width', d => xScale(xValue(d))) |
|
.attr('height', d => yScale.bandwidth()) |
|
.attr('fill', 'steelblue'); |
|
|
|
|
|
xAxisG.call(xAxis); |
|
|
|
yAxisG.call(yAxis); |
|
yAxisG.selectAll('.tick line').remove(); |
|
}); |
|
}; |
|
barChart('037'); |
|
//**************************chart***************************************** |
|
//**************************map******************************************* |
|
var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', |
|
osmAttrib = '© <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors', |
|
osm = L.tileLayer(osmUrl, {maxZoom: 18, attribution: osmAttrib}); |
|
|
|
var map = L.map('map').setView([37.5, -115], 6).addLayer(osm); |
|
|
|
var svgMap = d3.select(map.getPanes().overlayPane).append("svg"), |
|
gMap = svgMap.append("g").attr("class", "leaflet-zoom-hide"); |
|
|
|
var transform = d3.geoTransform({point: projectPoint}), |
|
path = d3.geoPath().projection(transform); |
|
|
|
d3.json("counties.json", function(error, ca) { |
|
var features = ca.objects.CA.geometries.map(function(d) { return topojson.feature(ca, d); }); |
|
var all = topojson.merge(ca, ca.objects.CA.geometries); |
|
|
|
var states = gMap.selectAll("path") |
|
.data(features) |
|
.enter() |
|
.append("path") |
|
.on("mouseover", function(d){ |
|
//d3.select(this).transition(0).duration(0); |
|
//console.log(d.properties.COUNTYFP) |
|
barChart(d.properties.COUNTYFP); |
|
}); |
|
|
|
map.on("viewreset", reset); |
|
reset(); |
|
|
|
// Reposition the SVG to cover the features. |
|
function reset() { |
|
var bounds = path.bounds(all), |
|
topLeft = bounds[0], |
|
bottomRight = bounds[1]; |
|
|
|
svgMap .attr("width", bottomRight[0] - topLeft[0]) |
|
.attr("height", bottomRight[1] - topLeft[1]) |
|
.style("left", topLeft[0] + "px") |
|
.style("top", topLeft[1] + "px"); |
|
|
|
gMap.attr("transform", "translate(" + -topLeft[0] + "," + -topLeft[1] + ")"); |
|
|
|
states.attr("d", path); |
|
} |
|
}); |
|
|
|
// Use Leaflet to implement a D3 geometric transformation. |
|
function projectPoint(x, y) { |
|
// Returns the map layer point that corresponds to the given geographical coordinates |
|
var point = map.latLngToLayerPoint(new L.LatLng(y, x)); |
|
this.stream.point(point.x, point.y); |
|
} |
|
//**************************map******************************************* |
|
</script> |