Using d3-tile to display raster image tiles underneath a CSV dataset of point locations (U.S. state capitals), and d3-zoom for pan & zoom. See also the TopoJSON version and the static version.
Tiles copyright OpenStreetMap contributors.
license: gpl-3.0 | |
redirect: https://observablehq.com/@d3/zoomable-raster-vector |
Using d3-tile to display raster image tiles underneath a CSV dataset of point locations (U.S. state capitals), and d3-zoom for pan & zoom. See also the TopoJSON version and the static version.
Tiles copyright OpenStreetMap contributors.
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
margin: 0; | |
} | |
path { | |
fill: none; | |
stroke: red; | |
stroke-linejoin: round; | |
stroke-width: 1.5px; | |
} | |
</style> | |
<svg></svg> | |
<script src="//d3js.org/d3.v4.min.js"></script> | |
<script src="//d3js.org/d3-tile.v0.0.min.js"></script> | |
<script src="//d3js.org/topojson.v1.min.js"></script> | |
<script> | |
var pi = Math.PI, | |
tau = 2 * pi; | |
var width = Math.max(960, window.innerWidth), | |
height = Math.max(500, window.innerHeight); | |
// 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("svg") | |
.attr("width", width) | |
.attr("height", height); | |
var raster = svg.append("g"); | |
var vector = svg.append("path"); | |
d3.csv("us-state-capitals.csv", type, function(error, capitals) { | |
if (error) throw error; | |
vector | |
.datum({type: "FeatureCollection", features: capitals}); | |
// Compute the projected initial center. | |
var center = projection([-98.5, 39.5]); | |
// 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]); | |
vector | |
.attr("d", path); | |
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 "http://" + "abc"[d[1] % 3] + ".tile.openstreetmap.org/" + d[2] + "/" + d[0] + "/" + d[1] + ".png"; }) | |
.attr("x", function(d) { return d[0] * 256; }) | |
.attr("y", function(d) { return d[1] * 256; }) | |
.attr("width", 256) | |
.attr("height", 256); | |
} | |
function type(d) { | |
return { | |
type: "Feature", | |
properties: {name: d.description, state: d.name}, | |
geometry: {type: "Point", coordinates: [+d.longitude, +d.latitude]} | |
}; | |
} | |
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 + ")"; | |
} | |
</script> |
name | description | latitude | longitude | |
---|---|---|---|---|
Alabama | Montgomery | 32.377716 | -86.300568 | |
Alaska | Juneau | 58.301598 | -134.420212 | |
Arizona | Phoenix | 33.448143 | -112.096962 | |
Arkansas | Little Rock | 34.746613 | -92.288986 | |
California | Sacramento | 38.576668 | -121.493629 | |
Colorado | Denver | 39.739227 | -104.984856 | |
Connecticut | Hartford | 41.764046 | -72.682198 | |
Delaware | Dover | 39.157307 | -75.519722 | |
Hawaii | Honolulu | 21.307442 | -157.857376 | |
Florida | Tallahassee | 30.438118 | -84.281296 | |
Georgia | Atlanta | 33.749027 | -84.388229 | |
Idaho | Boise | 43.617775 | -116.199722 | |
Illinois | Springfield | 39.798363 | -89.654961 | |
Indiana | Indianapolis | 39.768623 | -86.162643 | |
Iowa | Des Moines | 41.591087 | -93.603729 | |
Kansas | Topeka | 39.048191 | -95.677956 | |
Kentucky | Frankfort | 38.186722 | -84.875374 | |
Louisiana | Baton Rouge | 30.457069 | -91.187393 | |
Maine | Augusta | 44.307167 | -69.781693 | |
Maryland | Annapolis | 38.978764 | -76.490936 | |
Massachusetts | Boston | 42.358162 | -71.063698 | |
Michigan | Lansing | 42.733635 | -84.555328 | |
Minnesota | St. Paul | 44.955097 | -93.102211 | |
Mississippi | Jackson | 32.303848 | -90.182106 | |
Missouri | Jefferson City | 38.579201 | -92.172935 | |
Montana | Helena | 46.585709 | -112.018417 | |
Nebraska | Lincoln | 40.808075 | -96.699654 | |
Nevada | Carson City | 39.163914 | -119.766121 | |
New Hampshire | Concord | 43.206898 | -71.537994 | |
New Jersey | Trenton | 40.220596 | -74.769913 | |
New Mexico | Santa Fe | 35.68224 | -105.939728 | |
North Carolina | Raleigh | 35.78043 | -78.639099 | |
North Dakota | Bismarck | 46.82085 | -100.783318 | |
New York | Albany | 42.652843 | -73.757874 | |
Ohio | Columbus | 39.961346 | -82.999069 | |
Oklahoma | Oklahoma City | 35.492207 | -97.503342 | |
Oregon | Salem | 44.938461 | -123.030403 | |
Pennsylvania | Harrisburg | 40.264378 | -76.883598 | |
Rhode Island | Providence | 41.830914 | -71.414963 | |
South Carolina | Columbia | 34.000343 | -81.033211 | |
South Dakota | Pierre | 44.367031 | -100.346405 | |
Tennessee | Nashville | 36.16581 | -86.784241 | |
Texas | Austin | 30.27467 | -97.740349 | |
Utah | Salt Lake City | 40.777477 | -111.888237 | |
Vermont | Montpelier | 44.262436 | -72.580536 | |
Virginia | Richmond | 37.538857 | -77.43364 | |
Washington | Olympia | 47.035805 | -122.905014 | |
West Virginia | Charleston | 38.336246 | -81.612328 | |
Wisconsin | Madison | 43.074684 | -89.384445 | |
Wyoming | Cheyenne | 41.140259 | -104.820236 |
the background's dead 😢