scatter = {
const container = html`<div id="scatter-container"></div>`;
yield container;
const data = philosophers.map(d => ({
birthYear: +new Date(d.lifespan[0], 0, 1),
year: d.lifespan[1] - d.lifespan[0],
name: d.name
}));
const w = 600;
const h = 300;
const m = 50;
const canvas = new G.Canvas({
container,
width: w + m * 2,
height: h + m * 2
});
const [minBirth, maxBirth] = extent(data, d => d.birthYear);
const [minYear, maxYear] = extent(data, d => d.year);
for (const { birthYear, year } of data) {
const x = m + ((birthYear - minBirth) / (maxBirth - minBirth)) * w;
const y = m + ((year - minYear) / (maxYear - minYear)) * h;
canvas.addShape('circle', {
attrs: {
x: x,
y: h + m * 2 - y,
r: 5,
fill: '#5B8FF9'
}
});
}
const xTicks = ticksByInterval(
year(yearCeil(minBirth, 200)),
year(yearFloor(maxBirth, 200)),
200
).map(d => +DateYear(d));
for (const tick of xTicks) {
const x = m + ((tick - minBirth) / (maxBirth - minBirth)) * w;
const y = h + m * 2 - 30;
canvas.addShape('line', {
attrs: {
x1: x,
x2: x,
y1: y - 5,
y2: y,
stroke: 'black'
}
});
canvas.addShape('text', {
attrs: {
text: `${year(tick)}`,
x: x,
y: y + 3,
stroke: 'black',
textAlign: 'center',
textBaseline: 'top',
fontSize: 10,
fontWeight: 'lighter'
}
});
}
const yTicks = ticksByInterval(
Math.ceil(minYear / 10) * 10,
Math.floor(maxYear / 10) * 10,
10
);
for (const tick of yTicks) {
const x = m - 15;
const y = h + m * 2 - (m + ((tick - minYear) / (maxYear - minYear)) * h);
canvas.addShape('line', {
attrs: {
x1: x - 5,
x2: x,
y1: y,
y2: y,
stroke: 'black'
}
});
canvas.addShape('text', {
attrs: {
text: tick,
x: x - 15,
y,
stroke: 'black',
textAlign: 'right',
textBaseline: 'middle',
fontSize: 10,
fontWeight: 'lighter'
}
});
}
function ticksByInterval(start, end, interval) {
const size = (((end - start) / interval) | 0) + 1;
return new Array(size).fill(0).map((_, i) => start + i * interval);
}
function yearCeil(timestamp, count) {
const y1 = year(timestamp);
const y2 = Math.ceil(y1 / count) * count;
return +DateYear(y2);
}
function yearFloor(timestamp, count) {
const y1 = year(timestamp);
const y2 = Math.floor(y1 / count) * count;
return +DateYear(y2);
}
function year(timestamp) {
return new Date(timestamp).getFullYear();
}
function DateYear(year) {
if (0 <= year && year < 100) {
const date = new Date(-1, 0, 1);
date.setFullYear(year);
return date;
}
return new Date(year, 0, 1);
}
}