UNPKG

@mapbox/geo-viewport

Version:

convert between viewports and extents

74 lines (61 loc) 2.4 kB
var SphericalMercator = require('@mapbox/sphericalmercator'); // The SphericalMercator library only accepts a variable // tileSize on instantiation, which it uses to pre-cache // calculations by zoom level. // We cache each instantiation, keyed by tile size, to avoid // repeating this cost when working with a single tile size // (assumed to be the most-common use case). var smCache = {}; module.exports.viewport = viewport; module.exports.bounds = bounds; function fetchMerc(tileSize, allowAntiMeridian) { tileSize = tileSize || 256; antiMeridian = allowAntiMeridian || false; var cacheKey = tileSize + String(antiMeridian); if (!smCache[cacheKey]) { smCache[cacheKey] = new SphericalMercator({ size: tileSize, antimeridian: antiMeridian }); } return smCache[cacheKey]; } function getAdjusted(base, ratios, allowFloat) { var adjusted = Math.min( base - (Math.log(ratios[0]) / Math.log(2)), base - (Math.log(ratios[1]) / Math.log(2))); return allowFloat ? adjusted : Math.floor(adjusted); } function viewport(bounds, dimensions, minzoom, maxzoom, tileSize, allowFloat, allowAntiMeridian) { minzoom = (minzoom === undefined) ? 0 : minzoom; maxzoom = (maxzoom === undefined) ? 20 : maxzoom; var merc = fetchMerc(tileSize, allowAntiMeridian); var base = maxzoom; var bl = merc.px([bounds[0], bounds[1]], base); var tr = merc.px([bounds[2], bounds[3]], base); var width = tr[0] - bl[0]; var height = bl[1] - tr[1]; var centerPixelX = bl[0] + (width / 2); var centerPixelY = tr[1] + (height / 2); var ratios = [width / dimensions[0], height / dimensions[1]]; var adjusted = getAdjusted(base, ratios, allowFloat); var center = merc.ll([centerPixelX, centerPixelY], base); var zoom = Math.max(minzoom, Math.min(maxzoom, adjusted)); return { center, zoom }; } function bounds(viewport, zoom, dimensions, tileSize) { if (viewport.lon !== undefined) { viewport = [ viewport.lon, viewport.lat ]; } var merc = fetchMerc(tileSize); var px = merc.px(viewport, zoom); var tl = merc.ll([ px[0] - (dimensions[0] / 2), px[1] - (dimensions[1] / 2) ], zoom); var br = merc.ll([ px[0] + (dimensions[0] / 2), px[1] + (dimensions[1] / 2) ], zoom); return [tl[0], br[1], br[0], tl[1]]; }