forked from jadiehm's block: Line area chart with swoopy drag annotations
-
-
Save jdspersonal/9718cabadc444394f2c4f8bc77ff40de to your computer and use it in GitHub Desktop.
Line area chart with swoopy drag annotations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(root, factory) { | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = factory(require('d3')); | |
} else if (typeof define === 'function' && define.amd) { | |
define(['d3'], factory); | |
} else { | |
root.d3 = factory(root.d3); | |
} | |
}(this, function(d3) { | |
d3.selection.prototype.translate = function(xy) { | |
return this.attr('transform', function(d,i) { | |
return 'translate('+[typeof xy == 'function' ? xy.call(this, d,i) : xy]+')'; | |
}); | |
}; | |
d3.transition.prototype.translate = function(xy) { | |
return this.attr('transform', function(d,i) { | |
return 'translate('+[typeof xy == 'function' ? xy.call(this, d,i) : xy]+')'; | |
}); | |
}; | |
d3.selection.prototype.tspans = function(lines, lh) { | |
return this.selectAll('tspan') | |
.data(lines) | |
.enter() | |
.append('tspan') | |
.text(function(d) { return d; }) | |
.attr('x', 0) | |
.attr('dy', function(d,i) { return i ? lh || 15 : 0; }); | |
}; | |
d3.selection.prototype.append = function(name) { | |
var n = d3_parse_attributes(name), s; | |
name = n.attr ? n.tag : name; | |
name = d3_selection_creator(name); | |
s = this.select(function() { | |
return this.appendChild(name.apply(this, arguments)); | |
}); | |
//attrs not provided by default in v4 | |
for (var name in n.attr) { s.attr(name, n.attr[name]) } | |
return s; | |
}; | |
d3.selection.prototype.insert = function(name, before) { | |
var n = d3_parse_attributes(name), s; | |
name = n.attr ? n.tag : name; | |
name = d3_selection_creator(name); | |
before = d3_selection_selector(before); | |
s = this.select(function() { | |
return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); | |
}); | |
//attrs not provided by default in v4 | |
for (var name in n.attr) { s.attr(name, n.attr[name]) } | |
return s; | |
}; | |
//no selection.enter in v4 | |
if (d3.selection.enter){ | |
d3.selection.enter.prototype.append = d3.selection.prototype.append | |
d3.selection.enter.prototype.insert = d3.selection.prototype.insert | |
} | |
var d3_parse_attributes_regex = /([\.#])/g; | |
function d3_parse_attributes(name) { | |
if (typeof name === "string") { | |
var attr = {}, | |
parts = name.split(d3_parse_attributes_regex), p; | |
name = parts.shift(); | |
while ((p = parts.shift())) { | |
if (p == '.') attr['class'] = attr['class'] ? attr['class'] + ' ' + parts.shift() : parts.shift(); | |
else if (p == '#') attr.id = parts.shift(); | |
} | |
return attr.id || attr['class'] ? { tag: name, attr: attr } : name; | |
} | |
return name; | |
} | |
function d3_selection_creator(name) { | |
var qualify = d3.namespace || d3.ns.qualify //v4 API change | |
return typeof name === "function" ? name : (name = qualify(name)).local ? function() { | |
return this.ownerDocument.createElementNS(name.space, name.local); | |
} : function() { | |
return this.ownerDocument.createElementNS(this.namespaceURI, name); | |
}; | |
} | |
function d3_selection_selector(selector) { | |
return typeof selector === "function" ? selector : function() { | |
return this.querySelector(selector); | |
}; | |
} | |
d3.wordwrap = function(line, maxCharactersPerLine) { | |
var w = line.split(' '), | |
lines = [], | |
words = [], | |
maxChars = maxCharactersPerLine || 40, | |
l = 0; | |
w.forEach(function(d) { | |
if (l+d.length > maxChars) { | |
lines.push(words.join(' ')); | |
words.length = 0; | |
l = 0; | |
} | |
l += d.length; | |
words.push(d); | |
}); | |
if (words.length) { | |
lines.push(words.join(' ')); | |
} | |
return lines; | |
}; | |
d3.ascendingKey = function(key) { | |
return typeof key == 'function' ? function (a, b) { | |
return key(a) < key(b) ? -1 : key(a) > key(b) ? 1 : key(a) >= key(b) ? 0 : NaN; | |
} : function (a, b) { | |
return a[key] < b[key] ? -1 : a[key] > b[key] ? 1 : a[key] >= b[key] ? 0 : NaN; | |
}; | |
}; | |
d3.descendingKey = function(key) { | |
return typeof key == 'function' ? function (a, b) { | |
return key(b) < key(a) ? -1 : key(b) > key(a) ? 1 : key(b) >= key(a) ? 0 : NaN; | |
} : function (a, b) { | |
return b[key] < a[key] ? -1 : b[key] > a[key] ? 1 : b[key] >= a[key] ? 0 : NaN; | |
}; | |
}; | |
d3.f = function(){ | |
var functions = arguments; | |
//convert all string arguments into field accessors | |
var i = 0, l = functions.length; | |
while (i < l) { | |
if (typeof(functions[i]) === 'string' || typeof(functions[i]) === 'number'){ | |
functions[i] = (function(str){ return function(d){ return d[str] }; })(functions[i]) | |
} | |
i++; | |
} | |
//return composition of functions | |
return function(d) { | |
var i=0, l = functions.length; | |
while (i++ < l) d = functions[i-1].call(this, d); | |
return d; | |
}; | |
}; | |
// store d3.f as convenient unicode character function (alt-f on macs) | |
if (typeof window !== 'undefined' && !window.hasOwnProperty('ƒ')) window.ƒ = d3.f; | |
// this tweak allows setting a listener for multiple events, jquery style | |
var d3_selection_on = d3.selection.prototype.on; | |
d3.selection.prototype.on = function(type, listener, capture) { | |
if (typeof type == 'string' && type.indexOf(' ') > -1) { | |
type = type.split(' '); | |
for (var i = 0; i<type.length; i++) { | |
d3_selection_on.apply(this, [type[i], listener, capture]); | |
} | |
} else { | |
d3_selection_on.apply(this, [type, listener, capture]); | |
} | |
return this; | |
}; | |
// for everyone's sake, let's add prop as alias for property | |
d3.selection.prototype.prop = d3.selection.prototype.property; | |
// combines data().enter().append() | |
d3.selection.prototype.appendMany = function(data, name){ | |
return this.selectAll(name).data(data).enter().append(name); | |
}; | |
return d3; | |
})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html lang='en-GB'> | |
<head> | |
<meta charset='utf-8'> | |
</head> | |
<style> | |
body { | |
font-family: sans-serif;; | |
font-size: 16px; | |
line-height: 1.4; | |
display: block; | |
margin: 0; | |
padding: 0; | |
color: #333; | |
-webkit-font-smoothing: antialiased; | |
} | |
p { | |
font-family: sans-serif; | |
font-size: 14px; | |
margin: 5px 0 0 0; | |
} | |
/*template styles*/ | |
.gia-chart-wrapper { | |
max-width: 960px; | |
margin: 0 auto; | |
} | |
/*chart styles*/ | |
.y.axis line { | |
fill: none; | |
stroke: #dcdcdc; | |
stroke-dasharray: 1px 1px; | |
shape-rendering: crispEdges; | |
stroke-width: 1px; | |
} | |
.x.axis line { | |
fill: none; | |
stroke: #333333; | |
shape-rendering: crispEdges; | |
stroke-width: 1px; | |
} | |
.tick.g-baseline line { | |
stroke: #333333; | |
stroke-dasharray: 0; | |
stroke-width: 1px; | |
} | |
.axis text { | |
font-family: sans-serif; | |
font-size: 12px; | |
pointer-events: none; | |
fill: #bdbdbd; | |
} | |
.y.axis text { | |
text-anchor: end !important; | |
font-size:12px; | |
fill: #bdbdbd; | |
} | |
.domain { | |
display: none; | |
} | |
.line { | |
stroke: #4bc6df; | |
stroke-width: 2px; | |
fill: none; | |
} | |
.area { | |
fill: #4bc6df; | |
opacity: 0.1; | |
} | |
.g-label-circle { | |
fill: #4bc6df; | |
} | |
.g-label-text, .g-label-text-bold { | |
font-family: sans-serif; | |
font-size: 14px; | |
text-align: left; | |
} | |
.g-label-text-bold { | |
font-weight: 700; | |
} | |
.annotations path{ | |
fill: none; | |
stroke: black; | |
} | |
.annotations g:hover circle{ | |
stroke: red; | |
} | |
.annotations g:hover text{ | |
fill: red; | |
} | |
.swoopy-drag-lines path { | |
fill: none; | |
stroke: #333333; | |
} | |
.swoopy-drag-lines text { | |
font-family: sans-serif; | |
font-size: 14px; | |
text-align: left; | |
fill: #333333; | |
} | |
.swoopy-drag-lines tspan:first-child { | |
font-weight: 700; | |
} | |
@media (max-width: 575px) { | |
.label-group1, .label-group3, .label-group4, .label-group5 { | |
display: none; | |
} | |
} | |
@media (max-width: 475px) { | |
.label-group1, .label-group2, .label-group3, .label-group4, .label-group5 { | |
display: none; | |
} | |
} | |
@media (max-width: 375px) { | |
.label-group1, .label-group2, .label-group3, .label-group4, .label-group5, .label-group6, .label-group7 { | |
display: none; | |
} | |
} | |
</style> | |
<body> | |
<main> | |
<div class='gia-chart-wrapper'> | |
<div class='gia-chart'> | |
</div> | |
</div> | |
</main> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script> | |
<script src='d3-jetpack.js'></script> | |
<script src='swoopy-drag.js'></script> | |
<script> | |
//Margin conventions | |
var margin = {top: 50, right: 5, bottom: 30, left: 25}; | |
var widther = d3.select(".gia-chart").node().clientWidth; | |
var width = widther - margin.left - margin.right, | |
height = 430 - margin.top - margin.bottom; | |
//Parses date for correct time format | |
var parseDate = d3.time.format("%e-%b-%y").parse; | |
var monthArr = ['Jan.', 'Feb.', 'March', 'Apr.', 'May', 'June', 'July', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.']; | |
//Appends the svg to the chart-container div | |
var svg = d3.select(".gia-chart").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 + ")"); | |
//Creates the xScale | |
var xScale = d3.time.scale() | |
.range([0, width]); | |
//Creates the yScale | |
var yScale = d3.scale.linear() | |
.range([height, 0]); | |
//Defines the y axis styles | |
var yAxis = d3.svg.axis() | |
.scale(yScale) | |
.tickSize(-width) | |
.tickPadding(8) | |
.orient("left"); | |
//Defines the y axis styles | |
var xAxis = d3.svg.axis() | |
.scale(xScale) | |
.tickPadding(8) | |
.orient("bottom") | |
.ticks(6) | |
.tickFormat(d3.time.format("%Y")); | |
//line function convention (feeds an array) | |
var line = d3.svg.line() | |
.x(function(d) { return xScale(d.time); }) | |
.y(function(d) { return yScale(d.value); }); | |
//area function | |
var area = d3.svg.area() | |
.x(function(d) {return xScale(d.time); }) | |
.y0(height) | |
.y1(function(d) {return yScale(d.value); }); | |
//Loads the data | |
d3.csv("swhc.csv", ready); | |
function ready(err, data) { | |
if (err) throw "error loading data"; | |
//FORMAT data | |
data.forEach(function(d) { | |
d.value = +d.value; | |
d.time = parseDate(d.time); | |
}); | |
//Organizes the data | |
data.sort(function(a,b) { return a.time - b.time; }); | |
var maxY = d3.max(data, function(d) { return d.value; }); | |
//Defines the xScale max | |
xScale.domain(d3.extent(data, function(d) { return d.time; })); | |
//Defines the yScale max | |
yScale.domain([0, 30]); | |
//Appends the y axis | |
var yAxisGroup = svg.append("g") | |
.attr("class", "y axis") | |
.call(yAxis) | |
.selectAll("g") | |
.classed("g-baseline", function(d) {return d == 0}); | |
//Appends the x axis | |
var xAxisGroup = svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis); | |
//Binds the data to the line | |
var drawarea = svg.append("path") | |
.datum(data) | |
.attr("class", "area") | |
.attr("d", area); | |
//Binds the data to the line | |
var drawline = svg.append("path") | |
.datum(data) | |
.attr("class", "line") | |
.attr("d", line); | |
//Adding labels | |
var labelElements = svg.append("g") | |
.attr("class", "fiddly-bits") | |
var label = labelElements.selectAll(".g-label-element") | |
.data(data.filter(function(d) { return d.event == "yes"; })) | |
.enter().append("g") | |
.attr("class", "g-label-element") | |
.attr("transform", function(d) { return "translate(" + xScale(d.time) + "," + yScale(d.value) + ")"; } ); | |
label.append("circle") | |
.attr("r", 3) | |
.attr("class", "g-label-circle"); | |
/* | |
label.append("text") | |
.attr("x", 0) | |
.attr("y", function(d) { | |
if (d.position == "down") { return 30; } | |
else { return -26; } | |
}) | |
.text(function(d) { return monthArr[d.time.getMonth()] + " " + d.time.getDate() + ", " + d.time.getFullYear() ; }) | |
.style("text-anchor","end") | |
.attr("class", "g-label-text-bold"); | |
label.append("text") | |
.attr("x", 0) | |
.attr("y", function(d) { | |
if (d.position == "down") { return 46; } | |
else { return -10; } | |
}) | |
.text(function(d) { return d.desc_info; }) | |
.style("text-anchor","end") | |
.attr("class", "g-label-text"); | |
*/ | |
//Swoopy-drag | |
var annotations = [ | |
{ | |
"xVal": 1467864000000, | |
"yVal": 28.04, | |
"path": "M0,-36L0,-9", | |
"text": "July 7, 2016 Dallas police shooting", | |
"textOffset": [ | |
-76, | |
-61 | |
] | |
}, | |
{ | |
"xVal": 1465704000000, | |
"yVal": 22.5, | |
"path": "M-113,-81C-62,-103,-6,-89,-1,-11", | |
"text": "June 12, 2016 Orlando nightclub shooting", | |
"textOffset": [ | |
-172, | |
-67 | |
] | |
}, | |
{ | |
"xVal": 1449032400000, | |
"yVal": 18.18, | |
"path": "M0,60L0,3", | |
"text": "Dec. 2, 2015 San Bernardino terrorist attack", | |
"textOffset": [ | |
-23, | |
80 | |
] | |
}, | |
{ | |
"xVal": 1434513600000, | |
"yVal": 15.75, | |
"path": "M0,85L0,5", | |
"text": "June 17, 2015 Charleston church shooting", | |
"textOffset": [ | |
-58, | |
102 | |
] | |
}, | |
{ | |
"xVal": 1403928000000, | |
"yVal": 13.55, | |
"path": "M50,-67C14,-65,0,-34,14,-6", | |
"text": "July 28, 2014 S&W charged with bribing foreign officials", | |
"textOffset": [ | |
53, | |
-93 | |
] | |
}, | |
{ | |
"xVal": 1400817600000, | |
"yVal": 15.08, | |
"path": "M-80,-92C-27,-93,9,-58,-1,-8", | |
"text": "May 23, 2014 Isla Vista shooting", | |
"textOffset": [ | |
-144, | |
-117 | |
] | |
}, | |
{ | |
"xVal": 1379304000000, | |
"yVal": 10.94, | |
"path": "M0,41L0,4", | |
"text": "Sept. 16, 2013 Washington, DC Navy Yard shooting", | |
"textOffset": [ | |
-25, | |
57 | |
] | |
}, | |
{ | |
"xVal": 1355461200000, | |
"yVal": 9.05, | |
"path": "M-20,-79C13,-66,27,-27,3,-7", | |
"text": "Dec. 14, 2012 Sandy Hook school shooting", | |
"textOffset": [ | |
-71, | |
-102 | |
] | |
} | |
] | |
var swoopy = d3.swoopyDrag() | |
.x(function(d){ return xScale(d.xVal) }) | |
.y(function(d){ return yScale(d.yVal) }) | |
.draggable(false) | |
.annotations(annotations) | |
var swoopySel = svg.append('g').call(swoopy) | |
.attr("class", "swoopy-drag-lines"); | |
swoopySel.selectAll('text') | |
.each(function(d){ | |
d3.select(this) | |
.text('') //clear existing text | |
.tspans(d3.wordwrap(d.text, 12)) //wrap after 20 char | |
}); | |
swoopySel.selectAll('g') | |
.attr("class", function(d, i) { | |
return 'label-group'+i; | |
}); | |
//RESPONSIVENESS | |
d3.select(window).on("resize", resized); | |
function resized() { | |
//new margin | |
var newMargin = {top: 30, right: 5, bottom: 30, left: 25}; | |
var newWidther = d3.select(".gia-chart").node().clientWidth; | |
var newWidth = newWidther - newMargin.left - newMargin.right; | |
//Change the width of the svg | |
d3.select("svg") | |
.attr("width", newWidth + newMargin.left + newMargin.right); | |
//Change the xScale | |
xScale | |
.range([0, newWidth]); | |
//Update the line | |
line = d3.svg.line() | |
.x(function(d) { return xScale(d.time); }) | |
.y(function(d) { return yScale(d.value); }); | |
d3.selectAll('.line') | |
.attr("d", line); | |
//Updates circle labels | |
d3.selectAll('.g-label-element') | |
.attr("transform", function(d) { return "translate(" + xScale(d.time) + "," + yScale(d.value) + ")"; } ); | |
//Update the area | |
area = d3.svg.area() | |
.x(function(d) {return xScale(d.time); }) | |
.y0(height) | |
.y1(function(d) {return yScale(d.value); }); | |
d3.selectAll('.area') | |
.attr("d", area); | |
//Updates xAxis | |
d3.selectAll(".x.axis") | |
.call(xAxis); | |
//Updates ticks | |
xAxis | |
.scale(xScale); | |
//Updates yAxis | |
d3.selectAll(".y.axis") | |
.call(yAxis); | |
yAxis | |
.tickSize(-newWidth); | |
swoopySel.remove(); | |
swoopySel = svg.append('g').call(swoopy) | |
.attr("class", "swoopy-drag-lines"); | |
swoopySel.selectAll('g') | |
.attr("class", function(d, i) { | |
return 'label-group'+i; | |
}); | |
swoopySel.selectAll('text') | |
.each(function(d){ | |
d3.select(this) | |
.text('') //clear existing text | |
.tspans(d3.wordwrap(d.text, 12)) //wrap after 20 char | |
}) | |
}; | |
} | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
time | value | |
---|---|---|
2018-06-01T00:00:00.000Z | 37318098.4799999 | |
2018-06-02T00:00:00.000Z | 35200822.81999995 | |
2018-06-03T00:00:00.000Z | 23225827.90000017 | |
2018-06-04T00:00:00.000Z | 28364938.010000043 | |
2018-06-05T00:00:00.000Z | 29760666.01999992 | |
2018-06-06T00:00:00.000Z | 28050074.360000018 | |
2018-06-07T00:00:00.000Z | 31219660.58999986 | |
2018-06-08T00:00:00.000Z | 29952565.92999995 | |
2018-06-09T00:00:00.000Z | 32772572.21999995 | |
2018-06-10T00:00:00.000Z | 22620799.570000127 | |
2018-06-11T00:00:00.000Z | 29660438.430000015 | |
2018-06-12T00:00:00.000Z | 33174527.789999943 | |
2018-06-13T00:00:00.000Z | 32342782.529999916 | |
2018-06-14T00:00:00.000Z | 30625570.219999872 | |
2018-06-15T00:00:00.000Z | 25948493.830000028 | |
2018-06-16T00:00:00.000Z | 25833050.03000013 | |
2018-06-17T00:00:00.000Z | 17886698.250000067 | |
2018-06-18T00:00:00.000Z | 20566058.39 | |
2018-06-19T00:00:00.000Z | 22448159.759999953 | |
2018-06-20T00:00:00.000Z | 26195582.169999976 | |
2018-06-21T00:00:00.000Z | 28678938.56999989 | |
2018-06-22T00:00:00.000Z | 5979358.1999999955 | |
2018-06-23T00:00:00.000Z | 550823.2600000001 | |
2018-06-24T00:00:00.000Z | 19348286.710000083 | |
2018-06-25T00:00:00.000Z | 28853964.86000002 | |
2018-06-26T00:00:00.000Z | 28020644.01000005 | |
2018-06-27T00:00:00.000Z | 27035135.82000005 | |
2018-06-28T00:00:00.000Z | 28863801.06000009 | |
2018-06-29T00:00:00.000Z | 30753024.780000024 | |
2018-06-30T00:00:00.000Z | 29036676.5100001 | |
2018-07-01T00:00:00.000Z | 18273642.16000008 | |
2018-07-02T00:00:00.000Z | 26319319.850000028 | |
2018-07-03T00:00:00.000Z | 21927335.17000002 | |
2018-07-04T00:00:00.000Z | 25789378.95000001 | |
2018-07-05T00:00:00.000Z | 27405314.26999995 | |
2018-07-06T00:00:00.000Z | 25865165.679999974 | |
2018-07-07T00:00:00.000Z | 20457663.050000053 | |
2018-07-08T00:00:00.000Z | 14375680.400000034 | |
2018-07-09T00:00:00.000Z | 25525487.359999985 | |
2018-07-10T00:00:00.000Z | 22564465.650000006 | |
2018-07-11T00:00:00.000Z | 22827990.970000036 | |
2018-07-12T00:00:00.000Z | 23657926.910000023 | |
2018-07-13T00:00:00.000Z | 24162583.140000034 | |
2018-07-14T00:00:00.000Z | 20625699.200000092 | |
2018-07-15T00:00:00.000Z | 13294208.13000003 | |
2018-07-16T00:00:00.000Z | 22833595.510000113 | |
2018-07-17T00:00:00.000Z | 23550366.61000009 | |
2018-07-18T00:00:00.000Z | 25607971.090000078 | |
2018-07-19T00:00:00.000Z | 24400357.20000006 | |
2018-07-20T00:00:00.000Z | 26073817.160000056 | |
2018-07-21T00:00:00.000Z | 20837664.700000096 | |
2018-07-22T00:00:00.000Z | 14125018.160000041 | |
2018-07-23T00:00:00.000Z | 22497301.800000027 | |
2018-07-24T00:00:00.000Z | 20708570.920000058 | |
2018-07-25T00:00:00.000Z | 26697267.600000028 | |
2018-07-26T00:00:00.000Z | 22614289.470000073 | |
2018-07-27T00:00:00.000Z | 27603181.509999983 | |
2018-07-28T00:00:00.000Z | 23813998.020000055 | |
2018-07-29T00:00:00.000Z | 16391522.820000065 | |
2018-07-30T00:00:00.000Z | 24225155.690000027 | |
2018-07-31T00:00:00.000Z | 21393142.390000045 | |
2018-08-01T00:00:00.000Z | 22475794.34000004 | |
2018-08-02T00:00:00.000Z | 22234699.500000034 | |
2018-08-03T00:00:00.000Z | 21954382.709999993 | |
2018-08-04T00:00:00.000Z | 18811835.69000005 | |
2018-08-05T00:00:00.000Z | 13660423.920000026 | |
2018-08-06T00:00:00.000Z | 21132751.949999966 | |
2018-08-07T00:00:00.000Z | 19147202.75999996 | |
2018-08-08T00:00:00.000Z | 17745879.499999974 | |
2018-08-09T00:00:00.000Z | 19279651.659999985 | |
2018-08-10T00:00:00.000Z | 22445957.59999992 | |
2018-08-11T00:00:00.000Z | 20952838.270000003 | |
2018-08-12T00:00:00.000Z | 15985039.800000051 | |
2018-08-13T00:00:00.000Z | 20019541.07999999 | |
2018-08-14T00:00:00.000Z | 20834954.679999985 | |
2018-08-15T00:00:00.000Z | 21523077.30999996 | |
2018-08-16T00:00:00.000Z | 20103743.509999964 | |
2018-08-17T00:00:00.000Z | 22528607.079999905 | |
2018-08-18T00:00:00.000Z | 24803632.73999998 | |
2018-08-19T00:00:00.000Z | 18343864.350000057 | |
2018-08-20T00:00:00.000Z | 26431426.799999904 | |
2018-08-21T00:00:00.000Z | 21262228.45999998 | |
2018-08-22T00:00:00.000Z | 19797715.599999994 | |
2018-08-23T00:00:00.000Z | 18948100.250000007 | |
2018-08-24T00:00:00.000Z | 37014586.919999674 | |
2018-08-25T00:00:00.000Z | 34941495.269999824 | |
2018-08-26T00:00:00.000Z | 22710635.390000027 | |
2018-08-27T00:00:00.000Z | 24672881.989999905 | |
2018-08-28T00:00:00.000Z | 24197944.14999989 | |
2018-08-29T00:00:00.000Z | 23905824.67999989 | |
2018-08-30T00:00:00.000Z | 23520759.64999986 | |
2018-08-31T00:00:00.000Z | 26648384.38999978 | |
2018-09-01T00:00:00.000Z | 32029759.98999966 | |
2018-09-02T00:00:00.000Z | 19190491.220000017 | |
2018-09-03T00:00:00.000Z | 16800216.00999999 | |
2018-09-04T00:00:00.000Z | 17626358.71999998 | |
2018-09-05T00:00:00.000Z | 18504007.86999996 | |
2018-09-06T00:00:00.000Z | 19665093.76999995 | |
2018-09-07T00:00:00.000Z | 22012685.019999873 | |
2018-09-08T00:00:00.000Z | 28729725.389999885 | |
2018-09-09T00:00:00.000Z | 16310304.350000061 | |
2018-09-10T00:00:00.000Z | 14291240.260000031 | |
2018-09-11T00:00:00.000Z | 16876559.07999998 | |
2018-09-12T00:00:00.000Z | 19057559.449999962 | |
2018-09-13T00:00:00.000Z | 19397458.94999997 | |
2018-09-14T00:00:00.000Z | 22678717.20999991 | |
2018-09-15T00:00:00.000Z | 29504492.119999893 | |
2018-09-16T00:00:00.000Z | 17293666.730000064 | |
2018-09-17T00:00:00.000Z | 15340411.120000036 | |
2018-09-18T00:00:00.000Z | 16072178.810000017 | |
2018-09-19T00:00:00.000Z | 17172371.119999986 | |
2018-09-20T00:00:00.000Z | 20595878.669999976 | |
2018-09-21T00:00:00.000Z | 22109340.109999932 | |
2018-09-22T00:00:00.000Z | 31381853.279999875 | |
2018-09-23T00:00:00.000Z | 18232363.060000096 | |
2018-09-24T00:00:00.000Z | 18549511.460000094 | |
2018-09-25T00:00:00.000Z | 28996585.769999582 | |
2018-09-26T00:00:00.000Z | 26546703.44999981 | |
2018-09-27T00:00:00.000Z | 33100174.83999963 | |
2018-09-28T00:00:00.000Z | 33123705.619999647 | |
2018-09-29T00:00:00.000Z | 41106428.77999939 | |
2018-09-30T00:00:00.000Z | 24590793.140000008 | |
2018-10-01T00:00:00.000Z | 19832385.630000006 | |
2018-10-02T00:00:00.000Z | 21736936.840000022 | |
2018-10-03T00:00:00.000Z | 23340744.61000004 | |
2018-10-04T00:00:00.000Z | 24940860.549999982 | |
2018-10-05T00:00:00.000Z | 26488543.209999885 | |
2018-10-06T00:00:00.000Z | 34853383.849999696 | |
2018-10-07T00:00:00.000Z | 20584618.030000117 | |
2018-10-08T00:00:00.000Z | 16565998.900000073 | |
2018-10-09T00:00:00.000Z | 17414663.15 | |
2018-10-10T00:00:00.000Z | 18120533.01999998 | |
2018-10-11T00:00:00.000Z | 18187773.94999998 | |
2018-10-12T00:00:00.000Z | 21543195.2099999 | |
2018-10-13T00:00:00.000Z | 27674049.7299999 | |
2018-10-14T00:00:00.000Z | 15743557.510000069 | |
2018-10-15T00:00:00.000Z | 14200923.520000072 | |
2018-10-16T00:00:00.000Z | 15427668.90000004 | |
2018-10-17T00:00:00.000Z | 16069347.06000004 | |
2018-10-18T00:00:00.000Z | 18094701.349999987 | |
2018-10-19T00:00:00.000Z | 24762888.74999982 | |
2018-10-20T00:00:00.000Z | 30621622.049999747 | |
2018-10-21T00:00:00.000Z | 17605562.350000117 | |
2018-10-22T00:00:00.000Z | 15774413.000000084 | |
2018-10-23T00:00:00.000Z | 16240147.640000064 | |
2018-10-24T00:00:00.000Z | 19071672.55 | |
2018-10-25T00:00:00.000Z | 29802037.559999418 | |
2018-10-26T00:00:00.000Z | 32140461.96999956 | |
2018-10-27T00:00:00.000Z | 38908406.979999416 | |
2018-10-28T00:00:00.000Z | 24626417.279999882 | |
2018-10-29T00:00:00.000Z | 23506036.989999924 | |
2018-10-30T00:00:00.000Z | 21277440.330000017 | |
2018-10-31T00:00:00.000Z | 22763249.769999932 | |
2018-11-01T00:00:00.000Z | 23807339.08999988 | |
2018-11-02T00:00:00.000Z | 27568010.839999802 | |
2018-11-03T00:00:00.000Z | 25106218.77999991 | |
2018-11-04T00:00:00.000Z | 15719207.870000059 | |
2018-11-05T00:00:00.000Z | 13667601.710000042 | |
2018-11-06T00:00:00.000Z | 15392047.570000041 | |
2018-11-07T00:00:00.000Z | 16935979.540000025 | |
2018-11-08T00:00:00.000Z | 21554674.909999996 | |
2018-11-09T00:00:00.000Z | 21977831.36999992 | |
2018-11-10T00:00:00.000Z | 28474813.869999964 | |
2018-11-11T00:00:00.000Z | 15302440.040000033 | |
2018-11-12T00:00:00.000Z | 12815078.310000058 | |
2018-11-13T00:00:00.000Z | 14057690.73999999 | |
2018-11-14T00:00:00.000Z | 14907514.009999987 | |
2018-11-15T00:00:00.000Z | 16198278.089999987 | |
2018-11-16T00:00:00.000Z | 19943852.92999989 | |
2018-11-17T00:00:00.000Z | 25912502.769999925 | |
2018-11-18T00:00:00.000Z | 15011677.180000082 | |
2018-11-19T00:00:00.000Z | 14241334.71000008 | |
2018-11-20T00:00:00.000Z | 17169496.650000047 | |
2018-11-21T00:00:00.000Z | 16806456.90000004 | |
2018-11-22T00:00:00.000Z | 18382934.70000001 | |
2018-11-23T00:00:00.000Z | 57578090.309998594 | |
2018-11-24T00:00:00.000Z | 37139682.60999963 | |
2018-11-25T00:00:00.000Z | 22055386.900000088 | |
2018-11-26T00:00:00.000Z | 19915713.280000065 | |
2018-11-27T00:00:00.000Z | 22473854.800000038 | |
2018-11-28T00:00:00.000Z | 23090355.85000005 | |
2018-11-29T00:00:00.000Z | 21858475.60000004 | |
2018-11-30T00:00:00.000Z | 26595035.319999952 | |
2018-12-01T00:00:00.000Z | 32625549.829999875 | |
2018-12-02T00:00:00.000Z | 21053152.70000007 | |
2018-12-03T00:00:00.000Z | 18084801.600000028 | |
2018-12-04T00:00:00.000Z | 20294950.920000028 | |
2018-12-05T00:00:00.000Z | 23172304.119999938 | |
2018-12-06T00:00:00.000Z | 23703590.709999975 | |
2018-12-07T00:00:00.000Z | 27095281.55999992 | |
2018-12-08T00:00:00.000Z | 34255904.629999734 | |
2018-12-09T00:00:00.000Z | 22701473.090000067 | |
2018-12-10T00:00:00.000Z | 19145366.900000043 | |
2018-12-11T00:00:00.000Z | 20890017.08000003 | |
2018-12-12T00:00:00.000Z | 23540452.069999922 | |
2018-12-13T00:00:00.000Z | 22690434.370000005 | |
2018-12-15T00:00:00.000Z | 43080451.13999956 | |
2018-12-16T00:00:00.000Z | 26841355.12999995 | |
2018-12-17T00:00:00.000Z | 26518618.46999987 | |
2018-12-18T00:00:00.000Z | 33110842.48999968 | |
2018-12-19T00:00:00.000Z | 39577369.48999962 | |
2018-12-20T00:00:00.000Z | 52920133.8799994 | |
2018-12-21T00:00:00.000Z | 90908315.81999984 | |
2018-12-22T00:00:00.000Z | 74485198.12000008 | |
2018-12-23T00:00:00.000Z | 52738707.17999951 | |
2018-12-24T00:00:00.000Z | 8191082.590000013 | |
2018-12-25T00:00:00.000Z | 2406514.1899999995 | |
2018-12-26T00:00:00.000Z | 64372612.65999955 | |
2018-12-27T00:00:00.000Z | 58085377.4299995 | |
2018-12-28T00:00:00.000Z | 53490851.709999524 | |
2018-12-29T00:00:00.000Z | 44591953.99999964 | |
2018-12-30T00:00:00.000Z | 35581974.549999766 | |
2018-12-31T00:00:00.000Z | 25135560.899999883 | |
2019-01-02T00:00:00.000Z | 25933653.32999991 | |
2019-01-03T00:00:00.000Z | 23723882.999999892 | |
2019-01-04T00:00:00.000Z | 24332766.36999988 | |
2019-01-05T00:00:00.000Z | 23080429.759999916 | |
2019-01-06T00:00:00.000Z | 13533799.050000042 | |
2019-01-07T00:00:00.000Z | 18378487.31999991 | |
2019-01-08T00:00:00.000Z | 16027820.279999984 | |
2019-01-09T00:00:00.000Z | 16112221.629999988 | |
2019-01-10T00:00:00.000Z | 16008129.66999997 | |
2019-01-11T00:00:00.000Z | 18466670.17999993 | |
2019-01-12T00:00:00.000Z | 24032203.799999923 | |
2019-01-13T00:00:00.000Z | 13990798.230000056 | |
2019-01-14T00:00:00.000Z | 12552685.870000055 | |
2019-01-15T00:00:00.000Z | 13237920.010000031 | |
2019-01-16T00:00:00.000Z | 13613017.710000042 | |
2019-01-17T00:00:00.000Z | 14165832.350000007 | |
2019-01-18T00:00:00.000Z | 21135985.059999883 | |
2019-01-19T00:00:00.000Z | 26199530.88999989 | |
2019-01-20T00:00:00.000Z | 15009574.440000065 | |
2019-01-21T00:00:00.000Z | 13128462.34000004 | |
2019-01-22T00:00:00.000Z | 14093098.870000018 | |
2019-01-23T00:00:00.000Z | 15122279.199999984 | |
2019-01-24T00:00:00.000Z | 16691719.339999948 | |
2019-01-25T00:00:00.000Z | 32325521.239999585 | |
2019-01-26T00:00:00.000Z | 37470154.639999606 | |
2019-01-27T00:00:00.000Z | 18288809.959999993 | |
2019-01-28T00:00:00.000Z | 15727602.749999944 | |
2019-01-29T00:00:00.000Z | 16562421.799999924 | |
2019-01-30T00:00:00.000Z | 17436300.689999927 | |
2019-01-31T00:00:00.000Z | 18057569.06999987 | |
2019-02-01T00:00:00.000Z | 20447066.279999822 | |
2019-02-02T00:00:00.000Z | 27350316.619999815 | |
2019-02-03T00:00:00.000Z | 13369680.690000057 | |
2019-02-04T00:00:00.000Z | 12510335.580000041 | |
2019-02-05T00:00:00.000Z | 13212346.770000003 | |
2019-02-06T00:00:00.000Z | 14506415.750000002 | |
2019-02-07T00:00:00.000Z | 15465113.319999957 | |
2019-02-08T00:00:00.000Z | 18927399.57999989 | |
2019-02-09T00:00:00.000Z | 28243363.40999987 | |
2019-02-10T00:00:00.000Z | 15156849.100000057 | |
2019-02-11T00:00:00.000Z | 13291643.299999991 | |
2019-02-12T00:00:00.000Z | 16690212.819999935 | |
2019-02-13T00:00:00.000Z | 16736657.979999939 | |
2019-02-14T00:00:00.000Z | 17084170.219999928 | |
2019-02-15T00:00:00.000Z | 18681833.709999885 | |
2019-02-16T00:00:00.000Z | 24146082.029999893 | |
2019-02-17T00:00:00.000Z | 13200523.630000051 | |
2019-02-18T00:00:00.000Z | 13408722.519999994 | |
2019-02-19T00:00:00.000Z | 14759092.979999958 | |
2019-02-20T00:00:00.000Z | 18503807.189999904 | |
2019-02-21T00:00:00.000Z | 16814470.009999935 | |
2019-02-22T00:00:00.000Z | 21859622.99999985 | |
2019-02-23T00:00:00.000Z | 25659614.149999898 | |
2019-02-24T00:00:00.000Z | 13892804.190000053 | |
2019-02-25T00:00:00.000Z | 20470486.389999844 | |
2019-02-26T00:00:00.000Z | 20902472.859999858 | |
2019-02-27T00:00:00.000Z | 22732398.409999862 | |
2019-02-28T00:00:00.000Z | 25405848.119999804 | |
2019-03-01T00:00:00.000Z | 26949560.659999795 | |
2019-03-02T00:00:00.000Z | 33551285.859999776 | |
2019-03-03T00:00:00.000Z | 16917981.670000035 | |
2019-03-04T00:00:00.000Z | 14640505.819999974 | |
2019-03-05T00:00:00.000Z | 15850028.359999958 | |
2019-03-06T00:00:00.000Z | 16971391.199999947 | |
2019-03-07T00:00:00.000Z | 17433514.559999924 | |
2019-03-08T00:00:00.000Z | 21452783.509999882 | |
2019-03-09T00:00:00.000Z | 30956693.22999988 | |
2019-03-10T00:00:00.000Z | 16959494.510000043 | |
2019-03-11T00:00:00.000Z | 16286705.189999996 | |
2019-03-12T00:00:00.000Z | 16385487.099999983 | |
2019-03-13T00:00:00.000Z | 15739235.059999997 | |
2019-03-14T00:00:00.000Z | 17287740.119999968 | |
2019-03-15T00:00:00.000Z | 21473764.06999988 | |
2019-03-16T00:00:00.000Z | 30456293.799999867 | |
2019-03-17T00:00:00.000Z | 16113410.980000056 | |
2019-03-18T00:00:00.000Z | 13705977.470000025 | |
2019-03-19T00:00:00.000Z | 16448366.94999997 | |
2019-03-20T00:00:00.000Z | 19272052.229999952 | |
2019-03-21T00:00:00.000Z | 19943306.129999943 | |
2019-03-22T00:00:00.000Z | 23372758.199999902 | |
2019-03-23T00:00:00.000Z | 34768031.459999785 | |
2019-03-24T00:00:00.000Z | 17375261.06000007 | |
2019-03-25T00:00:00.000Z | 21080868.779999893 | |
2019-03-26T00:00:00.000Z | 20536714.029999916 | |
2019-03-27T00:00:00.000Z | 23147506.769999888 | |
2019-03-28T00:00:00.000Z | 23684686.829999898 | |
2019-03-29T00:00:00.000Z | 27889583.379999854 | |
2019-03-30T00:00:00.000Z | 36090782.079999745 | |
2019-03-31T00:00:00.000Z | 20812255.290000074 | |
2019-04-01T00:00:00.000Z | 17061445.97999999 | |
2019-04-02T00:00:00.000Z | 18027847.099999983 | |
2019-04-03T00:00:00.000Z | 18462818.84999998 | |
2019-04-04T00:00:00.000Z | 19641133.049999963 | |
2019-04-05T00:00:00.000Z | 22814221.309999935 | |
2019-04-06T00:00:00.000Z | 30268523.3799999 | |
2019-04-07T00:00:00.000Z | 18317415.07000009 | |
2019-04-08T00:00:00.000Z | 14939201.840000063 | |
2019-04-09T00:00:00.000Z | 17497618.12999999 | |
2019-04-10T00:00:00.000Z | 19998450.129999936 | |
2019-04-11T00:00:00.000Z | 21646016.12999992 | |
2019-04-12T00:00:00.000Z | 24292128.30999991 | |
2019-04-13T00:00:00.000Z | 30700269.789999858 | |
2019-04-14T00:00:00.000Z | 18109930.520000093 | |
2019-04-15T00:00:00.000Z | 21318906.77999996 | |
2019-04-16T00:00:00.000Z | 22586033.84999997 | |
2019-04-17T00:00:00.000Z | 24826833.03999994 | |
2019-04-18T00:00:00.000Z | 32627779.519999694 | |
2019-04-19T00:00:00.000Z | 20104625.360000107 | |
2019-04-20T00:00:00.000Z | 23290976.650000066 | |
2019-04-21T00:00:00.000Z | 14280428.180000046 | |
2019-04-22T00:00:00.000Z | 18516970.0100001 | |
2019-04-23T00:00:00.000Z | 23220198.530000057 | |
2019-04-24T00:00:00.000Z | 23621890.52000006 | |
2019-04-25T00:00:00.000Z | 34528628.17999983 | |
2019-04-26T00:00:00.000Z | 40000468.26999977 | |
2019-04-27T00:00:00.000Z | 44763338.57999981 | |
2019-04-28T00:00:00.000Z | 26765973.020000085 | |
2019-04-29T00:00:00.000Z | 24958578.04 | |
2019-04-30T00:00:00.000Z | 23506627.519999985 | |
2019-05-01T00:00:00.000Z | 22717359.700000126 | |
2019-05-02T00:00:00.000Z | 22354056.409999948 | |
2019-05-03T00:00:00.000Z | 26204129.759999927 | |
2019-05-04T00:00:00.000Z | 33777822.03999991 | |
2019-05-05T00:00:00.000Z | 19525113.490000088 | |
2019-05-06T00:00:00.000Z | 16536585.770000013 | |
2019-05-07T00:00:00.000Z | 18018429.07000002 | |
2019-05-08T00:00:00.000Z | 23019920.139999833 | |
2019-05-09T00:00:00.000Z | 18899945.29 | |
2019-05-10T00:00:00.000Z | 22821047.979999945 | |
2019-05-11T00:00:00.000Z | 28833640.870000012 | |
2019-05-12T00:00:00.000Z | 17855361.840000067 | |
2019-05-13T00:00:00.000Z | 16297567.290000034 | |
2019-05-14T00:00:00.000Z | 17905106.040000007 | |
2019-05-15T00:00:00.000Z | 20496116.409999844 | |
2019-05-16T00:00:00.000Z | 20410830.71999998 | |
2019-05-17T00:00:00.000Z | 24513048.739999983 | |
2019-05-18T00:00:00.000Z | 29396536.609999996 | |
2019-05-19T00:00:00.000Z | 18598606.79000007 | |
2019-05-20T00:00:00.000Z | 23334505.500000067 | |
2019-05-21T00:00:00.000Z | 24897226.3000001 | |
2019-05-22T00:00:00.000Z | 28317934.130000044 | |
2019-05-23T00:00:00.000Z | 24205120.95000004 | |
2019-05-24T00:00:00.000Z | 37984593.43999978 | |
2019-05-25T00:00:00.000Z | 44530931.99999979 | |
2019-05-26T00:00:00.000Z | 25081486.87000009 | |
2019-05-27T00:00:00.000Z | 24996197.579999927 | |
2019-05-28T00:00:00.000Z | 26286860.559999924 | |
2019-05-29T00:00:00.000Z | 28690690.259999935 | |
2019-05-30T00:00:00.000Z | 29305670.389999975 | |
2019-05-31T00:00:00.000Z | 41570463.16999971 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
d3.swoopyDrag = function(){ | |
var x = d3.scale.linear() | |
var y = d3.scale.linear() | |
var annotations = [] | |
var annotationSel | |
var draggable = false | |
var dispatch = d3.dispatch('drag') | |
var textDrag = d3.behavior.drag() | |
.on('drag', function(d){ | |
var x = d3.event.x | |
var y = d3.event.y | |
d.textOffset = [x, y].map(Math.round) | |
d3.select(this).call(translate, d.textOffset) | |
dispatch.drag() | |
}) | |
.origin(function(d){ return {x: d.textOffset[0], y: d.textOffset[1]} }) | |
var circleDrag = d3.behavior.drag() | |
.on('drag', function(d){ | |
var x = d3.event.x | |
var y = d3.event.y | |
d.pos = [x, y].map(Math.round) | |
var parentSel = d3.select(this.parentNode) | |
var path = '' | |
parentSel.selectAll('circle').each(function(d){ | |
path = path + '' + d.type + d.pos | |
}) | |
parentSel.select('path').attr('d', path).datum().path = path | |
d3.select(this).call(translate, d.pos) | |
dispatch.drag() | |
}) | |
.origin(function(d){ return {x: d.pos[0], y: d.pos[1]} }) | |
var rv = function(sel){ | |
annotationSel = sel.selectAll('g').data(annotations) | |
annotationSel.exit().remove() | |
annotationSel.enter().append('g') | |
annotationSel.call(translate, function(d){ return [x(d), y(d)] }) | |
var textSel = annotationSel.append('text') | |
.call(translate, ƒ('textOffset')) | |
.text(ƒ('text')) | |
annotationSel.append('path') | |
.attr('d', ƒ('path')) | |
if (!draggable) return | |
annotationSel.style('cursor', 'pointer') | |
textSel.call(textDrag) | |
annotationSel.selectAll('circle').data(function(d){ | |
var points = [] | |
var i = 1 | |
var type = 'M' | |
var commas = 0 | |
for (var j = 1; j < d.path.length; j++){ | |
var curChar = d.path[j] | |
if (curChar == ',') commas++ | |
if (curChar == 'L' || curChar == 'C' || commas == 2){ | |
points.push({pos: d.path.slice(i, j).split(','), type: type}) | |
type = curChar | |
i = j + 1 | |
commas = 0 | |
} | |
} | |
points.push({pos: d.path.slice(i, j).split(','), type: type}) | |
return points | |
}).enter().append('circle') | |
.attr({r: 8, fill: 'rgba(0,0,0,0)', stroke: '#333', 'stroke-dasharray': '2 2'}) | |
.call(translate, ƒ('pos')) | |
.call(circleDrag) | |
dispatch.drag() | |
} | |
rv.annotations = function(_x){ | |
if (typeof(_x) == 'undefined') return annotations | |
annotations = _x | |
return rv | |
} | |
rv.x = function(_x){ | |
if (typeof(_x) == 'undefined') return x | |
x = _x | |
return rv | |
} | |
rv.y = function(_x){ | |
if (typeof(_x) == 'undefined') return y | |
y = _x | |
return rv | |
} | |
rv.draggable = function(_x){ | |
if (typeof(_x) == 'undefined') return draggable | |
draggable = _x | |
return rv | |
} | |
return d3.rebind(rv, dispatch, 'on') | |
//no jetpack dependency | |
function translate(sel, pos){ | |
sel.attr('transform', function(d){ | |
var posStr = typeof(pos) == 'function' ? pos(d) : pos | |
return 'translate(' + posStr + ')' | |
}) | |
} | |
function ƒ(str){ return function(d){ return d[str] } } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment