Published
Edited
Dec 5, 2020
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
map = {
const canvas = d3
.create("canvas")
.attr("width", mapWidth)
.attr("height", mapHeight)
.node();
canvas.width = mapWidth;
canvas.height = mapHeight;
let ctx = canvas.getContext("2d");
scaleCanvas(canvas, ctx);
ctx.fillStyle = "rgba(5,5,5,1)";
ctx.fillRect(0, 0, mapWidth, mapHeight);
// let path = d3.geoPath(projection, ctx)
/*
ctx.save();
ctx.beginPath(),
path(land),
(ctx.strokeStyle = "rgba(255, 255, 255, 0.2 )"),
ctx.stroke();
ctx.restore();
*/
// DRAW TICK
draw(ctx);
// svg.append("g").attr("transform", "translate(${height},20)");
// .append(() => legend({ ramp, title: data.title, width: 260 }));

return canvas;
}
Insert cell
function draw(ctx) {
let path = d3.geoPath(projection, ctx);
circles.forEach(d => {
// if (d.longitude > lngFilter * 2 - 160) return false;
if (!d.longitude || !d.latitude || !d) return false;
const loc = projection([d.longitude, d.latitude]);
if (!loc) return null;
const [x, y] = loc;
// const x = width / 2;
// const y = height / 2;

// let r = 2.5 * (sliceFilter * 0.01);
// if (r < 1) r = 1;
let r = d.frames(tick) * 2;
let fill = d.colorFrames(tick);

ctx.save();
ctx.beginPath(),
path(hexGeoJSON),
(ctx.strokeStyle = "rgba(255, 255, 255, 1 )"),
ctx.stroke();
ctx.restore();

// ctx.fillStyle = "rgba(225, 225, 225, 1)";
ctx.fillStyle = weightColor(1 - fill);
//ctx.strokeStyle = "rgba(225, 225, 225, 0.15)";
ctx.lineWidth = 1;
// ctx.fillRect(x, y, 2, 2);
ctx.beginPath();
// ctx.arc(x, y, 2, 0, 2 * Math.PI);
// ctx.stroke();
ctx.arc(x, y, r, 0, 2 * Math.PI);
ctx.fill();
});
}
Insert cell
hexagons = {
const hexes = {};
circles.forEach(d => {
const hexID = h3.geoToH3(d.latitude, d.longitude);
if (!hexes[hexID]) hexes[hexID] = [];
// hexes[hexID].push(d);
// hexes.push(d);
});
return hexes;
}
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
//hexGeoJSON = h3.h3SetToMultiPolygon(Object.keys(hexagons), true)
Insert cell
hexIDs = Object.keys(hexagons)
Insert cell
hexGeoJSON = geojson2h3.h3SetToMultiPolygonFeature(hexIDs)
Insert cell
circles = slicedMonthlyData
.sort((a, b) => {
//return +a.longitude - +b.latitude;
return +b['30DayActiveHH'] - +a['30DayActiveHH'];
})
.map((c, i) => {
// Add for each one, some condition where we're gonna say like
// where in the life cycle this circle is
// where in the animation does this circle kick in

let start = Math.round(
(i * (ticks.length - 50)) / slicedMonthlyData.length
);
return {
...c,
// frames: generateSimple(Math.round(i * 0.01), {
// startVal: 0
// })
frames: keyframe([
[0, 0],
[start, 0],
[start + 10, 1],
[start + 50, 0.3],
[240, 0.3]
]),
colorFrames: keyframe([
[0, 0.25],
[start, 0.5],
[start + 10, 1],
[start + 50, 0.5],
[240, 0.5]
])
};
})
Insert cell
projection = d3
// .geoAlbersUsa()
// .geoMiller()
.geoEquirectangular()
// .geoInterruptedMollweideHemispheres()
// .geoVanDerGrinten2()
//.translate([width / 2, height / 2])
// .scale([width * 0.2])
.fitWidth(mapWidth * 0.98, land)
.translate([mapWidth / 2, mapHeight / 2])
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function normalizeLayer(layer, baseAtZero = false) {
const hexagons = Object.keys(layer);
// Pass one, get max
const max = hexagons.reduce(
(max, hex) => Math.max(max, layer[hex]),
-Infinity
);
const min = baseAtZero
? hexagons.reduce((min, hex) => Math.min(min, layer[hex]), Infinity)
: 0;
// Pass two, normalize
hexagons.forEach(hex => {
layer[hex] = (layer[hex] - min) / (max - min);
});
return layer;
}
Insert cell
drawKeyframes(circles[2400].frames.frames)
Insert cell
html`<div>
${chance
.shuffle(circles)
.slice(0, 25)
.map(d => {
return drawKeyframes(d.frames.frames);
})}
</div>
`
Insert cell
circles[1]
Insert cell
Insert cell
Insert cell
Insert cell
//weightColor = d3.scaleSequential(d3.interpolateGreys)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
mapHeight = 2048 / 4
Insert cell
mapWidth = 4096 / 4
Insert cell
Insert cell
Insert cell
Insert cell
h3 = require('https://bundle.run/h3-js@3.1.0')
Insert cell
geojson2h3 = require('https://bundle.run/geojson2h3@1.0.1')
Insert cell
Insert cell
Insert cell
Chance = require('chance')
Insert cell
chance = new Chance('hi')
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