A demo of d3-tile when projecting to fit a bounding box.
Tiles copyright OpenStreetMap contributors.
forked from mbostock's block: Tile by Bounding Box (wrap update)
A demo of d3-tile when projecting to fit a bounding box.
Tiles copyright OpenStreetMap contributors.
forked from mbostock's block: Tile by Bounding Box (wrap update)
| // https://d3js.org/d3-tile/ Version 0.0.3. Copyright 2016 Mike Bostock. | |
| (function (global, factory) { | |
| typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array')) : | |
| typeof define === 'function' && define.amd ? define(['exports', 'd3-array'], factory) : | |
| (factory((global.d3 = global.d3 || {}),global.d3)); | |
| }(this, function (exports,d3Array) { 'use strict'; | |
| function tile() { | |
| var x0 = 0, | |
| y0 = 0, | |
| x1 = 960, | |
| y1 = 500, | |
| tx = (x0 + x1) / 2, | |
| ty = (y0 + y1) / 2, | |
| scale = 256, | |
| zoomDelta = 0, | |
| wrap = true; | |
| function tile() { | |
| var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0), | |
| z0 = Math.round(z + zoomDelta), | |
| j = 1 << z0, | |
| k = Math.pow(2, z - z0 + 8), | |
| x = tx - scale / 2, | |
| y = ty - scale / 2, | |
| tiles = [], | |
| cols = d3Array.range( | |
| Math.max(wrap ? -Infinity : 0, Math.floor((x0 - x) / k)), | |
| Math.min(Math.ceil((x1 - x) / k), wrap ? Infinity : j) | |
| ), | |
| rows = d3Array.range( | |
| Math.max(0, Math.floor((y0 - y) / k)), | |
| Math.min(Math.ceil((y1 - y) / k), j) | |
| ); | |
| rows.forEach(function(y) { | |
| cols.forEach(function(x) { | |
| var d = [(x % j + j) % j, y, z0]; | |
| d.x = x * 256; | |
| d.y = y * 256; | |
| tiles.push(d); | |
| }); | |
| }); | |
| tiles.translate = [x / k, y / k]; | |
| tiles.scale = k; | |
| return tiles; | |
| } | |
| tile.size = function(_) { | |
| return arguments.length ? (x0 = y0 = 0, x1 = +_[0], y1 = +_[1], tile) : [x1, y1]; | |
| }; | |
| tile.extent = function(_) { | |
| return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], tile) : [[x0, y0], [x1, y1]]; | |
| }; | |
| tile.scale = function(_) { | |
| return arguments.length ? (scale = +_, tile) : scale; | |
| }; | |
| tile.translate = function(_) { | |
| return arguments.length ? (tx = +_[0], ty = +_[1], tile) : [tx, ty]; | |
| }; | |
| tile.zoomDelta = function(_) { | |
| return arguments.length ? (zoomDelta = +_, tile) : zoomDelta; | |
| }; | |
| tile.wrap = function(_) { | |
| return arguments.length ? (wrap = _, tile) : wrap; | |
| }; | |
| return tile; | |
| } | |
| exports.tile = tile; | |
| Object.defineProperty(exports, '__esModule', { value: true }); | |
| })); |
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| svg, | |
| #tiles { | |
| position: absolute; | |
| width: 960px; | |
| height: 600px; | |
| overflow: hidden; | |
| } | |
| </style> | |
| <div id="tiles"></div> | |
| <svg width="960" height="600"></svg> | |
| <script src="//d3js.org/d3.v4.0.0-alpha.50.min.js"></script> | |
| <script src="d3-tile.js"></script> | |
| <script src="//d3js.org/topojson.v1.min.js"></script> | |
| <script> | |
| var pi = Math.PI, | |
| tau = 2 * pi; | |
| var svg = d3.select("svg"), | |
| width = +svg.attr("width"), | |
| height = +svg.attr("height"); | |
| // 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]); | |
| // Compute the projected bounding box given a geographic bounding box (here, California). | |
| // This assumes parallels are horizontal and meridians are vertical… | |
| // but you could use path.bounds to handle arbitrary shapes. | |
| // Note that the y-dimension is flipped relative to latitude! | |
| var bounds = [[-124.408585, 32.534291], [-114.138271, 42.007768]], | |
| p0 = projection([bounds[0][0], bounds[1][1]]), | |
| p1 = projection([bounds[1][0], bounds[0][1]]); | |
| // Convert this to a scale k and translate tx, ty for the projection. | |
| // For crisp image tiles, clamp to the nearest power of two. | |
| var k = floor(0.95 / Math.max((p1[0] - p0[0]) / width, (p1[1] - p0[1]) / height)), | |
| tx = (width - k * (p1[0] + p0[0])) / 2, | |
| ty = (height - k * (p1[1] + p0[1])) / 2; | |
| projection | |
| .scale(k / tau) | |
| .translate([tx, ty]); | |
| // Lastly convert this to the corresponding tile.scale and tile.translate; | |
| // see http://bl.ocks.org/mbostock/4150951 for a related example. | |
| var tiles = d3.tile() | |
| .size([width, height]) | |
| .scale(k) | |
| .translate([tx, ty]) | |
| (); | |
| d3.select("#tiles") | |
| .selectAll("img").data(tiles).enter().append("img") | |
| .style("position", "absolute") | |
| .attr("src", function(d, i) { return "http://" + "abc"[d[1] % 3] + ".tile.openstreetmap.org/" + d[2] + "/" + d[0] + "/" + d[1] + ".png"; }) | |
| .style("left", function(d) { return (d.x / tiles.scale + tiles.translate[0]) * tiles.scale + "px"; }) | |
| .style("top", function(d) { return (d.y / tiles.scale + tiles.translate[1]) * tiles.scale + "px"; }) | |
| .attr("width", tiles.scale) | |
| .attr("height", tiles.scale); | |
| d3.json("https://gist.githubusercontent.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/us.json", function(error, us) { | |
| if (error) throw error; | |
| svg.append("path") | |
| .datum(topojson.mesh(us, us.objects.states)) | |
| .attr("d", d3.geoPath().projection(projection)) | |
| .attr("fill", "none") | |
| .attr("stroke", "#000"); | |
| }); | |
| function floor(k) { | |
| return Math.pow(2, Math.floor(Math.log(k) / Math.LN2)); | |
| } | |
| </script> |
| �PNG | |