Published
Edited
Dec 14, 2020
Insert cell
Insert cell
canvas = {
d3.select('body').selectAll('div#canvas').remove();
const div = d3.select('body').append('div').attr('id', 'canvas');
const mapContext = DOM.context2d(width, height);
const origT = projection.translate();
const origS = projection.scale();
const timeLineContext = DOM.context2d(width, height);
div.append(() => mapContext.canvas)
.style('position', 'relative');
div.append(() => timeLineContext.canvas)
.style('position', 'absolute')
.style('left', 0)
.style('top', 0);
const voronoiG = div.append('svg')
.style('width', width)
.style('height', height)
.style('position', 'absolute')
.style('left', 0)
.style('top', 0)
.append('g')
.style('fill', 'none')
.style('stroke', 'red');
function renderMap() {
mapContext.clearRect(0, 0, width, height);
drawMap(mapContext);
drawTriangles(mapContext);
voronoiG.call(makeVoronoi);
}
function renderTimeLine() {
timeLineContext.clearRect(0, 0, width, height);
drawTimeAxis(timeLineContext);
drawDistribution(timeLineContext);
}
function render() {
renderMap();
renderTimeLine();
}
function zoomed(){
const newScale = d3.event.transform.k;
const newTranslate = [newScale*origT[0] + d3.event.transform.x, newScale*origT[1] + d3.event.transform.y];
projection.scale(origS*newScale)
.translate(newTranslate);
renderMap();
}
const zoom = d3.zoom()
.translateExtent([[0,0],[width, height]])
.scaleExtent([1, 90])
.on("zoom", zoomed);
div.style('background', 'aliceblue')
.call(zoom)
.call(render)
;
return html`${div.node()}`;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
memberTimestamps = nonNullMembers.map(m => new Date(m.date_with_hour + ':00'));
Insert cell
Insert cell
Insert cell
Insert cell
membersByLocation = d3.group(nonNullMembers, m => longLatToString([m.long, m.lat]));
Insert cell
membersByHour = d3.group(nonNullMembers, m => m.date_with_hour);
Insert cell
nonNullMembers = membersRaw.filter(d=> d.lat);
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
projection = d3.geoFahey()//d3.geoNaturalEarth1().rotate([-10,0])
Insert cell
land = topojson.feature(world, world.objects.land)
Insert cell
world = fetch("https://cdn.jsdelivr.net/npm/world-atlas@1/world/50m.json").then(response => response.json())
Insert cell
topojson = require("topojson-client@3")
Insert cell
d3 = require("d3-zoom", "d3-selection", "d3-fetch", "d3-geo@1", "d3-geo-projection@2", "d3-scale", "d3-shape", "d3-array", "d3-time", "d3-time-format", "d3-geo-voronoi")
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