Planet Coverage
Simple multi series line chart looking at Planet's coverage of the Earth overtime.
Credits
forked from mbostock's block: Multi-Series Line Chart
forked from sadbumblebee's block: Multi-Series Line Chart (Planet Coverage)
forked from lorenzopub's block: Multi-Series Line Chart (Planet Coverage)
forked from Thanaporn-sk's block: Multi-Series Line Chart (Planet Coverage)
xxxxxxxxxx
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet">
<style>
.axis--x path {
stroke-width: 1px;
stroke: #777;
}
.tick line {
stroke: #777;
}
.axis--x.years {
font-weight: 600;
font-size: 12px;
}
.axis--x text {
fill: #a5a5a5;
}
.axis--y path {
display: none;
}
.annotations text {
fill: #a5a5a5;
}
.band text {
fill: #a5a5a5;
}
.axis--y text {
font-size: 11px;
fill: #a5a5a5;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.25px;
}
.axis--x text {
font-size: 11px;
}
body {
font-family: "Lato", "Helvetica", "Arial", sans-serif;
color: #3d3d3d;
}
h1 {
font-size: 24px;
font-weight: 600;
line-height: 32px;
}
.overlay {
fill: none;
pointer-events: all;
}
.focus line {
fill: none;
stroke: steelblue;
}
.title {
margin: auto;
}
.bands {
font-size: 11px;
font-weight: 600;
}
.annotations {
font-size: 10px;
}
#tooltip {
position: absolute;
width: 250px;
height: auto;
padding: 10px;
margin: 60px 0 0 75px;
background-color: #f3f3f3;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
-webkit-box-shadow: 2px 2px 6px 0px rgba(0,0,0,0.15);
-moz-box-shadow: 2px 2px 6px 0px rgba(0,0,0,0.15);
box-shadow: 2px 2px 6px 0px rgba(0,0,0,0.15);
pointer-events: none;
z-index: 1000;
visibility: visible;
opacity: 1;
transition: visibility .5s, opacity 0.5s linear;
}
#tooltip.hidden {
visibility: hidden;
opacity: 0;
}
#tooltip p {
margin: 0;
font-size: 12px;
line-height: 18px;
}
#copytext {
position: relative;
width: 600px;
height: auto;
padding: 5px;
margin: 10px 0 0 10px;
z-index: 1000;
}
#copytext p {
margin: 0;
color: #a5a5a5;
font-size: 12px;
line-height: 14px;
max-width: 450px;
}
#date {
font-weight: bold;
}
#box {
/*background-color: white;*/
text-transform: uppercase;
padding: 1px 2px 2px 1px;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
font-size: 10px;
margin-right: 3px;
}
#boxSpacer {
display: inline-block;
width: 30px;
}
.legendTitle {
background-color: #27808e;
color: white;
}
.legendRGB {
background-color: #70cf57;
color: white;
}
.legendNIR {
padding-left: 2px;
background-color: #482475;
color: white;
}
</style>
<div id="copytext">
<h1 class="title">Land Surface Area Imaged Daily</h1>
<p>Launches ranging from four to a couple dozen Doves at a time, our aptly named 'flocks' dramatically increase our imagery cadence with each deployment.</p>
</div>
<div>
<span id="tooltip" class="hidden">
<p><span id="date">Coverage!</span></p>
<p><span id="value">100</span></p>
</span>
</div>
<svg id="chart" width="800" height="350"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 80, bottom: 40, left: 50},
width = svg.attr("width") - margin.left - margin.right,
height = svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var parseTime = d3.timeParse("%x"),
bisectDate = d3.bisector(function(d) { return d.date; }).left,
toolTime = d3.timeFormat("%B %d, " + "20" + "%y"),
abbreviateNum = d3.format('.2s');
var xAxisTime = d3.timeFormat("%b");
var x0AxisYear = d3.timeFormat("20" + "%y")
var viridisColors = ["#440154","#440256","#450457","#450559","#46075a","#46085c","#460a5d","#460b5e","#470d60","#470e61","#471063","#471164","#471365","#481467","#481668","#481769","#48186a","#481a6c","#481b6d","#481c6e","#481d6f","#481f70","#482071","#482173","#482374","#482475","#482576","#482677","#482878","#482979","#472a7a","#472c7a","#472d7b","#472e7c","#472f7d","#46307e","#46327e","#46337f","#463480","#453581","#453781","#453882","#443983","#443a83","#443b84","#433d84","#433e85","#423f85","#424086","#424186","#414287","#414487","#404588","#404688","#3f4788","#3f4889","#3e4989","#3e4a89","#3e4c8a","#3d4d8a","#3d4e8a","#3c4f8a","#3c508b","#3b518b","#3b528b","#3a538b","#3a548c","#39558c","#39568c","#38588c","#38598c","#375a8c","#375b8d","#365c8d","#365d8d","#355e8d","#355f8d","#34608d","#34618d","#33628d","#33638d","#32648e","#32658e","#31668e","#31678e","#31688e","#30698e","#306a8e","#2f6b8e","#2f6c8e","#2e6d8e","#2e6e8e","#2e6f8e","#2d708e","#2d718e","#2c718e","#2c728e","#2c738e","#2b748e","#2b758e","#2a768e","#2a778e","#2a788e","#29798e","#297a8e","#297b8e","#287c8e","#287d8e","#277e8e","#277f8e","#27808e","#26818e","#26828e","#26828e","#25838e","#25848e","#25858e","#24868e","#24878e","#23888e","#23898e","#238a8d","#228b8d","#228c8d","#228d8d","#218e8d","#218f8d","#21908d","#21918c","#20928c","#20928c","#20938c","#1f948c","#1f958b","#1f968b","#1f978b","#1f988b","#1f998a","#1f9a8a","#1e9b8a","#1e9c89","#1e9d89","#1f9e89","#1f9f88","#1fa088","#1fa188","#1fa187","#1fa287","#20a386","#20a486","#21a585","#21a685","#22a785","#22a884","#23a983","#24aa83","#25ab82","#25ac82","#26ad81","#27ad81","#28ae80","#29af7f","#2ab07f","#2cb17e","#2db27d","#2eb37c","#2fb47c","#31b57b","#32b67a","#34b679","#35b779","#37b878","#38b977","#3aba76","#3bbb75","#3dbc74","#3fbc73","#40bd72","#42be71","#44bf70","#46c06f","#48c16e","#4ac16d","#4cc26c","#4ec36b","#50c46a","#52c569","#54c568","#56c667","#58c765","#5ac864","#5cc863","#5ec962","#60ca60","#63cb5f","#65cb5e","#67cc5c","#69cd5b","#6ccd5a","#6ece58","#70cf57","#73d056","#75d054","#77d153","#7ad151","#7cd250","#7fd34e","#81d34d","#84d44b","#86d549","#89d548","#8bd646","#8ed645","#90d743","#93d741","#95d840","#98d83e","#9bd93c","#9dd93b","#a0da39","#a2da37","#a5db36","#a8db34","#aadc32","#addc30","#b0dd2f","#b2dd2d","#b5de2b","#b8de29","#bade28","#bddf26","#c0df25","#c2df23","#c5e021","#c8e020","#cae11f","#cde11d","#d0e11c","#d2e21b","#d5e21a","#d8e219","#dae319","#dde318","#dfe318","#e2e418","#e5e419","#e7e419","#eae51a","#ece51b","#efe51c","#f1e51d","#f4e61e","#f6e620","#f8e621","#fbe723","#fde725"]
var viridisThreeColors = [viridisColors[200],viridisColors[25],viridisColors[110]]
var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
z = d3.scaleOrdinal(viridisThreeColors);
var line = d3.line()
.curve(d3.curveBasis)
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.area); });
d3.csv("data.csv", type, function(error, data) {
if (error) throw error;
var bands = data.columns.slice(1).map(function(id) {
return {
id: id,
values: data.map(function(d) {
return {date: d.date, area: d[id]};
})
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(bands, function(c) { return d3.min(c.values, function(d) { return d.area; }); }),
d3.max(bands, function(c) { return d3.max(c.values, function(d) { return d.area; }); })
]);
z.domain(bands.map(function(c) { return c.id; }));
g.append("g")
.attr("class", "axis axis--x months")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(xAxisTime).tickSizeOuter(0).tickPadding(10).ticks(d3.timeMonth));
g.append('g')
.attr('class', 'axis axis--x years')
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(x0AxisYear).tickSizeOuter(0).tickPadding(25).ticks(d3.timeYear));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(5, "s").tickSizeOuter(0).tickPadding(5));
g.append('g')
.attr('class', 'legend')
.append("text")
// .attr("transform", "rotate(-90)")
.attr("x", -32)
.attr("y", -9)
.attr("dy", "0.71em")
.attr('font-size', '12px')
.attr("fill", "#3d3d3d")
.text("Area in square kilometers");
// g.append("g")
// .attr("class", "axis axis--y")
// .attr("transform", "translate( " + (width + 20) + ", 0 )")
// .call(d3.axisRight(y).ticks(5, "s").tickSizeOuter(0).tickPadding(5));
var band = g.selectAll(".band")
.data(bands)
.enter().append("g")
.attr("class", "band");
band.append("path")
.attr("class", "line")
.attr("d", function(d) { console.log(d.values[1]); return line(d.values); })
.style("stroke", function(d) { return z(d.id); });
band.append("text")
.attr('class', 'bands')
.datum(function(d) { return {id: d.id, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + (x(d.value.date) - 10) + "," + (y(d.value.area) - 8) + ")"; })
.attr("x", -20)
.attr('text-align', 'right')
.attr("dy", "0.35em")
// .style("font", "10px sans-serif")
.text(function(d) { return d.id; });
//set your focus circle and make sure it's invisible
var focus = band.append("g")
.attr("class", "focus")
.style("display", "none");
focus.append('line')
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', 0)
.attr('y2', height)
.style('stroke-width', 1)
.style('stroke-dasharray', '1,6')
.style('stroke', '#12BCC2');
focus.append("text")
.attr("x", 9)
.attr("dy", ".35em");
//Create area of focus for your mouse event
band.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.on("mouseover", function() { focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
//Mouse move function for watching over focus.
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
y0 = y(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0,
thisBand = "";
focus.transition()
.duration(50)
.attr('transform', 'translate(' + x(x0) + ', 0)');
// focus.append('line')
// console.log(xx0);
// focus.select('text').text('Test');
d3.select("#tooltip")
// .style("left", width - 50 + "px")
// .style("top", "50px")
.select('#date')
.text("Coverage for " + toolTime(d.date));
d3.select("#tooltip")
.select("#value")
.html('<span id="box" class="legendTitle">Total</span><div id="boxSpacer">' + abbreviateNum(d.Total) + '</div> ' + '<span id="box" class="legendRGB">RGB</span><div id="boxSpacer">' + abbreviateNum(d.RGB) + '</div> ' + '<span id="box" class="legendNIR">VNIR</span>' + abbreviateNum(d.VNIR) + ' sq. km ');
//Show the tooltip
d3.select("#tooltip").classed("hidden", false);
}
//Annotations
var annotations = g.append('g').attr('class','annotations');
// Doves //
// Flock 1D
annotations.append('g')
.append('line')
.attr('x1', 97)
.attr('y1', y(5000000))
.attr('x2', 97)
.attr('y2', y(1000000))
.attr("stroke-width", 1)
.attr('stroke-dasharray', '1, 2')
.attr("stroke", "#12BCC2");
annotations.append('g')
.append('text')
.attr('x', 78)
.attr('y', y(6000000))
.text('Flock 1d');
// FLOCK 1E
annotations.append('g')
.append('line')
.attr('x1', 184)
.attr('y1', y(8000000))
.attr('x2', 184)
.attr('y2', y(1000000))
.attr("stroke-width", 1)
.attr('stroke-dasharray', '1, 2')
.attr("stroke", "#12BCC2");
annotations.append('g')
.append('text')
.attr('x', 166)
.attr('y', y(9000000))
.text('Flock 1e');
// FLOCK 2B
annotations.append('g')
.append('line')
.attr('x1', 303)
.attr('y1', y(13000000))
.attr('x2', 303)
.attr('y2', y(1787234))
.attr("stroke-width", 1)
.attr('stroke-dasharray', '1, 2')
.attr("stroke", "#12BCC2");
annotations.append('g')
.append('text')
.attr('x', 285)
.attr('y', y(14221820))
.text('Flock 2b');
//Flock 2e
annotations.append('g')
.append('line')
.attr('x1', 408)
.attr('y1', y(20300000))
.attr('x2', 408)
.attr('y2', y(9255319))
.attr("stroke-width", 1)
.attr('stroke-dasharray', '1, 2')
.attr("stroke", "#12BCC2");
annotations.append('g')
.append('text')
.attr('x', 390)
.attr('y', y(21200000))
.text('Flock 2e');
//Flock 2e'
annotations.append('g')
.append('line')
.attr('x1', 508)
.attr('y1', y(24900000))
.attr('x2', 508)
.attr('y2', y(11438298))
.attr("stroke-width", 1)
.attr('stroke-dasharray', '1, 2')
.attr("stroke", "#12BCC2");
annotations.append('g')
.append('text')
.attr('x', 490)
.attr('y', y(26182704))
.text("Flock 2e'");
//Flock 2p
// annotations.append('g')
// .append('line')
// .attr('x1', 594)
// .attr('y1', y(29000000))
// .attr('x2', 594)
// .attr('y2', y(13500000))
// .attr("stroke-width", 1)
// .attr('stroke-dasharray', '1, 2')
// .attr("stroke", "#12BCC2");
annotations.append('g')
.append('line')
.attr('x1', 594)
.attr('y1', y(8510638))
.attr('x2', 594)
.attr('y2', y(29002979))
.attr("stroke-width", 1)
.attr('stroke-dasharray', '1, 2')
.attr("stroke", "#12BCC2");
annotations.append('g')
.append('text')
.attr('x', 576)
.attr('y', y(30000000))
.text('Flock 2p');
//Build 12 Deployment
// annotations.append('g')
// .append('text')
// .attr('x', 460)
// .attr('y', y(30500000))
// .text('Build 12 Dove Satellites Deployed');
// annotations.append('g')
// .append('line')
// .attr('x1', 533)
// .attr('y1', y(1000000))
// .attr('x2', 533)
// .attr('y2', y(29000000))
// .attr("stroke-width", 1)
// .attr('stroke-dasharray', '2, 2, 5')
// .attr("stroke", "rgb(119,119,119)");
});
function type(d, _, columns) {
d.date = parseTime(d.date);
for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c];
return d;
}
</script>
https://d3js.org/d3.v4.min.js