Last active
April 26, 2020 10:07
-
-
Save mthh/c8f7c673414da8980474a7bea569bb48 to your computer and use it in GitHub Desktop.
d3 transition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: MIT | |
height: 535 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Country | CountryCode | Series | SeriesCode | 1970 | 1971 | 1972 | 1973 | 1974 | 1975 | 1976 | 1977 | 1978 | 1979 | 1980 | 1981 | 1982 | 1983 | 1984 | 1985 | 1986 | 1987 | 1988 | 1989 | 1990 | 1991 | 1992 | 1993 | 1994 | 1995 | 1996 | 1997 | 1998 | 1999 | 2000 | 2001 | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
European Union | EUU | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | 96.61009 | 96.59614 | 96.62024 | 96.41632 | 96.55341 | 96.50732 | 96.60095 | 96.34062 | 96.26472 | 96.0699 | 95.82447 | 95.21122 | 95.10601 | 94.84984 | 94.96997 | 95.10299 | 95.70635 | 95.6916 | 95.74489 | 95.59834 | 95.34953 | 95.22209 | 94.7738 | 95.11806 | 95.63038 | 96.0977 | 96.63364 | 97.36443 | 98.46769 | 98.3779 | 98.51014 | 98.54619 | 98.3794 | 98.26918 | 97.98124 | 98.23621 | 98.34876 | 98.47068 | 98.6939 | 98.78753 | 98.85742 | 98.78684 | 98.6698 | 98.32635 | |
Fragile and conflict affected situations | FCS | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | 41.26276 | 41.16214 | 42.05738 | 43.60742 | 43.30613 | 44.19519 | 45.5206 | 46.77219 | 47.65314 | 50.07585 | 52.68497 | 54.72917 | 53.7965 | 54.28538 | 54.52158 | 54.04974 | 54.70665 | 53.78846 | 54.32845 | 52.91621 | 50.82418 | 54.58232 | 53.65904 | 53.85171 | 54.44489 | 54.44947 | 53.13934 | 52.40899 | 52.19064 | 51.66156 | 52.20496 | 53.80738 | 56.71934 | 59.00989 | 61.13658 | 61.8487 | 63.68402 | 64.53225 | 67.52052 | 68.06396 | 68.88713 | 69.75518 | 71.90069 | 71.63384 | |
Heavily indebted poor countries (HIPC) | HPC | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | .. | .. | 31.94414 | 32.90021 | 33.68679 | 35.46441 | 37.50372 | 39.21024 | 40.68446 | 41.9581 | 43.74801 | 45.03222 | 44.22897 | 45.01984 | 44.92422 | 44.77224 | 45.07152 | 44.41191 | 44.60369 | 43.39967 | 42.19297 | 43.74316 | 42.58519 | 42.3936 | 43.36206 | 44.38504 | 44.15921 | 46.98458 | 47.98826 | 48.50737 | 50.39618 | 53.20747 | 56.95739 | 60.08622 | 62.95804 | 65.53953 | 68.02163 | 69.95456 | 73.25144 | 73.76343 | 74.33972 | 75.61815 | 76.91965 | 77.49571 | |
Sub-Saharan Africa (all income levels) | SSF | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | .. | .. | .. | .. | .. | 39.10568 | 40.15078 | 42.60246 | 45.23686 | 48.4128 | 50.73162 | 52.91822 | 54.53045 | 54.9287 | 54.37809 | 53.12834 | 51.51788 | 50.42196 | 49.83144 | 50.21799 | 49.67436 | 50.82698 | 50.51715 | 51.02866 | 51.31942 | 51.34877 | 49.89618 | 52.69448 | 54.14818 | 55.38012 | 57.43951 | 59.3815 | 60.99001 | 63.49616 | 65.53115 | 67.84841 | 69.8376 | 71.88173 | 73.21121 | 73.86698 | 74.21368 | 75.07751 | 75.93007 | 76.29307 | |
World | WLD | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | 64.39105 | 63.8871 | 64.87696 | 67.83868 | 68.82677 | 70.6355 | 71.58348 | 71.51174 | 69.78469 | 70.03184 | 71.34842 | 72.21853 | 72.59067 | 72.87325 | 73.31925 | 74.38668 | 75.7264 | 76.29259 | 77.24019 | 77.69612 | 77.94786 | 78.17473 | 77.86134 | 78.17906 | 78.5283 | 78.23202 | 78.31261 | 78.79151 | 79.79754 | 81.211 | 82.26044 | 82.91992 | 83.56383 | 85.80512 | 86.43092 | 86.92009 | 87.76219 | 89.13018 | 89.59027 | 89.86923 | 90.19236 | 90.40838 | 90.43876 | 90.33611 | |
OECD members | OED | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | .. | 89.93604 | 89.993 | 90.44101 | 90.24625 | 90.32824 | 90.91474 | 91.23871 | 91.41878 | 92.17577 | 94.09777 | 94.08079 | 94.66681 | 94.41048 | 94.77431 | 94.74189 | 95.6062 | 96.07206 | 96.41088 | 96.12245 | 96.80986 | 96.58962 | 96.18679 | 95.60099 | 95.45323 | 95.69942 | 95.68604 | 96.02915 | 96.58329 | 97.1593 | 97.43097 | 97.69493 | 97.20884 | 96.92627 | 96.51848 | 96.69753 | 97.13136 | 97.48092 | 97.65628 | 97.40247 | 97.09942 | 97.00714 | 96.80648 | 96.6306 | |
Middle East & North Africa (all income levels) | MEA | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | 44.85906 | 44.80407 | 47.79441 | 49.59928 | 50.69423 | 54.31628 | 57.05165 | 59.10183 | 60.84321 | 59.7132 | 63.03837 | 62.56794 | 64.45899 | 65.59448 | 67.14591 | 68.07089 | 69.5574 | 71.08415 | 72.47347 | 72.89762 | 75.48452 | 77.1297 | 73.92113 | 74.75731 | 77.89115 | 76.38415 | 80.01185 | 80.22886 | 80.62006 | 81.10303 | 82.22133 | 84.62012 | 86.60936 | 87.34724 | 88.44492 | 88.43019 | 89.35341 | 89.73569 | 90.53626 | 91.36755 | 92.99107 | 93.4294 | 94.33016 | 93.14842 | |
Least developed countries: UN classification | LDC | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | 29.3064 | 27.6506 | 31.29247 | 35.05885 | 34.77636 | 37.84784 | 40.15469 | 42.48859 | 43.4944 | 44.67606 | 46.23828 | 46.47017 | 45.35596 | 45.46051 | 46.05662 | 45.30972 | 45.5818 | 45.25263 | 48.17532 | 48.04211 | 47.65607 | 49.22526 | 49.14884 | 49.30633 | 50.20394 | 50.95232 | 51.05746 | 52.87445 | 53.61564 | 53.99038 | 56.3315 | 58.62957 | 62.35045 | 65.39041 | 68.40326 | 70.86196 | 73.43089 | 74.56947 | 76.73217 | 77.86371 | 77.86893 | 78.61898 | 79.55802 | 79.80053 | |
Latin America & Caribbean (all income levels) | LCN | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | 81.87537 | 82.24406 | 82.64448 | 83.23603 | 83.73576 | 83.75583 | 84.30577 | 85.17431 | 85.61146 | 87.13352 | 87.47275 | 88.59305 | 88.70893 | 88.86177 | 88.89106 | 89.23534 | 89.29865 | 89.47688 | 89.2616 | 88.42326 | 89.12177 | 89.4416 | 90.23628 | 90.46078 | 90.00822 | 89.89283 | 90.11073 | 90.26453 | 91.693 | 92.69359 | 93.22232 | 93.31715 | 94.17305 | 94.12511 | 94.49837 | 94.34318 | 94.3625 | 94.39295 | 94.07306 | 94.42434 | 94.53109 | 94.38145 | 93.75903 | 93.60884 | |
High income | HIC | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | .. | 91.43513 | 91.13899 | 91.30447 | 90.8492 | 91.06884 | 91.65998 | 91.88216 | 92.31251 | 92.49517 | 94.4352 | 94.08515 | 94.36195 | 93.72985 | 93.42314 | 93.66524 | 94.40037 | 95.10331 | 95.49145 | 95.58638 | 95.66042 | 95.5905 | 94.96875 | 94.58119 | 94.46948 | 94.65624 | 95.02925 | 95.47564 | 95.93902 | 96.12058 | 96.29323 | 96.82125 | 96.34979 | 96.06647 | 95.81528 | 95.62739 | 96.1971 | 96.60526 | 96.94215 | 97.01588 | 96.80425 | 96.69625 | 96.62188 | 96.48698 | |
East Asia & Pacific (all income levels) | EAS | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | .. | .. | .. | .. | .. | .. | .. | .. | .. | .. | .. | .. | .. | .. | .. | .. | 89.26129 | 93.49796 | 94.98887 | 94.1821 | 94.05041 | 92.84168 | 91.56869 | 90.47326 | 89.55572 | 88.7911 | 88.69199 | 88.69633 | 91.54781 | 94.29917 | 94.53937 | 94.93492 | 95.14224 | 95.16641 | 94.90849 | 94.34484 | 94.05987 | 95.11704 | 95.42956 | 95.74127 | 96.04546 | 96.32802 | 95.83425 | 95.87639 | |
Arab World | ARB | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | 42.84292 | 42.82264 | 44.16319 | 45.35383 | 45.93243 | 47.77129 | 49.40708 | 50.58012 | 51.66248 | 53.91799 | 55.50587 | 56.1497 | 56.94808 | 57.94749 | 59.26525 | 60.05314 | 61.34173 | 62.89461 | 63.99371 | 64.15573 | 65.30609 | 66.56963 | 62.65608 | 63.52473 | 67.39799 | 65.9064 | 69.88704 | 70.57265 | 71.65497 | 73.15838 | 74.32056 | 75.98818 | 77.18511 | 77.79193 | 78.41859 | 78.71033 | 79.64724 | 79.75937 | 80.86663 | 81.29138 | 82.64643 | 82.74064 | 84.47501 | 83.4875 | |
Europe & Central Asia (all income levels) | ECS | Adjusted net enrolment rate, primary, female (%) | SE.PRM.TENR.FE | .. | .. | .. | 92.72244 | 92.67544 | 92.73936 | 93.0773 | 93.01079 | 92.95091 | 92.98602 | 92.68179 | 91.82266 | 91.86256 | 91.75669 | 92.74555 | 92.90579 | 93.57895 | 93.68688 | 94.24011 | 94.10122 | 94.30686 | 94.77744 | 94.53947 | 94.10468 | 93.93649 | 93.78877 | 94.16484 | 94.23135 | 94.96886 | 95.28114 | 95.99717 | 96.8206 | 97.281 | 96.96585 | 97.03667 | 96.39124 | 96.62284 | 96.75377 | 97.07202 | 96.90757 | 97.28002 | 97.37261 | 97.34016 | 97.23212 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>bars</title> | |
<link href="https://fonts.googleapis.com/css?family=Anton&display=swap" rel="stylesheet"> | |
<style> | |
.axis { | |
font: 10px sans-serif; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.axis--y path { | |
display: none; | |
} | |
.bar { | |
fill-opacity: .9; | |
} | |
.wld { | |
fill: #9ecae1; | |
} | |
.chart-title { | |
margin-bottom: 0; | |
} | |
.source { | |
margin-top: 0; | |
font-size: 11px; | |
} | |
.year { | |
font-size: 32px; | |
left: 850px; | |
position: absolute; | |
top: 325px; | |
font-family: 'Anton', sans-serif; | |
letter-spacing: 3px; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="wrapper"> | |
<h4 class="chart-title">Adjusted net enrolment rate, primary, female (%) <span class="year"></span></h4> | |
<div class="chart"></div> | |
<p class="source">Data source: The World Bank</p> | |
<div> | |
<div> | |
<input type="radio" id="chknodelay" name="opt" value="nodelay"/> | |
<label for="chknodelay">No delay</label> | |
</div> | |
<div> | |
<input type="radio" id="chkdelay" name="opt" value="delay"/> | |
<label for="chkdelay">Delay between each element</label> | |
</div> | |
<div> | |
<input type="radio" id="chkmovebardelay" name="opt" value="movebardelay"/> | |
<label for="chkmovebardelay">Move bar first + delay between each element</label> | |
</div> | |
</div> | |
</div> | |
<script src="//d3js.org/d3.v5.min.js"></script> | |
<script> | |
const colors = { | |
'European Union': '#8dd3c7', | |
'Fragile and conflict affected situations': '#ffffb3', | |
'Heavily indebted poor countries (HIPC)': '#bebada', | |
'Sub-Saharan Africa (all income levels)': '#fb8072', | |
'World': '#b15928', | |
'OECD members': '#fdb462', | |
'Middle East & North Africa (all income levels)': '#b3de69', | |
'Least developed countries: UN classification': '#fccde5', | |
'Latin America & Caribbean (all income levels)': '#d9d9d9', | |
'High income': '#bc80bd', | |
'East Asia & Pacific (all income levels)': '#ccebc5', | |
'Arab World': '#ffed6f', | |
'Europe & Central Asia (all income levels)': '#80b1d3', | |
}; | |
const margin = {top: 20, right: 60, bottom: 40, left: 260}; | |
const width = 960 - margin.left - margin.right; | |
const height = 400 - margin.top - margin.bottom; | |
const percentFormat = d3.format('.0%'); | |
const leftPadding = 5; | |
const delay = function(d, i) { | |
return i * 40; | |
}; | |
function sortData(data) { | |
return data.sort((a, b) => b.value - a.value); | |
} | |
function removeGeoAreasWithNoData(data) { | |
return data.filter(d => d.value); | |
} | |
function prepareData(data) { | |
return data.reduce((accumulator, d) => { | |
Object.keys(d).forEach((k) => { | |
if (!Number.isInteger(+k)) { return; } | |
let value; | |
if (d[+k] === '..') { | |
value = 0; | |
} else { | |
value = +d[+k] / 100; | |
} | |
const newEntry = { | |
value, | |
geoCode: d.CountryCode, | |
geoName: d.Country, | |
}; | |
if (accumulator[+k]) { | |
accumulator[+k].push(newEntry); | |
} else { | |
accumulator[+k] = [newEntry]; | |
} | |
}); | |
return accumulator; | |
}, {}); | |
} | |
function xAccessor(d) { | |
return d.value; | |
} | |
function yAccessor(d) { | |
return d.geoName; | |
} | |
const xScale = d3.scaleLinear() | |
.range([0, width]) | |
.domain([0, 1]); | |
const yScale = d3.scaleBand() | |
.rangeRound([0, height], 0.1) | |
.padding(0.1); | |
function drawXAxis(el) { | |
el.append('g') | |
.attr('class', 'axis axis--x') | |
.attr('transform', `translate(${leftPadding},${height})`) | |
.call(d3.axisBottom(xScale).tickFormat(percentFormat)); | |
} | |
function drawYAxis(el, data, t) { | |
let axis = el.select('.axis--y'); | |
if (axis.empty()) { | |
axis = el.append('g') | |
.attr('class', 'axis axis--y'); | |
} | |
axis.transition(t) | |
.call(d3.axisLeft(yScale)) | |
.selectAll('g') | |
.delay(behavior === 'nodelay' ? null : delay); | |
} | |
function drawBars(el, data, t) { | |
let barsG = el.select('.bars-g'); | |
if (barsG.empty()) { | |
barsG = el.append('g') | |
.attr('class', 'bars-g'); | |
} | |
const bars = barsG | |
.selectAll('.bar') | |
.data(data, yAccessor); | |
bars.exit() | |
.remove(); | |
bars.enter() | |
.append('rect') | |
.attr('class', d => d.geoCode === 'WLD' ? 'bar wld' : 'bar') | |
.attr('width', d => xScale(xAccessor(d))) | |
.attr('x', leftPadding) | |
.attr('y', 300) | |
.style('fill', d => colors[yAccessor(d)]) | |
if (behavior === 'delay') { | |
bars | |
.merge(bars).transition() | |
.duration(900) | |
.attr('y', d => yScale(yAccessor(d))) | |
.attr('height', yScale.bandwidth()) | |
.attr('width', d => xScale(xAccessor(d))) | |
.delay(delay); | |
} else if (behavior === 'movebardelay') { | |
bars | |
.merge(bars).transition() | |
.duration(450) | |
.attr('y', d => yScale(yAccessor(d))) | |
.attr('height', yScale.bandwidth()) | |
.delay(delay) | |
.transition() | |
.duration(450) | |
.attr('width', d => xScale(xAccessor(d))) | |
.delay(delay); | |
} else { | |
bars | |
.merge(bars).transition() | |
.duration(900) | |
.attr('y', d => yScale(yAccessor(d))) | |
.attr('height', yScale.bandwidth()) | |
.attr('width', d => xScale(xAccessor(d))) | |
} | |
const labels = barsG | |
.selectAll('text') | |
.data(data, yAccessor); | |
labels.exit() | |
.remove(); | |
labels.enter() | |
.append('text') | |
.attr('x', d => xScale(xAccessor(d)) + 7.5) | |
.attr('y', 300) | |
.style('fill', 'transparent') | |
.html(d => xAccessor(d)) | |
if (behavior === 'delay') { | |
labels | |
.merge(labels) | |
.transition() | |
.duration(900) | |
.attr('y', d => yScale(yAccessor(d)) + 17.5) | |
.tween('text', function(d) { | |
const i = d3.interpolate(this.textContent, d.value); | |
const prec = (d.value + "").split("."); | |
return function a(t) { | |
this.textContent = Math.round(i(t) * 10000) / 10000; | |
}; | |
}) | |
.attr('x', d => xScale(xAccessor(d)) + 7.5) | |
.style('fill', 'black') | |
.delay(delay); | |
} else if (behavior === 'movebardelay') { | |
labels | |
.merge(labels) | |
.transition() | |
.duration(450) | |
.attr('y', d => yScale(yAccessor(d)) + 17.5) | |
.delay(delay) | |
.transition() | |
.duration(450) | |
.tween('text', function(d) { | |
const i = d3.interpolate(this.textContent, d.value); | |
const prec = (d.value + "").split("."); | |
return function a(t) { | |
this.textContent = Math.round(i(t) * 10000) / 10000; | |
}; | |
}) | |
.attr('x', d => xScale(xAccessor(d)) + 7.5) | |
.style('fill', 'black') | |
.delay(delay); | |
} else { | |
labels | |
.merge(labels) | |
.transition() | |
.duration(900) | |
.attr('y', d => yScale(yAccessor(d)) + 17.5) | |
.tween('text', function(d) { | |
const i = d3.interpolate(this.textContent, d.value); | |
const prec = (d.value + "").split("."); | |
return function a(t) { | |
this.textContent = Math.round(i(t) * 10000) / 10000; | |
}; | |
}) | |
.attr('x', d => xScale(xAccessor(d)) + 7.5) | |
.style('fill', 'black') | |
} | |
} | |
let behavior = 'nodelay'; | |
const onchangeradio = function onchangeradio() { | |
if (this.checked) { | |
behavior = this.value; | |
} | |
}; | |
document.querySelectorAll('input[name="opt"]') | |
.forEach((el) => { | |
el.onchange = onchangeradio; | |
}); | |
document.querySelector('input[value="nodelay"]').checked = true; | |
const svg = d3.select('.chart').append('svg') | |
.attr('width', width + margin.left + margin.right) | |
.attr('height', height + margin.top + margin.bottom) | |
.append('g') | |
.attr('transform', `translate(${margin.left},${margin.top})`); | |
fetch('./data.csv') | |
.then((res) => res.text()) | |
.then((res) => { | |
const data = prepareData(d3.csvParse(res)); | |
const years = Object.keys(data).map(d => +d); | |
const lastYear = years[years.length - 1]; | |
let startYear = 1986; // years[0]; | |
let selectedData = removeGeoAreasWithNoData(sortData(data[startYear])); | |
let geoAreas = selectedData.map(yAccessor); | |
d3.select('.year').text(startYear); | |
yScale.domain(geoAreas); | |
drawXAxis(svg, selectedData); | |
drawYAxis(svg, selectedData); | |
drawBars(svg, selectedData); | |
const interval = d3.interval(() => { | |
const t = d3.transition().duration(900); | |
startYear += 1; | |
selectedData = removeGeoAreasWithNoData(sortData(data[startYear])); | |
d3.select('.year').text(startYear); | |
yScale.domain(selectedData.map(yAccessor)); | |
drawYAxis(svg, selectedData, t); | |
drawBars(svg, selectedData, t); | |
if (startYear === lastYear) { | |
interval.stop(); | |
} | |
}, 1600); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment