Published
Edited
Nov 2, 2021
1 star
Insert cell
Insert cell
viewof position = html`<div id='mouse-position'>`
Insert cell
target = html`<div style="height:${width/2}px">`;
Insert cell
Insert cell
features = counties
Insert cell
Insert cell
info = html`<div></div>`
Insert cell
function canvasFunction(extent, resolution, pixelRatio, size, projection) {
var canvasWidth = size[0];
var canvasHeight = size[1];

var canvas = d3.select(document.createElement('canvas'));
canvas.attr('width', canvasWidth).attr('height', canvasHeight);

var context = canvas.node().getContext('2d');
// Trial projection with unit scale is used to compute bounding box
var d3Projection = d3.geoMercator().scale(1).translate([0, 0]);
var d3Path = d3.geoPath().projection(d3Projection);

// Compute the projected planar bounding box (typically in pixels) for the specified GeoJSON object.
var pixelBounds = d3Path.bounds(features);
var pixelBoundsWidth = pixelBounds[1][0] - pixelBounds[0][0];
var pixelBoundsHeight = pixelBounds[1][1] - pixelBounds[0][1];

// Compute spherical bounding box: [lowerLeft, upperRight]
var geoBounds = d3.geoBounds(features);
// Compute the OpenLayers-projected bounding box from spherical bounding box
var geoBoundsLeftBottom = ol.proj.fromLonLat(geoBounds[0], projection);
var geoBoundsRightTop = ol.proj.fromLonLat(geoBounds[1], projection);
var geoBoundsWidth = geoBoundsRightTop[0] - geoBoundsLeftBottom[0];
if (geoBoundsWidth < 0) {
geoBoundsWidth += ol.extent.getWidth(projection.getExtent());
}
var geoBoundsHeight = geoBoundsRightTop[1] - geoBoundsLeftBottom[1];

var widthResolution = geoBoundsWidth / pixelBoundsWidth;
var heightResolution = geoBoundsHeight / pixelBoundsHeight;
var r = Math.max(widthResolution, heightResolution);
var scale = r / (resolution / pixelRatio);
// Print some diagnostics to a cell
let f = d3.format("\ ,d");
info.innerHTML = "Left bottom: " + geoBoundsLeftBottom.map(f) +
"<br>Right top: " + geoBoundsRightTop.map(f) +
"<br>widthResolution, heightResolution: " + widthResolution + ", " + heightResolution;

var center = ol.proj.toLonLat(ol.extent.getCenter(extent), projection);
d3Projection.scale(scale).center(center)
.translate([canvasWidth / 2, canvasHeight / 2]);
d3Path = d3Path.projection(d3Projection).context(context);

context.beginPath();
d3Path(topojson.mesh(topo, topo.objects.counties, (a, b) => a !== b && (a.id / 1000 | 0) === (b.id / 1000 | 0)));
// context.lineWidth = 0.5 / scale;
context.lineWidth = 1;
context.strokeStyle = "#aaa";
context.stroke();
context.beginPath();
d3Path(topojson.mesh(topo, topo.objects.states, (a, b) => a !== b));
// context.lineWidth = 0.5 / scale;
context.strokeStyle = "#555";
context.stroke();
context.beginPath();
d3Path(topojson.feature(topo, topo.objects.nation));
// context.lineWidth = 1 / scale;
context.strokeStyle = "#000";
context.stroke();
return canvas.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
topo = d3.json("https://pbogden.github.io/mapping/data/topojson/us-10m.json")
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