Skip to content

Instantly share code, notes, and snippets.

@tomshanley
Last active April 4, 2017 03:47
Show Gist options
  • Save tomshanley/2171ccee1ec89835ec96461fb6074b18 to your computer and use it in GitHub Desktop.
Save tomshanley/2171ccee1ec89835ec96461fb6074b18 to your computer and use it in GitHub Desktop.
Makeover Monday - marimekko with step
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<style>
body { text-align: center;}
p, button { text-align: center; }
path { display: none}
line { stroke: lightGrey }
#next-button { background-color: #2E8B57; background-image: linear-gradient(to bottom,#8FBC8F 0,#2E8B57 100%) }
text { fill: Black }
rect { shape-rendering: crispEdges; stroke: white; stroke-width: 1px; }
.industry-label { font-size: 14px }
</style>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
<p id="headline" class="text-center lead">
</p>
<div id="chart"></div>
<p id="source-link">More information and analysis is available in the PwC report: <a href="http://www.pwc.co.uk/services/economics-policy/insights/uk-economic-outlook.html">UK Economic Outlook March 2017</a></p>
<button id="next-button" type="button" class="btn btn-primary btn-lg btn-block">
Next
</button>
</div>
</div>
</div>
<script>
var data = [
{
"industry": "Wholesale and retail trade",
"employmentShare": 0.15,
"jobAutomation": 0.44
},
{
"industry": "Manufacturing",
"employmentShare": 0.08,
"jobAutomation": 0.46
},
{
"industry": "Administrative and support services",
"employmentShare": 0.08,
"jobAutomation": 0.37
},
{
"industry": "Transportation and storage",
"employmentShare": 0.05,
"jobAutomation": 0.56
},
{
"industry": "Professional, scientific and technical",
"employmentShare": 0.09,
"jobAutomation": 0.26
},
{
"industry": "Human health and social work",
"employmentShare": 0.12,
"jobAutomation": 0.17
},
{
"industry": "Accommodation and food services",
"employmentShare": 0.07,
"jobAutomation": 0.26
},
{
"industry": "Construction",
"employmentShare": 0.064,
"jobAutomation": 0.24
},
{
"industry": "Public administration and defence",
"employmentShare": 0.043,
"jobAutomation": 0.32
},
{
"industry": "Information and communication",
"employmentShare": 0.041,
"jobAutomation": 0.27
},
{
"industry": "Financial and insurance",
"employmentShare": 0.032,
"jobAutomation": 0.32
},
{
"industry": "Education",
"employmentShare": 0.087,
"jobAutomation": 0.09
},
{
"industry": "Arts and entertainment",
"employmentShare": 0.029,
"jobAutomation": 0.22
},
{
"industry": "Other services",
"employmentShare": 0.027,
"jobAutomation": 0.19
},
{
"industry": "Real estate",
"employmentShare": 0.017,
"jobAutomation": 0.28
},
{
"industry": "Water, sewage and waste management",
"employmentShare": 0.006,
"jobAutomation": 0.63
},
{
"industry": "Agriculture, forestry and fishing",
"employmentShare": 0.011,
"jobAutomation": 0.19
},
{
"industry": "Electricity and gas supply",
"employmentShare": 0.004,
"jobAutomation": 0.32
},
{
"industry": "Mining and quarrying",
"employmentShare": 0.002,
"jobAutomation": 0.23
},
{
"industry": "Domestic personnel and self-subsistence",
"employmentShare": 0.003,
"jobAutomation": 0.08
}
]
var vWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var vHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
const width = vWidth * 0.35;
const height = vHeight * 0.8;
const margin = {"top": 25, "left": vWidth * 0.3, "right": vWidth * 0.1, "bottom": 25};
var xScale = d3.scaleLinear().range([0,width]).domain([0,1]); //jobAutomation
var yScale = d3.scaleLinear().range([0,height]); //employmentShare
var totalOffset = 0;
const rowGap = 20;
const dataLength = data.length;
const expandedHeight = height + (dataLength * rowGap);
const jobs = 34766667;
const overallPercent = 0.3;
var chartNo = 2;
const duration = 1000;
const mainColour = "SeaGreen";
const backgroundColour = "PaleGoldenRod";
var sourceLink = d3.select("#source-link").style("display", "none");
data.forEach(function(d){
d.offset = totalOffset;
totalOffset = d.offset + d.employmentShare;
});
yScale.domain([0,totalOffset]);
var select = d3.select("button").on("click", updateChart)
var xAxis = d3.axisTop(xScale).tickFormat(formatPercentage);
var defaultHeadline = "There are currently " + roundMillions(jobs) + " million jobs in the UK:";
var defaultRectText = "All " + roundMillions(jobs) + " million jobs:";
/////////////////////////////////////////////////////////////////////
var headline = d3.select("#headline").text(defaultHeadline);
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
var chart = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
chart.append("rect")
.attr("id", "base-rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height)
.style("fill", backgroundColour);
chart.append("rect")
.attr("class", "overall-automation")
.attr("x", 0)
.attr("y", 0)
.attr("width", 0)
.attr("height", height)
.style("fill", mainColour);
chart.append("text")
.attr("id", "initial-text")
.text(defaultRectText)
.attr("x", -5)
.attr("y", height/2)
.style("text-anchor", "end");
var gAxis = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(xAxis);
gAxis.selectAll("text")
.style("fill", mainColour)
.style("opacity", 0);
gAxis.selectAll("line").remove();
var industries = chart.selectAll(".industry")
.data(data)
.enter()
.append("g")
.attr("class", "industry")
.attr("transform", function(d) { return "translate(0," + yScale(d.offset) + ")"; });
industries.append("text")
.text(function(d) { return formatPercentage(d.employmentShare * d.jobAutomation); })
.attr("x", width + 5)
.attr("y", function(d) { return (yScale(d.employmentShare)/2) + 5; })
.style("opacity", 0);
var all = industries.append("rect")
.attr("class", "all")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", function(d) { return yScale(d.employmentShare) < 3 ? 3 : yScale(d.employmentShare); })
.style("fill", backgroundColour)
.style("opacity",0);
industries.append("text")
.attr("class", "all-text")
.text(function(d){ return formatMillions(d.employmentShare * jobs) + " (" + formatPercentage(d.employmentShare) + ")" })
.attr("x", width/2)
.attr("y", function(d) { return 5 + yScale(d.employmentShare)/2; })
.style("opacity",0)
.style("text-anchor", "middle");
var automation = industries.append("rect")
.attr("class", "automation")
.attr("x", 0)
.attr("y", 0)
.attr("width", 0)
.attr("height", function(d) { return yScale(d.employmentShare) < 3 ? 3 : yScale(d.employmentShare); })
.style("fill", mainColour);
industries.append("text")
//.filter(function(d){ return d.industry != "Domestic personnel and self-subsistence" && d.industry != "Mining and quarrying" && d.industry != "Agriculture, forestry and fishing"; })
.attr("class", "automation-text")
//.text(function(d){ return formatPercentage(d.jobAutomation)})
.text(function(d){ return formatMillions((d.employmentShare * jobs) * d.jobAutomation) + " (" + formatPercentage(d.jobAutomation) + ")" })
//.attr("x", function(d){ return xScale(d.jobAutomation) + 5 })
.attr("x", width + 5 )
.attr("y", function(d) { return 5 + yScale(d.employmentShare)/2; })
.style("fill", mainColour)
.style("opacity",0);
var industryLabel = industries.append("text")
//.filter(function(d){ return d.industry != "Domestic personnel and self-subsistence" && d.industry != "Mining and quarrying" && d.industry != "Agriculture, forestry and fishing"; })
.attr("class", "industry-label")
.text(function(d) { return d.industry })
.attr("x", -5)
.attr("y", function(d) { return (yScale(d.employmentShare)/2) + 5; })
.style("text-anchor", "end")
.style("opacity", 0);
function updateChart() {
if (chartNo === 1) {
headline.text(defaultHeadline);
sourceLink.style("display", "none");
var t1 = d3.transition().duration(duration);
svg.transition(t1)
.attr("height", height + margin.top + margin.bottom);
industries.transition(t1)
.attr("transform", function(d, i) { return "translate(0," + yScale(d.offset) + ")"; });
automation.transition(t1)
.attr("width", 0)
.style("opacity",1);
d3.selectAll("#base-rect, #initial-text").transition(t1)
.style("opacity", 1);
d3.select("#initial-text")
.text(defaultRectText)
.style("fill", "black");
all.transition(t1)
.style("opacity", 0);
industryLabel.transition(t1)
.style("opacity", 0);
d3.selectAll(".automation-text").transition(t1)
.style("opacity", 0);
gAxis.selectAll("text").transition(t1)
.style("opacity", 0);
select.text("Next")
chartNo = chartNo + 1
} else if (chartNo === 2) {
headline.text("By 2030, " + formatPercentage(overallPercent) + " (" + roundMillions(jobs * overallPercent) + " million) of these jobs may be replaced by automation:");
var t2 = d3.transition().duration(duration)
d3.select("#initial-text").text(roundMillions(jobs * overallPercent) + " million job losses:")
.style("fill", mainColour);
d3.select(".overall-automation").transition(t2)
.attr("width", xScale(0.3));
gAxis.selectAll("text").transition(t2)
.delay(function(d){ return d * 700; })
.style("opacity", function(d) { return d < 0.4 ? 1 : 0; })
chartNo = chartNo + 1
} else if (chartNo === 3) {
headline.text("However the affect of automation will vary across industries.");
var t3 = d3.transition().duration(duration);
d3.select(".overall-automation").transition(t3)
.attr("width", 0);
d3.select("#initial-text").transition(t3)
.style("opacity", 0);
gAxis.selectAll("text").transition(t3)
.style("opacity", 0)
chartNo = chartNo + 1
} else if (chartNo === 4) {
headline.text("The current number of jobs are divided across these industries:");
var t4 = d3.transition().duration(duration);
d3.selectAll(".all, .industry-label, .all-text").transition(t4)
.style("opacity", 1);
d3.select("#base-rect").transition(t4)
.style("opacity", 0);
chartNo = chartNo + 1
} else if (chartNo === 5) {
headline.text("The estimated job losses due to automation per industry will vary:");
var t5 = d3.transition().duration(duration);
d3.selectAll(".all-text").transition(t5)
.style("opacity", 0 )
gAxis.selectAll("text").transition(t5)
.delay(function(d){ return d * 700; })
.style("opacity", 1 )
automation.transition(t5)
.attr("width", function(d) { return xScale(d.jobAutomation); });
d3.selectAll(".automation-text").transition(t5)
.style("opacity", 1 )
chartNo = chartNo + 1
} else if (chartNo === 6) {
headline.text("Over 2 million (40%) jobs in 'wholesale and retail trade' may be affected by automation:");
var t6 = d3.transition().duration(duration);
industries.selectAll(".industry-label, .automation-text").transition(t6)
.style("opacity", function(d) { return d.industry == "Wholesale and retail trade" ? 1 : 0; });
industries.selectAll(".automation").transition(t7)
.style("opacity", function(d) { return d.industry == "Wholesale and retail trade" ? 1 : 0.2; });
chartNo = chartNo + 1
} else if (chartNo === 7) {
headline.text("60% of 'water, sewage and waste management' may jobs may be affected:");
var t7 = d3.transition().duration(duration);
industries.selectAll(".industry-label, .automation-text").transition(t7)
.style("opacity", function(d) { return d.industry == "Water, sewage and waste management" ? 1 : 0; });
industries.selectAll(".automation").transition(t7)
.style("opacity", function(d) { return d.industry == "Water, sewage and waste management" ? 1 : 0.2; });
chartNo = chartNo + 1;
} else if (chartNo === 8) {
headline.text("Over half of these potential job losses are in four key industry sectors: wholesale and retail trade, manufacturing, administrative and support services, and transport and storage.");
var t8 = d3.transition().duration(duration);
svg.transition(t8)
.attr("height", expandedHeight + margin.top + margin.bottom);
industries.transition(t8)
.attr("transform", function(d, i) { return "translate(0," + (yScale(d.offset) + (i * rowGap)) + ")"; });
industries.selectAll(".industry-label, .automation, .automation-text").transition(t8)
.style("opacity", 1);
sourceLink.style("display", "inherit");
select.text("Restart");
chartNo = 1;
};
};
function formatPercentage(n) {
var roundedN = Math.round(n * 1000);
return roundedN/10 + "%";
};
function roundMillions(n) {
var roundedN = Math.round(n/10000)/100;
return roundedN;
};
function formatMillions(n) {
return roundMillions(n) + "M";
};
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment