Public
Edited
Feb 27, 2021
6 forks
188 stars
Insert cell
Insert cell
chart = memChart(year)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dcCensusBlockGroupsUrl = FileAttachment('dc-census.ndjson').url()
Insert cell
Insert cell
Insert cell
getNdjsonStream = async url => {
const { body } = await fetch(url);
const reader = ndjsonStream(body).getReader();
return reader;
}
Insert cell
Insert cell
Insert cell
borders = FileAttachment('dc-borders-topo.json').json()
Insert cell
Insert cell
getProjection = ({ rotate, center, parallels, transverseMercator } = {}) => {
let _projection = transverseMercator
? d3.geoTransverseMercator()
: d3.geoConicConformal().parallels(parallels);

return _projection.rotate(rotate).center(center);
}
Insert cell
projection = {
const { width, height } = dimensions;
const marylandStatePlane = {
rotate: [77, 0],
center: [0, 37.66],
parallels: [38.3, 39.45]
};

return getProjection(marylandStatePlane).fitSize(
[width, height],
topojson.feature(borders, borders.objects['dc-borders'])
);
}
Insert cell
Insert cell
generateDensity = (feature, ethnicity_column, year, context) => {
if (feature === undefined || feature === null) return;

const { properties } = feature;
const bounds = geopath.bounds(feature);
const populationData = Math.round(
properties[`${ethnicity_column}${censusYearMap[year]}`] / peoplePerPoint
);

if (!populationData) return;

// https://github.com/d3/d3-geo#path_bounds
const x_min = bounds[0][0];
const x_max = bounds[1][0];
const y_min = bounds[0][1];
const y_max = bounds[1][1];

let hits = 0;
let count = 0;

const limit = populationData * 10; // limit test to 10x the population.

let points = [];
while (hits < populationData - 1 && count < limit) {
const lat = y_min + Math.random() * (y_max - y_min);
const lng = x_min + Math.random() * (x_max - x_min);

const randomPoint = turf.point([lng, lat], {
color: colorScheme[ethnicity_column]
});

if (turf.booleanPointInPolygon(randomPoint, feature)) {
points.push(randomPoint);
hits++;
}

count++;
}

return turf.featureCollection(points);
}
Insert cell
Insert cell
drawDensity = ({ features }, context) => {
for (const feature of features) {
const {
properties: { color }
} = feature;

const {
geometry: {
coordinates: [x, y]
}
} = feature;

context.fillStyle = color;
context.fillRect(x, y, 1, 1);
}

return context;
}
Insert cell
Insert cell
drawBorder = (topojsonCollection, context) => {
geopath.context(context)(
d3.geoProject(topojson.mesh(topojsonCollection), projection)
);
context.globalAlpha = 1;
context.strokeStyle = strokeColor;
context.stroke();

return context;
}
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

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