xxxxxxxxxx
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D3</title>
<style>
circle {
fill: rgba(39, 54, 107, 0.25);
}
.leaf circle {
fill-opacity: 1;
}
text {
font: 12px sans-serif;
}
.topbar {
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
height: 48px;
border-bottom: 1px solid whitesmoke;
margin-bottom: 12px;
display: none;
}
select {
font-size: 16px;
}
</style>
</head>
<body>
<div id="root"></div>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
const metrics = [
'incidents',
'fatal_accidents',
'fatalities'
]
const thresholds = [5, 10, 25]
const topbar = d3.select('#root').append('div')
.attr({
class: 'topbar'
})
topbar.append('p').text('View airlines that had a minimum of')
const thresholdSelect = topbar.append('select')
.attr({ id: 'thresholdSelect' })
const metricSelect = topbar.append('select')
.attr({ id: 'metricSelect' })
topbar.append('p').text('between 1985-1999 or between 2000-2014.')
// Map the metrics to options in select
metrics.forEach(m => {
metricSelect.append('option')
.text(m)
});
thresholds.forEach(m => thresholdSelect.append('option').text(m))
// d3.select(thresholdSelect)
// .data(thresholds)
// .enter()
// .append('option')
// .text(String)
const diameter = 800
const format = d3.format(',d')
const pack = d3.layout.pack()
.size([ diameter - 4, diameter - 4 ])
.value(d => d.size)
const svg = d3.select('#root').append('svg')
.attr({
width: diameter,
height: diameter
})
.append('g')
.attr({
transform: 'translate(2, 2)'
})
const colorScale = d3.scale.linear()
.range(['#2C7BB6', '#D7191C'])
d3.csv('airlineSafety.csv', (err, data) => {
if (err) throw err
else {
let _state = {
metric: metricSelect.property('value'),
threshold: thresholdSelect.property('value')
}
const reducedByMetric = (metric, threshold) => {
const toReturn = data.reduce((acc, val, i) => {
if (val[`${metric}_85_99`] > +threshold || val[`${metric}_00_14`] > +threshold) {
acc.children.push({
name: val.airline,
delay: i,
isAirlineName: true,
children: [
{
name: '1985-1999',
size: val[`${metric}_85_99`],
delay: i
},
{
name: '2000-2014',
size: val[`${metric}_00_14`],
delay: i
}
]
})
}
return acc
}, {
name: 'airline_safety',
children: []
})
return toReturn
}
const updateGraph = (metric, threshold) => {
console.log(metric, threshold)
const valsArray = reducedByMetric(metric, threshold).children.reduce((acc, val) => {
const vals = val.children.map(c => +c.size)
return [ ...acc, ...vals ]
}, [])
const properData = reducedByMetric(metric, threshold)
const node = svg.datum(reducedByMetric(metric, threshold)).selectAll('.node')
.data(pack.nodes, d => Math.random())
colorScale.domain(d3.extent(valsArray))
if (properData.children.length > 0) {
const nodeEnter = node.enter()
.append('g')
.attr({
class: d => d.children ? 'node' : 'leaf node',
transform: d => `translate(${d.x}, ${d.y})`
})
nodeEnter
.append('title')
.text(d => d.name + (d.children ? '' : `: ${format(d.size)}`))
nodeEnter.append('circle')
.attr({ r: 0 })
nodeEnter.filter(d => !d.children || d.isAirlineName).append('text')
.attr({
dy: '0.3em'
})
.style({
'text-anchor': 'middle'
})
.text(d => d.isAirlineName ? d.name : `${d.value}`)
.attr({
transform: d => d.isAirlineName ? `translate(0, ${d.r - 20})` : '',
'font-size': 20,
fill: 'white'
})
// .style({ visibility: 'hidden' })
// Update ----------------------------
node.selectAll('g')
.attr({
class: d => d.children ? 'node' : 'leaf node',
transform: d => `translate(${d.x}, ${d.y})`
})
node
.selectAll('title')
.text(d => d.name + (d.children ? '' : `: ${format(d.size)}`))
node.selectAll('circle')
.attr({
r: 0
})
node.filter(d => !d.children || d.isAirlineName).selectAll('text')
.attr({
dy: '0.3em'
})
.style({
'text-anchor': 'middle'
})
.text(d => d.isAirlineName ? d.name : `${d.value}`)
.attr({
transform: d => d.isAirlineName ? `translate(0, ${d.r - 20})` : '',
fill: 'white'
})
// .style({ visibility: 'hidden' })
const animateCircles = () => {
d3.selectAll('circle')
.transition()
.duration(1000)
// .delay(d => d.delay ? d.delay * 40 : 0)
.attr({
r: d => d.r
})
d3.selectAll('.leaf').selectAll('circle')
.style({
fill: d => colorScale(d.value)
})
}
animateCircles()
}
node.exit().remove()
.transition()
.duration(500)
}
const updateGraphWithState = (obj) => {
_state = Object.assign({}, _state, obj)
updateGraph(_state.metric, _state.threshold)
}
metricSelect.on('change', () => {
updateGraphWithState({ metric: metricSelect.property('value') })
})
thresholdSelect.on('change', () => {
updateGraphWithState({ threshold: thresholdSelect.property('value') })
})
window.setInterval(() => {
updateGraphWithState({
metric: metrics[Math.floor(Math.random() * metrics.length)],
threshold: thresholds[Math.floor(Math.random() * thresholds.length)]
})
}, 2000)
updateGraphWithState()
}
})
</script>
</body>
</html>
https://d3js.org/d3.v3.min.js