|
<!DOCTYPE html> |
|
<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> |