Block-a-Day #5. Experiment with using patterns and animation to show the margin of error on a choropleth. Stripes periodically pulse to the extremes of the margin of error to show uncertainty. This is one where the only way to see if it works is to build it; unfortunately, the idea worked better in my imagination.
Data Sources: 2014 ACS
What I Learned: I might have used an SVG mask before in a visualization project, but I had certainly never used the combination of pattern and mask. Drew heavily upon John Schulz's block demonstrating this technique. This is also my first time using Mike Bostock's pattern for chained transitions.
What I'd Do With More Time: Not sure. This isn't as effective as I'd hoped. Might be a dead end.
Just what it sounds like. For fifteen days, I will make a D3.js v4 block every single day. Rules:
xxxxxxxxxx
<meta charset="utf-8">
<style>
#controls {
top: 240px;
left: 60px;
position: absolute;
font-family: sans-serif;
}
</style>
<body>
<form id="controls">
<strong>Poverty Rate of Families with Children Under 18</strong><br>
<input type="radio" name="survey" value="five-year" checked> ACS 5-Year<br>
<input type="radio" name="survey" value="one-year"> ACS 1-Year
</form>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>
var speed = 900
var width = 960
var height = 500
var color = d3.scaleLinear()
.range(['#ffd', '#c35'])
var projection = d3.geoMercator()
.center([-77.223, 38.85])
.scale(width * 12)
var path = d3.geoPath().projection(projection)
var svg = d3.select('body')
.append('svg')
.attr('width', width)
.attr('height', height)
var defs = svg.append('defs')
defs.append('pattern')
.attr('id', 'stripe-pattern')
.attr('width', 20)
.attr('height', 20)
.attr('patternUnits', 'userSpaceOnUse')
.attr('patternTransform', 'rotate(45)')
.append('rect')
.attr('width', 12)
.attr('height', 20)
.attr('fill', '#fff')
defs.append('mask')
.attr('id', 'stripe-mask')
.append('rect')
.attr('width', '100%')
.attr('height', '100%')
.attr('fill', 'url(#stripe-pattern)')
var layers = svg.selectAll('.layer')
.data(['fill', 'stripe'])
.enter().append('g')
.attr('class', function (d) { return 'layer ' + d })
var stripeLayer = layers.filter(function (d) { return d === 'stripe' })
.attr('mask', 'url(#stripe-mask)')
d3.queue()
.defer(d3.csv, 'data.csv', function (d) {
return {
acs: d.acs,
id: d['GEO.id2'],
name: d['GEO.display-label'],
rate: d.HC02_EST_VC02 !== '' ? +d.HC02_EST_VC02 / 100 : undefined,
moe: d.HC02_MOE_VC02 !== '' ? +d.HC02_MOE_VC02 / 100 : undefined
}
})
.defer(d3.json, 'md-counties.json')
.awaitAll(initialize)
function initialize(error, results) {
if (error) { throw error }
var data = results[0]
var geoData = results[1]
color.domain([
d3.min(data, function (d) { return d.rate - d.moe }),
d3.max(data, function (d) { return d.rate + d.moe })
])
var counties = layers.selectAll('path')
.data(topojson.feature(geoData, geoData.objects.md).features)
.enter().append('path')
.attr('d', path)
.style('stroke', '#fff')
.style('stroke-width', 1)
update('five-year')
d3.select('#controls').on('change', function () {
update(d3.select('input:checked').attr('value'))
})
function update(acs) {
counties.interrupt()
.data(data.filter(function (d) { return d.acs === acs }),
function (d) { return d.id })
.style('fill', function (d) { return d.rate ? color(d.rate) : '#eee' })
var tIn = d3.transition().duration(speed).ease(d3.easeSinIn)
var tOut = d3.transition().duration(speed).ease(d3.easeSinOut)
stripeLayer.selectAll('path')
.filter(function (d) { return d.rate })
.transition(tIn).delay(function (d, i) { return Math.random() * speed })
.on('start', function repeat() {
d3.active(this)
.style('fill', function (d) { return color(d.rate + d.moe) })
.transition(tOut)
.style('fill', function (d) { return color(d.rate) })
.transition(tIn).delay(speed / 2)
.style('fill', function (d) { return color(d.rate - d.moe) })
.transition(tOut)
.style('fill', function (d) { return color(d.rate) })
.transition(tIn).delay(speed / 2)
.on('start', repeat)
})
}
}
</script>
</body>
https://d3js.org/d3.v4.min.js
https://d3js.org/topojson.v1.min.js