diff --git a/data/core.yaml b/data/core.yaml index e769580d76..491e05cc52 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -753,7 +753,7 @@ en: custom_background: tooltip: Edit custom background header: Custom Background Settings - instructions: "Enter a tile URL template. Valid tokens are:\n {zoom} or {z}, {x}, {y} for Z/X/Y tile scheme\n {-y} or {ty} for flipped TMS-style Y coordinates\n {u} for quadtile scheme\n {switch:a,b,c} for DNS server multiplexing\n\nExample:\n{example}" + instructions: "Enter a tile URL template below.\n\nSupported WMS tokens:\n `{proj}`: requested projection (`EPSG:3857` only)\n `{wkid}`: same as proj, but without the EPSG (`3857` only)\n `{width}`, `{height}`: requested image dimensions (`256` only)\n `{bbox}`: requested bounding box (e.g. `minX,minY,maxX,maxY`)\n\nSupported TMS tokens:\n `{zoom}` or `{z}, `{x}`, `{y}`: Z/X/Y tile coordinates\n `{-y}` or `{ty}`: flipped TMS-style Y coordinates\n `{switch:a,b,c}`: DNS server multiplexing\n `{u}`: quadtile (Bing) scheme\n\nExample:\n{example}" template: placeholder: Enter a url template custom_data: diff --git a/dist/locales/en.json b/dist/locales/en.json index 2efd8074a5..302e164029 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -952,7 +952,7 @@ "custom_background": { "tooltip": "Edit custom background", "header": "Custom Background Settings", - "instructions": "Enter a tile URL template. Valid tokens are:\n {zoom} or {z}, {x}, {y} for Z/X/Y tile scheme\n {-y} or {ty} for flipped TMS-style Y coordinates\n {u} for quadtile scheme\n {switch:a,b,c} for DNS server multiplexing\n\nExample:\n{example}", + "instructions": "Enter a tile URL template below.\n\nSupported WMS tokens:\n `{proj}`: requested projection (`EPSG:3857` only)\n `{wkid}`: same as proj, but without the EPSG (`3857` only)\n `{width}`, `{height}`: requested image dimensions (`256` only)\n `{bbox}`: requested bounding box (e.g. `minX,minY,maxX,maxY`)\n\nSupported TMS tokens:\n `{zoom}` or `{z}, `{x}`, `{y}`: Z/X/Y tile coordinates\n `{-y}` or `{ty}`: flipped TMS-style Y coordinates\n `{switch:a,b,c}`: DNS server multiplexing\n `{u}`: quadtile (Bing) scheme\n\nExample:\n{example}", "template": { "placeholder": "Enter a url template" } diff --git a/modules/renderer/background_source.js b/modules/renderer/background_source.js index 72af62029d..3b9d4950ff 100644 --- a/modules/renderer/background_source.js +++ b/modules/renderer/background_source.js @@ -29,44 +29,44 @@ function vintageRange(vintage) { export function rendererBackgroundSource(data) { var source = Object.assign({}, data); // shallow copy - var offset = [0, 0]; - var name = source.name; - var description = source.description; - var best = !!source.best; - var template = source.encrypted ? utilAesDecrypt(source.template) : source.template; + var _offset = [0, 0]; + var _name = source.name; + var _description = source.description; + var _best = !!source.best; + var _template = source.encrypted ? utilAesDecrypt(source.template) : source.template; source.tileSize = data.tileSize || 256; source.zoomExtent = data.zoomExtent || [0, 22]; source.overzoom = data.overzoom !== false; source.offset = function(val) { - if (!arguments.length) return offset; - offset = val; + if (!arguments.length) return _offset; + _offset = val; return source; }; source.nudge = function(val, zoomlevel) { - offset[0] += val[0] / Math.pow(2, zoomlevel); - offset[1] += val[1] / Math.pow(2, zoomlevel); + _offset[0] += val[0] / Math.pow(2, zoomlevel); + _offset[1] += val[1] / Math.pow(2, zoomlevel); return source; }; source.name = function() { var id_safe = source.id.replace(/\./g, ''); - return t('imagery.' + id_safe + '.name', { default: name }); + return t('imagery.' + id_safe + '.name', { default: _name }); }; source.description = function() { var id_safe = source.id.replace(/\./g, ''); - return t('imagery.' + id_safe + '.description', { default: description }); + return t('imagery.' + id_safe + '.description', { default: _description }); }; source.best = function() { - return best; + return _best; }; @@ -82,15 +82,35 @@ export function rendererBackgroundSource(data) { }; - source.template = function(_) { - if (!arguments.length) return template; - if (source.id === 'custom') template = _; + source.template = function(val) { + if (!arguments.length) return _template; + if (source.id === 'custom') { + _template = val; + } return source; }; source.url = function(coord) { - if (this.type === 'wms') { + var result = _template; + if (result === '') return result; // source 'none' + + + // Guess a type based on the tokens present in the template + // (This is for 'custom' source, where we don't know) + if (!source.type) { + if (/\{(proj|wkid|bbox)\}/.test(_template)) { + source.type = 'wms'; + source.projection = 'EPSG:3857'; // guess + } else if (/\{(x|y)\}/.test(_template)) { + source.type = 'tms'; + } else if (/\{u\}/.test(_template)) { + source.type = 'bing'; + } + } + + + if (source.type === 'wms') { var tileToProjectedCoords = (function(x, y, z) { //polyfill for IE11, PhantomJS var sinh = Math.sinh || function(x) { @@ -102,7 +122,7 @@ export function rendererBackgroundSource(data) { var lon = x / zoomSize * Math.PI * 2 - Math.PI; var lat = Math.atan(sinh(Math.PI * (1 - 2 * y / zoomSize))); - switch (this.projection) { + switch (source.projection) { case 'EPSG:4326': return { x: lon * 180 / Math.PI, @@ -115,13 +135,14 @@ export function rendererBackgroundSource(data) { y: 20037508.34 / Math.PI * mercCoords[1] }; } - }).bind(this); + }); - var tileSize = this.tileSize; - var projection = this.projection; + var tileSize = source.tileSize; + var projection = source.projection; var minXmaxY = tileToProjectedCoords(coord[0], coord[1], coord[2]); var maxXminY = tileToProjectedCoords(coord[0]+1, coord[1]+1, coord[2]); - return template.replace(/\{(\w+)\}/g, function (token, key) { + + result = result.replace(/\{(\w+)\}/g, function (token, key) { switch (key) { case 'width': case 'height': @@ -144,28 +165,38 @@ export function rendererBackgroundSource(data) { return token; } }); + + } else if (source.type === 'tms') { + result = result + .replace('{x}', coord[0]) + .replace('{y}', coord[1]) + // TMS-flipped y coordinate + .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1) + .replace(/\{z(oom)?\}/, coord[2]); + + } else if (source.type === 'bing') { + result = result + .replace('{u}', function() { + var u = ''; + for (var zoom = coord[2]; zoom > 0; zoom--) { + var b = 0; + var mask = 1 << (zoom - 1); + if ((coord[0] & mask) !== 0) b++; + if ((coord[1] & mask) !== 0) b += 2; + u += b.toString(); + } + return u; + }); } - return template - .replace('{x}', coord[0]) - .replace('{y}', coord[1]) - // TMS-flipped y coordinate - .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1) - .replace(/\{z(oom)?\}/, coord[2]) - .replace(/\{switch:([^}]+)\}/, function(s, r) { - var subdomains = r.split(','); - return subdomains[(coord[0] + coord[1]) % subdomains.length]; - }) - .replace('{u}', function() { - var u = ''; - for (var zoom = coord[2]; zoom > 0; zoom--) { - var b = 0; - var mask = 1 << (zoom - 1); - if ((coord[0] & mask) !== 0) b++; - if ((coord[1] & mask) !== 0) b += 2; - u += b.toString(); - } - return u; - }); + + // these apply to any type.. + result = result.replace(/\{switch:([^}]+)\}/, function(s, r) { + var subdomains = r.split(','); + return subdomains[(coord[0] + coord[1]) % subdomains.length]; + }); + + + return result; };