Skip to content

Instantly share code, notes, and snippets.

@jdspersonal
Forked from lorenzopub/.block
Last active June 13, 2019 18:46
Show Gist options
  • Save jdspersonal/9718cabadc444394f2c4f8bc77ff40de to your computer and use it in GitHub Desktop.
Save jdspersonal/9718cabadc444394f2c4f8bc77ff40de to your computer and use it in GitHub Desktop.
Line area chart with swoopy drag annotations
license: mit
(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;
}));
<!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>
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
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