Published
Edited
Aug 11, 2019
2 forks
26 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function map(width, height) {
// Is there a way to do this that's not processing intensive?
// Have we already calculated everything to do this elsewhere? I'm not sure.
// Let me know if you know!
projection.fitSize([width, height], data);

const svg = d3
.create('svg')
.attr('viewBox', [0, 0, width, height])
.attr('width', width)
.attr('height', height)
.style('border', '1px dotted rgba(0, 0, 0, 50%)');

const g = svg.append('g');

g.selectAll('path')
.data(data.features ? data.features : [data]) // just in case someone passes a single Feature
.join('path')
.attr('fill', '#ccc')
.attr('stroke', '#eee')
.attr('d', path);

return svg.node();
}
Insert cell
Insert cell
Insert cell
stateplanes = {
const results = await d3.json('https://cdn.jsdelivr.net/gh/veltman/d3-stateplane/stateplane.json');
return results.filter(
({ EPSG }) => EPSG !== '26931' // we don't want Alaska Zone 1, it needs Oblique Mercator
);
}
Insert cell
Insert cell
projections = new Map([
['TM', d3.geoTransverseMercator],
['L', d3.geoConicConformal],
])
Insert cell
Insert cell
stateplane = stateplanes.find(d => d.EPSG === epsg)
Insert cell
Insert cell
projection = {
const { Projection: code, parallels, origin } = stateplane;

const projection = projections.get(code)();

if (parallels) {
projection.parallels(parallels.map(([p1, p2]) => p1 + p2 / 60));
}

if (origin) {
let rotation;

switch (code) {
case "L":
const [r1, r2] = origin[0];
rotation = [r1 + r2 / 60, 0];
break;
case "TM":
rotation = origin.map(([r1, r2], idx) =>
idx === 0 ? r1 + r2 / 60 : -r1 - r2 / 60
);
break;
default:
throw Error(`"${code}" is not a valid projection identifier.`);
}

projection.rotate(rotation);
}

return projection;
}
Insert cell
Insert cell
path = d3.geoPath(projection)
Insert cell
Insert cell
data = d3.json(customGeoJSONPath || defaultGeoJSONPath)
Insert cell
Insert cell
mapWidth = Math.min(userWidth, width)
Insert cell
heightRatio = {
const bounds = path.bounds(data);
return (bounds[1][1] - bounds[0][1]) / (bounds[1][0] - bounds[0][0]);
}
Insert cell
mapHeight = Math.floor(mapWidth * heightRatio)
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