Updated entry for Makeover Monday week 14, which was based on the data from a Guardian article and PwC report on the affects of automation on UK jobs.
The chart is vertical marimekko chart, just using rects and manually calculating the offset of each row, rather than using the d3 treemap function, like this example.
Updated using labella.js to create the labels, following Micah Stubbs' recommendation.
Built with blockbuilder.org, layitout.com, and Bootstrap.
forked from tomshanley's block: Makeover Monday - marimekko with step
forked from tomshanley's block: Makeover Monday - marimekko with labella.js
forked from lorenzopub's block: Makeover Monday - marimekko with labella.js
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="labella.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 { stroke: #8FBC8F; stroke-width: 1px; fill: none; opacity: 0.6 }
line { stroke: lightGrey }
#next-button { background-color: #2E8B57; background-image: linear-gradient(to bottom,#8FBC8F 0,#2E8B57 100%) }
text { fill: Black; font-size: 12px }
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">By 2030, over 30% of jobs could be replced by automation. Half of the potential job losses are in four key industry sectors: wholesale and retail trade, manufacturing, administrative and support services, and transport and storage:
</p>
<div id="chart"></div>
<p id="source-link">More information and analysis is available in the PwC report: <a href="https://www.pwc.co.uk/services/economics-policy/insights/uk-economic-outlook.html">UK Economic Outlook March 2017</a></p>
</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
}
]
const width = 290;
const height = 750;
const margin = {"top": 25, "left": 300, "right": 300, "bottom": 75};
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;
const mainColour = "SeaGreen";
const backgroundColour = "PaleGoldenRod";
data.forEach(function(d){
d.offset = totalOffset;
totalOffset = d.offset + d.employmentShare;
});
yScale.domain([0,totalOffset]);
var xAxis = d3.axisTop(xScale).tickFormat(formatPercentage);
/////////////////////////////////////////////////////////////////////
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 + ")");
var iLabels = svg.append("g").attr("class", "labels").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var iLinks = svg.append("g").attr("class", "links")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var vLabels = svg.append("g").attr("class", "labels").attr("transform", "translate(" + (width + margin.left) + "," + margin.top + ")");
var vLinks = svg.append("g").attr("class", "links")
.attr("transform", "translate(" + (width + margin.left) + "," + margin.top + ")");
var gAxis = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(xAxis);
gAxis.selectAll("text")
.style("fill", mainColour);
gAxis.selectAll("path").remove();
/////////////////////////////////////////////////////////////////////
var iNodes = data.map(function(industry){
var y = yScale(industry.offset) + yScale(industry.employmentShare)/2;
return new labella.Node(y, 15, industry);
});
var iRenderer = new labella.Renderer({
layerGap: 40,
nodeHeight: 5,
direction: 'left'
});
var iForce = new labella.Force({ minPos: 0, maxPos: (height + margin.bottom), nodeSpacing: 0, lineSpacing: 0 })
.nodes(iNodes)
.compute();
drawLabels(iForce.nodes());
function drawLabels(nodes){
// Add x,y,dx,dy to node
iRenderer.layout(nodes);
// Draw label rectangles
var iLabel = iLabels.selectAll('text')
.data(nodes)
.enter().append('g')
.attr('transform', function(d){return 'translate('+(d.x)+','+(d.y + 5)+')';});
iLabel.append('text')
.attr('x', 0)
.attr('y', 0)
.style('fill', mainColour)
.text(function(d){return (d.data.industry);})
.style("text-anchor", "end");
// Draw path from point on the timeline to the label rectangle
iLinks.selectAll('path')
.data(nodes)
.enter().append('path')
.attr('d', function(d){return iRenderer.generatePath(d);});
};
/////////////////////////////////////////////////////////////////////
var vNodes = data.map(function(industry){
var y = yScale(industry.offset) + yScale(industry.employmentShare)/2;
return new labella.Node(y, 15, industry);
});
var vRenderer = new labella.Renderer({
layerGap: 40,
nodeHeight: 5,
direction: 'right'
});
var vForce = new labella.Force({ minPos: 0, maxPos: (height + margin.bottom), nodeSpacing: 0, lineSpacing: 0 })
.nodes(vNodes)
.compute();
drawValues(vForce.nodes());
function drawValues(nodes){
// Add x,y,dx,dy to node
vRenderer.layout(nodes);
// Draw label rectangles
var vLabel = vLabels.selectAll('text')
.data(nodes)
.enter().append('g')
.attr('transform', function(d){return 'translate('+(d.x)+','+(d.y + 5)+')';});
vLabel.append('text')
.attr('x', 0)
.attr('y', 0)
.style('fill', mainColour)
.text(function(d){ return formatMillions((d.data.employmentShare * jobs) * d.data.jobAutomation) + " (" + formatPercentage(d.data.jobAutomation) + ")" })
.style("text-anchor", "start");
// Draw path from point on the timeline to the label rectangle
vLinks.selectAll('path')
.data(nodes)
.enter().append('path')
.attr('d', function(d){return vRenderer.generatePath(d);});
};
/////////////////////////////////////////////////////////////////////
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);
/*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("text-anchor", "middle");*/
var automation = industries.append("rect")
.attr("class", "automation")
.attr("x", 0)
.attr("y", 0)
.attr("width", function(d) { return xScale(d.jobAutomation); })
.attr("height", function(d) { return yScale(d.employmentShare) < 3 ? 3 : yScale(d.employmentShare); })
.style("fill", mainColour);
/*industries.append("text")
.attr("class", "automation-text")
.text(function(d){ return formatMillions((d.employmentShare * jobs) * d.jobAutomation) + " (" + formatPercentage(d.jobAutomation) + ")" })
.attr("x", width + 5 )
.attr("y", function(d) { return 5 + yScale(d.employmentShare)/2; })
.style("fill", mainColour);*/
/*var industryLabel = industries.append("text")
.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");*/
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>
https://d3js.org/d3.v4.min.js