Public
Edited
Jun 9, 2024
Paused
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
padding = 50
Insert cell
wave = svg`<svg viewBox="0 0 ${segments.reduce((a, b) => a + b)} 100">
<path id="wave" fill="none" stroke="currentColor" stroke-linecap="butt" stroke-linejoin="bevel" stroke-width="1" stroke-dasharray="1" stroke-dashoffset="1" pathLength="1" />
<animate xlink:href="#wave" attributeName="d" dur="150ms" repeatCount="indefinite" from="M ${origin} L ${path(
from
).join(" ")}" to="M ${origin} L ${path(to).join(" ")}" />
<style>
path[id="wave"] {
animation: dash ${segments.length}s steps(${
path(from).length
}, jump-none) alternate infinite;
}

@keyframes dash {
to {
stroke-dashoffset: 0;
}
}
</style>
</svg>`
Insert cell
path = (d) => {
let points = [];
for (let i = 0, push = Array.prototype.push; i < segments.length; i++) {
push.apply(
points,
d.map((p) => ({ x: p.x + segments[i], y: p.y }))
);
}
return points.map(pair);
}
Insert cell
segments = Array.from({ length: 3 }, (_, i) => i * tail.x)
Insert cell
to = [
{ x: 18, y: 10 },
{ x: 52, y: 80 },
{ x: 65, y: 20 },
{ x: 65, y: 70 },
{ x: 80, y: 90 },
{ x: 90, y: 30 },
{ x: 100, y: 40 },
{ x: 110, y: 75 },
{ x: 120, y: 30 },
{ x: 130, y: 80 },
{ x: 140, y: 10 },
tail
]
Insert cell
from = [
{ x: 20, y: 60 },
{ x: 50, y: 0 },
{ x: 60, y: 100 },
{ x: 70, y: 40 },
{ x: 80, y: 90 },
{ x: 90, y: 10 },
{ x: 100, y: 40 },
{ x: 110, y: 30 },
{ x: 120, y: 80 },
{ x: 130, y: 50 },
{ x: 140, y: 80 },
tail
]
Insert cell
origin = pair({ x: 0, y: 50 })
Insert cell
pair = ({ x, y }) => [x, y].join(",")
Insert cell
tail = ({ x: 150, y: 50 })
Insert cell
height = Math.min(Math.floor(width / 2), 480)
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