Published
Edited
Mar 28, 2018
2 forks
1 star
Insert cell
Insert cell
vis = {
const div = DOM.element('div');
const svg = DOM.svg(width, height);
const canvas = DOM.canvas(width, height);
canvas.style.position = 'absolute';
canvas.style.top = '0px';
canvas.style.left = '10px';
div.appendChild(svg);
div.appendChild(canvas);
return div;
}
Insert cell
anim = {
const ctx = d3.select(vis).select('canvas').node().getContext('2d');
// canvas.st({ position: 'absolute', top: 0 });
ctx.clearRect(0,0,width,height);
dots.forEach(d => {
if (cnt > d.start && cnt < d.end) {
ctx.beginPath();
ctx.fillStyle = d.race == 'white' ? 'teal' : 'orange';
const cur_l_f = d3.easeQuadInOut((cnt - d.start)/(d.end-d.start)) * d.pal.length;
const cur_l_i = Math.floor(cur_l_f);
// use pt from cache
const last_pt = d.pal.ptAtLen[cur_l_i];
const next_pt = d.pal.ptAtLen[cur_l_i+1] || last_pt;
const t = cur_l_f - cur_l_i; // < a value between 0 and 1
// linear interpolation!!!
const cur_pt = {
x: last_pt.x + (next_pt.x - last_pt.x) * t,
y: last_pt.y + (next_pt.y - last_pt.y) * t
};
if (cur_pt) {
ctx.arc(cur_pt.x, cur_pt.y + d.offset, 3, 0,2*Math.PI);
}
ctx.fill();
}
});
return cnt/max_cnt;
}
Insert cell
cnt = {
let i = 0;
while (true) yield Promises.delay(1000/33, i = (i+1)% max_cnt);
}
Insert cell
max_cnt = 500
Insert cell
dots = d3.range(num_dots).map(i => {
const curve = curves[i%curves.length];
return {
i, curve,
offset: ((Math.random() - 0.5) * (y0.bandwidth()- 5)),
start: Math.floor(Math.random() * max_cnt * 0.35),
end: max_cnt - Math.floor(Math.random() * max_cnt * 0.3),
pal: cache[curve.key],
race: Math.random() < 0.5 ? 'white' : 'black'
};
})
Insert cell
num_dots = 5000
Insert cell
svg = {
const svg = d3.select(vis).select('svg').html('');
svg.appendMany('path', curves)
.attr('d', path)
.st({stroke: 'gray', fill: 'none', strokeWidth: y0.bandwidth(), opacity: 0.1 });
return DOM.text('');
}
Insert cell
cache = {
const cache = {};
const s = svg;
d3.select(vis).select('svg').selectAll('path').each(function(d) {
const k = `${d.x1}-${d.x2}`;
const path = this;
const length = path.getTotalLength();
const ptAtLen = [];
d3.range(length).forEach(l => {
const pt = path.getPointAtLength(l);
ptAtLen[l] = {x:pt.x,y:pt.y};
});
cache[k] = {path, length, ptAtLen};
});
return cache;
}
Insert cell
Insert cell
Insert cell
Insert cell
height = 500
Insert cell
Insert cell
Insert cell
Insert cell
y0 = d3.scaleBand().domain(domain).range([0,height]).padding(0.2)
Insert cell
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