Join points with a parabolic interpolator, for Chris Henrick.
See the sinusoidal version.
Built with blockbuilder.org
license: mit |
Join points with a parabolic interpolator, for Chris Henrick.
See the sinusoidal version.
Built with blockbuilder.org
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } | |
</style> | |
</head> | |
<body> | |
<script> | |
var svg = d3.select("body").append("svg") | |
.attr("width", width = 960) | |
.attr("height", height = 500) | |
var steps = 400; | |
var parset = d3.timeParse('%m/%d/%y %H:%M'); | |
var data = d3.csvParse(`Date_Time,Event,Speed | |
3/31/17 0:24,flood,1.59 | |
3/31/17 3:42,slack,0 | |
3/31/17 7:12,ebb,-1.86 | |
3/31/17 10:30,slack,0 | |
3/31/17 13:12,flood,1.43 | |
3/31/17 17:00,slack,0 | |
3/31/17 20:00,ebb,-1.45 | |
3/31/17 22:42,slack,0 | |
4/1/17 1:12,flood,1.48 | |
4/1/17 4:24,slack,0 | |
4/1/17 8:06,ebb,-1.74 | |
4/1/17 11:30,slack,0 | |
4/1/17 14:06,flood,1.23 | |
4/1/17 18:06,slack,0 | |
4/1/17 21:00,ebb,-1.25 | |
4/1/17 23:36,slack,0`) | |
.map(d => { | |
d.time = +parset(d.Date_Time); | |
d.speed = +d.Speed; | |
return d; | |
}); | |
var x = d3.scaleLinear() | |
.domain(d3.extent(data.map(d => d.time))) | |
.range([0,width]); | |
var y = d3.scaleLinear() | |
.domain(d3.extent(data.map(d => d.speed))) | |
.range([height,0]); | |
function inter(t){ | |
var prev = d3.bisectLeft(data.map(d => d.time), t)-1, | |
r = 0; | |
if (!data[prev]) return 0; | |
var alpha = (t - data[prev].time) / (data[prev+1].time - data[prev].time); | |
if (data[prev].Event == 'slack') | |
alpha = 1 - (1 - alpha) * (1 - alpha); | |
else | |
alpha = alpha * alpha; | |
r = d3.interpolateNumber(data[prev].speed, data[prev+1].speed)(alpha); | |
return r; | |
} | |
var line = d3.line().x(x).y(u => y(inter(u))); | |
svg.append('path') | |
.attr('fill', 'none') | |
.attr('stroke', 'lightblue') | |
.attr('d', line(d3.range( | |
...x.domain(), | |
(x.domain()[1] - x.domain()[0]) / steps | |
))) | |
svg.selectAll('circle') | |
.data(data) | |
.enter() | |
.append('circle') | |
.attr('r', 4) | |
.attr('cx', d => x(d.time)) | |
.attr('cy', d => y(d.speed)) | |
</script> | |
</body> |