Build Interactive Report with Crossfilter and dc.js
http://shzhangji.com
by zjerryj
HTML
<link rel="stylesheet" href="https://unpkg.com/dc@2.1.3/dc.css">
<script src="https://unpkg.com/lodash@4.17.4/lodash.js"></script>
<script src="https://unpkg.com/moment@2.18.0/moment.js"></script>
<script src="https://unpkg.com/crossfilter@1.3.12/crossfilter.js"></script>
<script src="https://unpkg.com/d3@3.5.17/d3.js"></script>
<script src="https://unpkg.com/dc@2.1.3/dc.js"></script>
<h2>Example: Airline on-time performance</h2>
<div id="hour-chart">
<div class="title">Time of Day
<a class="reset" href="javascript:;" style="visibility: hidden;">reset</a>
</div>
</div>
<div id="delay-chart">
<div class="title">Arrival Delay (min.)
<a class="reset" href="javascript:;" style="visibility: hidden;">reset</a>
</div>
</div>
<div id="distance-chart">
<div class="title">Distance (mi.)
<a class="reset" href="javascript:;" style="visibility: hidden;">reset</a>
</div>
</div>
<div style="clear: both;"></div>
<div id="date-chart">
<div class="title">Date
<a class="reset" href="javascript:dateChart.filterAll();dc.redrawAll();" style="visibility: hidden;">reset</a>
</div>
</div>
<div style="clear: both;"></div>
<div id="flight-table" style="float: left;">
<table></table>
</div>
<div id="data-count" style="float: left; margin: 30px;"></div>
<div id="flights-csv" style="display:...
CSS
#flight-table table {
border-collapse: collapse;
}
#flight-table table .dc-table-head {
display: none;
}
#flight-table table .dc-table-label {
padding: 5px;
}
#flight-table table .dc-table-row {
background-color: #eee;
border-bottom: 2px solid white;
}
#flight-table table .dc-table-column {
width: 100px;
padding: 5px;
}
#flight-table table .dc-table-column._3 {
text-align: right;
}
#flight-table table .dc-table-column._4 {
text-align: right;
}
JavaScript
let flightsCsv = document.getElementById('flights-csv').innerHTML.trim()
let flights = d3.csv.parse(flightsCsv)
_.forEach(flights, (d, i) => {
d.index = i
d.date = moment('2001' + d.date, 'YYYYMMDDHHmm').toDate()
d.delay = +d.delay
d.distance = +d.distance
})
let flight = crossfilter(flights)
let hour = flight.dimension((d) => d.date.getHours() + d.date.getMinutes() / 60)
let hours = hour.group(Math.floor)
let delay = flight.dimension((d) => Math.max(-60, Math.min(149, d.delay)) / 10)
let delays = delay.group(Math.floor)
let distance = flight.dimension((d) => Math.min(1999, d.distance) / 50)
let distances = distance.group(Math.floor)
let date = flight.dimension((d) => d.date)
let dates = date.group(d3.time.day)
let hourChart = dc.barChart('#hour-chart')
hourChart
.width(350)
.height(150)
.dimension(hour)
.group(hours)
.x(d3.scale.linear()
.domain([0, 23])
.rangeRound([0, 10 * 24]))
.controlsUseVisibility(true)
hourChart.yAxis().tickFormat(d3.format('s'))
let delayChart = dc.barChart('#delay-chart')
delayChart
.width(350)
.height(150)
.dimension(delay)
.group(delays)
.x(d3.scale.linear()
.domain([-6, 15])
.rangeRound([0, 10 * 21]))
.controlsUseVisibility(true)
delayChart.xAxis().tickFormat((d) => d * 10)
delayChart.yAxis().tickFormat(d3.format('s'))
let distanceChart = dc.barChart('#distance-chart')
distanceChart
.width(450)
.height(150)
.dimension(distance)
.group(distances)
.x(d3.scale.linear()
.domain([0, 2000 / 50])
.rangeRound(0, 10 * 40))
.controlsUseVisibility(true)
distanceChart.xAxis().tickFormat((d) => d * 50)
distanceChart.yAxis().tickFormat(d3.format('s'))
let dateChart = dc.barChart('#date-chart')
dateChart
.width(1150)
.height(180)
.dimension(date)
.group(dates)
.x(d3.time.scale()
.domain([new Date(2001, 0, 1), new Date(2001, 3, 1)])
.rangeRound([0, 10 * 90]))
.round(d3.time.day.round)
.xUnits(d3.time.days)
...