Public
Edited
Nov 23, 2022
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{// https://observablehq.com/@thetylerwolf/day-19-interpolators
const svg = d3.create('svg')
.attr('width', width * 0.8)
.attr('height', 500)

const line = d3.line()
.x(d => d.x)
.y(d => d.y);

if (curvedLine) {
line.curve(d3.curveBasis)
}

const path = svg
.append('path')
.datum( data )
.attr('d', line)
.style('stroke', '#ffb3f0')
.style('stroke-width', 2)
.style('fill', 'transparent');
while(true) {
// https://developer.mozilla.org/en-US/docs/Web/API/SVGGeometryElement/getTotalLength
const length = path.node().getTotalLength();
// https://github.com/d3/d3-interpolate
const int = d3.interpolate(0, length);
// https://developer.mozilla.org/en-US/docs/Web/API/SVGGeometryElement/getPointAtLength
const x = (t) => path.node().getPointAtLength(int(t)).x;
const y = (t) => path.node().getPointAtLength(int(t)).y;
const circle = svg.selectAll('circle')
.data([ data[0] ])
.join('circle')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.style('stroke', '#6f0043')
.style('stroke-width', 4)
.style('fill', 'transparent')
.attr('r', 8);

if (animate) {
circle.transition().delay(500).duration(points * 100)
.attrTween('cx', () => x )
.attrTween('cy', () => y );
} else {
circle
.attr('cx', data[position].x)
.attr('cy', data[position].y);
}
yield svg.node();
// https://observablehq.com/@triptych/protip-promises-tick-run-code-every-set-interval
await Promises.tick(points * 100);
}
}
Insert cell
data = d3.range(points).map(() => ({
x: Math.random() * 900,
y: Math.random() * 500
}))
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more