Built with blockbuilder.org My first attempt at D3 was mostly copy and paste. I wanted most in this exercise to see how D3 works with laying out a web page.
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
body, h2, h5 { font-family: Verdana, Tahoma, sans-serif; }
p, ul { font-size: 80%;
line-height: 1.2;
}
#all { margin: 0 auto;
width: 930px;
height: 950px;
position: relative;
}
#SARdiv { float: left;
width: 615px;
}
#PBMdiv { float: right;
width: 280px;
height: 690px;
background: lightblue;
padding: 0 10px;
text-align: center;
}
.bar0 { fill: #8a89a6; }
.bar1 { fill: #ff8c00; }
.grid line { stroke: lightgrey;
stroke-opacity: 0.7;
shape-rendering: crispEdges;
}
.grid path { stroke-width: 0; }
.legend { font-weight: bold;
font-size: 80%;
}
</style>
</head>
<body>
<div id="all">
<h2>How Coast Guard measures 'Search and Rescue' performance</h2>
<div id="SARdiv">
<p>Since 2000, the Coast Guard has used data about lives saved and lost during
rescue missions to determine its performance benchmark. The chart below shows the number of
lives saved and the sum of lives lost and unaccounted for. The formula for determining the
SAR System Performance Benchmark and the benchmark scores are shown in the box to the
right. The Coast Guard makes it clear that no loss of life is desirable, but uses this
equation in the evaluation of the effectiveness of their rescue efforts.</p>
<script type="text/javascript">
(function() {
// set dimensions and margins of graph
var margin = {top: 20, right: 20, bottom: 20, left: 50},
width = 615 - margin.left - margin.right,
height = 550 - margin.top - margin.bottom;
// set ranges
var y = d3.scaleBand()
.range([height, 0])
.padding(0.3)
var x = d3.scaleLinear()
.range([0, width]);
// append svg to div
// append group to svg
// move group to top left margin
var svg = d3.select("#SARdiv").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 + ")");
// gridlines in x axis function
function make_x_gridlines() {
return d3.axisBottom(x)
.ticks(11) };
// get data
d3.csv("SARdata17.csv", function(error, data) {
if (error) throw error;
// format data
data.forEach(function(d) {
d.saved = +d.saved;
d.year = +d.year;
d.lostunacc = +d.lostunacc;
});
// scale range of data in domains
y.domain(data.map(function(d) { return d.year; }));
x.domain([0, d3.max(data, function(d) { return d.saved; })]);
// append saved rectangles to bar chart
svg.selectAll(".bar0")
.data(data)
.enter().append("rect")
.attr("class", "bar0")
.attr("y", function(d) { return y(d.year); })
.attr("height", y.bandwidth())
.attr("x", 0)
.attr("width", function(d) { return x(d.saved); });
// append text to bar0
svg.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d) { return d.saved; })
.attr("text-anchor", "middle")
.attr("y", function(d) { return y(d.year) + 16; })
.attr("x", function(d) { return x(d.saved) - 25; })
.attr("font-size", "60%")
.attr("fill", "white");
// append lost/unaccounted rectangles to bar chart
svg.selectAll(".bar1")
.data(data)
.enter().append("rect")
.attr("class", "bar1")
.attr("y", function(d) { return y(d.year); })
.attr("height", y.bandwidth())
.attr("x", 0)
.attr("width", function(d) { return x(d.lostunacc); });
// append text to bar1
svg.selectAll("text1")
.data(data)
.enter()
.append("text")
.text(function(d) { return d.lostunacc; })
.attr("text-anchor", "middle")
.attr("y", function(d) { return y(d.year) + 16; })
.attr("x", function(d) { return x(d.lostunacc) - 25; })
.attr("font-size", "60%")
.attr("fill", "white");
// add X axis
svg.append("g")
.attr("transform", "translate(0, " + height + ")")
.call(d3.axisBottom(x));
// add Y axis
svg.append("g")
.call(d3.axisLeft(y));
// add the X gridlines
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_gridlines()
.tickSize(-height)
.tickFormat("")
);
// add lostunacc legend
svg.append("text")
.attr("x", 25)
.attr("y", 0)
.attr("class", "legend")
.style("fill", "#ff8c00")
.text("Lives Lost and Unaccounted For");
// add lost legend
svg.append("text")
.attr("x", 350)
.attr("y", 0)
.attr("class", "legend")
.style("fill", "#8a89a6")
.text("Lives Saved");
});
})();
</script>
</div>
<div id="PBMdiv">
<h3 style="margin: 2px 0">Performance Benchmark</h3>
<p style="margin: 0 0">Lives Saved / Lives Saved + (Lives Lost + Lives Unaccounted For)</p>
<p>Percent of lives saved from imminent danger in the maritime environment:</p>
<script type="text/javascript">
(function() {
// set dimensions and margins of graph
var margin = {top: 35, right: 10, bottom: 20, left: 120},
width = 280 - margin.left - margin.right,
height = 690 - margin.top - margin.bottom;
// set ranges
var y = d3.scaleBand()
.range([height - 125, 0])
.padding(0.3)
var x = d3.scaleLinear()
.range([0, width]);
// append svg to div
// append group to svg
// move group to top left margin
var svg = d3.select("#PBMdiv").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height - margin.top - margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + 25 + ")");
// get data
d3.csv("SARdata17.csv", function(error, data) {
if (error) throw error;
// format data
data.forEach(function(d) {
d.saved = +d.saved;
d.year = +d.year;
d.lostunacc = +d.lostunacc;
});
// scale range of data in domains
y.domain(data.map(function(d) { return d.year; }));
x.domain([0, d3.max(data, function(d) { return d.saved / (d.saved + d.lostunacc); })]);
// append text
svg.selectAll("text")
.data(data)
.enter().append("text")
.attr("y", function(d) { return y(d.year) + 16; })
.attr("height", y.bandwidth())
.attr("x", 50)
.attr("font-size", "70%")
.text(function(d) { return d3.format(".1%")((d.saved) / (d.saved + d.lostunacc))} ) ;
// add Y axis
svg.append("g")
.call(d3.axisLeft(y));
});
})();
</script>
</div>
<h5>Notes on data</h5>
<ul>
<li>2000 - Egypt Air (217) & Alaska Air (88) crashes included in Lives Lost Before (total 305)</li>
<li>2001 – 173 Lives Unaccounted For from two large AMIO incidents</li>
<li>2002 – 439 lives in 7 large incidents included in Lives Saved; 105 lives in 3 large incidents included in Lives Unaccounted For</li>
<li>2003 – 439 lives in 8 large incidents included in Lives Saved</li>
<li>2005 – Does NOT include the 33,544 Lives Saved during Hurricane Katrina or the 138 during Hurricane Rita</li>
</ul>
</div>
</body>
https://d3js.org/d3.v4.min.js