Published
Edited
May 15, 2019
Insert cell
Insert cell
map = html`<div class='map'><svg></svg></div>`
Insert cell
height = 500 * width / 960;
Insert cell
{
var pi = Math.PI,
tau = 2 * pi;

// Initialize the projection to fit the world in a 1×1 square centered at the origin.
var projection = d3.geoMercator()
.scale(1 / tau)
.translate([0, 0]);

var path = d3.geoPath()
.projection(projection);

var tile = d3.tile()
.size([width, height]);
var zoom = d3.zoom()
.scaleExtent([1 << 11, 1 << 14])
.on("zoom", zoomed);

var svg = d3.select(map).select("svg")
.attr("width", width)
.attr("height", height);

// Compute the projected initial center.
var center = projection([-98.5, 39.5]);
var raster = svg.append("g");
// Apply a zoom transform equivalent to projection.{scale,translate,center}.
svg
.call(zoom)
.call(zoom.transform, d3.zoomIdentity
.translate(width / 2, height / 2)
.scale(1 << 12)
.translate(-center[0], -center[1]));
function zoomed() {
var transform = d3.event.transform;

var tiles = tile
.scale(transform.k)
.translate([transform.x, transform.y])
();

projection
.scale(transform.k / tau)
.translate([transform.x, transform.y]);

var image = raster
.attr("transform", stringify(tiles.scale, tiles.translate))
.selectAll("image")
.data(tiles, function(d) { return d; });

image.exit().remove();

image.enter().append("image")
.attr("xlink:href", function(d) { return "https://stamen-tiles-" + "abc"[d[1] % 3] + ".a.ssl.fastly.net/terrain/" + d[2] + "/" + d[0] + "/" + d[1] + (devicePixelRatio > 1 ? "@2x" : "") + ".png"; })
.attr("x", function(d) { return d[0] * 256; })
.attr("y", function(d) { return d[1] * 256; })
.attr("width", 256)
.attr("height", 256);
}

function stringify(scale, translate) {
var k = scale / 256, r = scale % 1 ? Number : Math.round;
return "translate(" + r(translate[0] * scale) + "," + r(translate[1] * scale) + ") scale(" + k + ")";
}
}
Insert cell
html`
<style>

body {
margin: 0;
}

.map {
position: relative;
overflow: hidden;
}

.layer {
position: absolute;
}

.tile {
pointer-events: none;
position: absolute;
width: 256px;
height: 256px;
}

.info {
position: absolute;
bottom: 10px;
left: 10px;
}

</style>`
Insert cell
d3 = require("d3@5", "d3-geo@1", "d3-tile@0.0.3")
Insert cell
d3.zoom
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