From 8d40fad82fc57046665264b35c2cf6bf818d9b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20de=20Metz?= Date: Tue, 7 Jul 2020 11:47:19 +0200 Subject: [PATCH] Release version 0.2.0. --- README.md | 34 ++++- dist/mapbox-gl-indoorequal.cjs.js | 207 +++++++++++++++++++++++--- dist/mapbox-gl-indoorequal.esm.js | 207 +++++++++++++++++++++++--- dist/mapbox-gl-indoorequal.umd.min.js | 2 +- package.json | 2 +- 5 files changed, 400 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 3946daf..36786e9 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,12 @@ map.addControl(indoorEqual); - [Parameters](#parameters-2) - [onAdd](#onadd) - [onRemove](#onremove) - - [updateLevel](#updatelevel) + - [setLevel](#setlevel) - [Parameters](#parameters-3) + - [updateLevel](#updatelevel) + - [Parameters](#parameters-4) + - [loadSprite](#loadsprite) + - [Parameters](#parameters-5) - [IndoorEqual#levelschange](#indoorequallevelschange) - [IndoorEqual#levelchange](#indoorequallevelchange) @@ -76,6 +80,7 @@ Load the indoor= source and layers in your map. - `options` **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** (optional, default `{}`) - `options.url` **[url](https://developer.mozilla.org/docs/Web/API/URL/URL)?** Override the default tiles URL (). - `options.apiKey` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** The API key if you use the default tile URL (get your free key at [indoorequal.com](https://indoorequal.com)). + - `options.layers` **[array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The layers to be used to style indoor= tiles. #### Properties @@ -112,14 +117,39 @@ Used when adding the control via the map instance: map.addControl(indoorEqual) Remove the level control Used when removing the control via the map instance: map.removeControl(indoorEqual) +#### setLevel + +Set the displayed level. + +##### Parameters + +- `level` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the level to be displayed + #### updateLevel -Update the displayed level. +Set the displayed level. ##### Parameters - `level` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the level to be displayed +**Meta** + +- **deprecated**: This is deprecated. + + +#### loadSprite + +Load a sprite and add all images to the map + +##### Parameters + +- `baseUrl` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the baseUrl where to load the sprite +- `options` **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** (optional, default `{}`) + - `options.update` **[url](https://developer.mozilla.org/docs/Web/API/URL/URL)?** Update existing image (default false) + +Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)** It resolves an hash of images. + ### IndoorEqual#levelschange Emitted when the list of available levels has been updated diff --git a/dist/mapbox-gl-indoorequal.cjs.js b/dist/mapbox-gl-indoorequal.cjs.js index 2166b0b..a57e07c 100644 --- a/dist/mapbox-gl-indoorequal.cjs.js +++ b/dist/mapbox-gl-indoorequal.cjs.js @@ -47,7 +47,7 @@ class LevelControl { if (level == this.indoorequal.level) { button.classList.add('mapboxgl-ctrl-active'); } - button.addEventListener('click', () => { this.indoorequal.updateLevel(level); }); + button.addEventListener('click', () => { this.indoorequal.setLevel(level); }); this.$el.appendChild(button); }); } @@ -96,9 +96,6 @@ const layers = [ "level" ] ], - layout: { - visibility: "visible" - }, paint: { "fill-color": "white" } @@ -117,9 +114,6 @@ const layers = [ "platform" ] ], - "layout": { - "visibility": "visible" - }, "paint": { "line-color": "#bfbfbf", "line-width": 1 @@ -137,9 +131,6 @@ const layers = [ "column" ] ], - "layout": { - "visibility": "visible" - }, "paint": { "fill-color": "#bfbfbf" } @@ -157,9 +148,6 @@ const layers = [ "wall" ] ], - "layout": { - "visibility": "visible" - }, "paint": { "line-color": "gray", "line-width": 2 @@ -172,9 +160,6 @@ const layers = [ "filter": [ "all" ], - "layout": { - "visibility": "visible", - }, "paint": { "line-color": "gray", "line-dasharray": [ @@ -273,6 +258,145 @@ const layers = [ } ]; +function createImage(image, {width, height}, channels, data) { + if (!data) { + data = new Uint8Array(width * height * channels); + } else if (data instanceof Uint8ClampedArray) { + data = new Uint8Array(data.buffer); + } else if (data.length !== width * height * channels) { + throw new RangeError('mismatched image size'); + } + image.width = width; + image.height = height; + image.data = data; + return image; +} + +function resizeImage(image, {width, height}, channels) { + if (width === image.width && height === image.height) { + return; + } + + const newImage = createImage({}, {width, height}, channels); + + copyImage(image, newImage, {x: 0, y: 0}, {x: 0, y: 0}, { + width: Math.min(image.width, width), + height: Math.min(image.height, height) + }, channels); + + image.width = width; + image.height = height; + image.data = newImage.data; +} + +function copyImage(srcImg, dstImg, srcPt, dstPt, size, channels) { + if (size.width === 0 || size.height === 0) { + return dstImg; + } + + if (size.width > srcImg.width || + size.height > srcImg.height || + srcPt.x > srcImg.width - size.width || + srcPt.y > srcImg.height - size.height) { + throw new RangeError('out of range source coordinates for image copy'); + } + + if (size.width > dstImg.width || + size.height > dstImg.height || + dstPt.x > dstImg.width - size.width || + dstPt.y > dstImg.height - size.height) { + throw new RangeError('out of range destination coordinates for image copy'); + } + + const srcData = srcImg.data; + const dstData = dstImg.data; + + for (let y = 0; y < size.height; y++) { + const srcOffset = ((srcPt.y + y) * srcImg.width + srcPt.x) * channels; + const dstOffset = ((dstPt.y + y) * dstImg.width + dstPt.x) * channels; + for (let i = 0; i < size.width * channels; i++) { + dstData[dstOffset + i] = srcData[srcOffset + i]; + } + } + return dstImg; +} + +// Not premultiplied, because ImageData is not premultiplied. +// UNPACK_PREMULTIPLY_ALPHA_WEBGL must be used when uploading to a texture. +class RGBAImage { + constructor(size, data) { + createImage(this, size, 4, data); + } + + resize(size) { + resizeImage(this, size, 4); + } + + replace(data, copy) { + if (copy) { + this.data.set(data); + } else if (data instanceof Uint8ClampedArray) { + this.data = new Uint8Array(data.buffer); + } else { + this.data = data; + } + } + + clone() { + return new RGBAImage({width: this.width, height: this.height}, new Uint8Array(this.data)); + } + + static copy(srcImg, dstImg, srcPt, dstPt, size) { + copyImage(srcImg, dstImg, srcPt, dstPt, size, 4); + } +} + +function getImageData(img, padding) { + const canvas = window.document.createElement('canvas'); + const context = canvas.getContext('2d'); + if (!context) { + throw new Error('failed to create canvas 2d context'); + } + canvas.width = img.width; + canvas.height = img.height; + context.drawImage(img, 0, 0, img.width, img.height); + return context.getImageData(0, 0, img.width, img.height); +} + +function loadSprite(baseUrl) { + const format = window.devicePixelRatio > 1 ? '@2x' : ''; + let json, image; + + const jsonRequest = fetch(`${baseUrl}${format}.json`) + .then(r => r.json()) + .then(r => json = r); + + const imageRequest = fetch(`${baseUrl}${format}.png`) + .then(r => r.blob()) + .then(r => { + image = new Image(); + image.src = URL.createObjectURL(r); + return new Promise((resolve, reject) => { + image.onload = () => resolve(); + image.onerror = () => reject(); + }); + }); + + return Promise.all([jsonRequest, imageRequest]) + .then(() => { + const imageData = getImageData(image); + const result = {}; + + for (const id in json) { + const {width, height, x, y, sdf, pixelRatio, stretchX, stretchY, content} = json[id]; + const data = new RGBAImage({width, height}); + RGBAImage.copy(imageData, data, {x, y}, {x: 0, y: 0}, {width, height}); + result[id] = {data, pixelRatio, sdf, stretchX, stretchY, content}; + } + return result; + }); +} + const SOURCE_ID = 'indoorequal'; /** @@ -281,6 +405,7 @@ const SOURCE_ID = 'indoorequal'; * @param {object} options * @param {url} [options.url] Override the default tiles URL (https://tiles.indoorequal.org/). * @param {string} [options.apiKey] The API key if you use the default tile URL (get your free key at [indoorequal.com](https://indoorequal.com)). + * @param {array} [options.layers] The layers to be used to style indoor= tiles. * @property {string} level The current level displayed * @property {array} levels The levels that can be displayed in the current view * @fires IndoorEqual#levelschange @@ -289,14 +414,15 @@ const SOURCE_ID = 'indoorequal'; */ class IndoorEqual { constructor(map, options = {}) { - const defaultOpts = { url: 'https://tiles.indoorequal.org/' }; - const opts = { ...defaultOpts, ...options }; + const defaultOpts = { url: 'https://tiles.indoorequal.org/', layers }; + const opts = { ...defaultOpts, ...options }; if (opts.url === defaultOpts.url && !opts.apiKey) { throw 'You must register your apiKey at https://indoorequal.com before and set it as apiKey param.'; } this.map = map; this.url = opts.url; this.apiKey = opts.apiKey; + this.layers = opts.layers; this.levels = []; this.level = "0"; this.events = {}; @@ -351,23 +477,56 @@ class IndoorEqual { } /** - * Update the displayed level. + * Set the displayed level. * @param {string} level the level to be displayed * @fires IndoorEqual#levelchange */ - updateLevel(level) { + setLevel(level) { this.level = level; this._updateFilters(); this._emitLevelChange(); } + /** + * Set the displayed level. + * @deprecated + * @param {string} level the level to be displayed + * @fires IndoorEqual#levelchange + */ + updateLevel(level) { + this.setLevel(level); + } + + /** + * Load a sprite and add all images to the map + * @param {string} baseUrl the baseUrl where to load the sprite + * @param {object} options + * @param {url} [options.update] Update existing image (default false) + * @return {Promise} It resolves an hash of images. + */ + loadSprite(baseUrl, options = {}) { + const opts = { update: false, ...options }; + return loadSprite(baseUrl) + .then((sprite) => { + for (const id in sprite) { + const { data, ...options } = sprite[id]; + if (!this.map.hasImage(id)) { + this.map.addImage(id, data, options); + } else if (opts.update) { + this.map.updateImage(id, data); + } + } + return sprite; + }); + } + _addSource() { const queryParams = this.apiKey ? `?key=${this.apiKey}` : ''; this.map.addSource(SOURCE_ID, { type: 'vector', url: `${this.url}${queryParams}` }); - layers.forEach((layer) => { + this.layers.forEach((layer) => { this.map.addLayer({ source: SOURCE_ID, ...layer @@ -382,14 +541,14 @@ class IndoorEqual { } _updateFilters() { - layers.forEach((layer) => { - this.map.setFilter(layer.id, [ ...layer.filter, ['==', 'level', this.level]]); + this.layers.forEach((layer) => { + this.map.setFilter(layer.id, [ ...layer.filter || ['all'], ['==', 'level', this.level]]); }); } _refreshAfterLevelsUpdate() { if (!this.levels.includes(this.level)) { - this.updateLevel('0'); + this.setLevel('0'); } } diff --git a/dist/mapbox-gl-indoorequal.esm.js b/dist/mapbox-gl-indoorequal.esm.js index f02a04e..e8ffb73 100644 --- a/dist/mapbox-gl-indoorequal.esm.js +++ b/dist/mapbox-gl-indoorequal.esm.js @@ -43,7 +43,7 @@ class LevelControl { if (level == this.indoorequal.level) { button.classList.add('mapboxgl-ctrl-active'); } - button.addEventListener('click', () => { this.indoorequal.updateLevel(level); }); + button.addEventListener('click', () => { this.indoorequal.setLevel(level); }); this.$el.appendChild(button); }); } @@ -92,9 +92,6 @@ const layers = [ "level" ] ], - layout: { - visibility: "visible" - }, paint: { "fill-color": "white" } @@ -113,9 +110,6 @@ const layers = [ "platform" ] ], - "layout": { - "visibility": "visible" - }, "paint": { "line-color": "#bfbfbf", "line-width": 1 @@ -133,9 +127,6 @@ const layers = [ "column" ] ], - "layout": { - "visibility": "visible" - }, "paint": { "fill-color": "#bfbfbf" } @@ -153,9 +144,6 @@ const layers = [ "wall" ] ], - "layout": { - "visibility": "visible" - }, "paint": { "line-color": "gray", "line-width": 2 @@ -168,9 +156,6 @@ const layers = [ "filter": [ "all" ], - "layout": { - "visibility": "visible", - }, "paint": { "line-color": "gray", "line-dasharray": [ @@ -269,6 +254,145 @@ const layers = [ } ]; +function createImage(image, {width, height}, channels, data) { + if (!data) { + data = new Uint8Array(width * height * channels); + } else if (data instanceof Uint8ClampedArray) { + data = new Uint8Array(data.buffer); + } else if (data.length !== width * height * channels) { + throw new RangeError('mismatched image size'); + } + image.width = width; + image.height = height; + image.data = data; + return image; +} + +function resizeImage(image, {width, height}, channels) { + if (width === image.width && height === image.height) { + return; + } + + const newImage = createImage({}, {width, height}, channels); + + copyImage(image, newImage, {x: 0, y: 0}, {x: 0, y: 0}, { + width: Math.min(image.width, width), + height: Math.min(image.height, height) + }, channels); + + image.width = width; + image.height = height; + image.data = newImage.data; +} + +function copyImage(srcImg, dstImg, srcPt, dstPt, size, channels) { + if (size.width === 0 || size.height === 0) { + return dstImg; + } + + if (size.width > srcImg.width || + size.height > srcImg.height || + srcPt.x > srcImg.width - size.width || + srcPt.y > srcImg.height - size.height) { + throw new RangeError('out of range source coordinates for image copy'); + } + + if (size.width > dstImg.width || + size.height > dstImg.height || + dstPt.x > dstImg.width - size.width || + dstPt.y > dstImg.height - size.height) { + throw new RangeError('out of range destination coordinates for image copy'); + } + + const srcData = srcImg.data; + const dstData = dstImg.data; + + for (let y = 0; y < size.height; y++) { + const srcOffset = ((srcPt.y + y) * srcImg.width + srcPt.x) * channels; + const dstOffset = ((dstPt.y + y) * dstImg.width + dstPt.x) * channels; + for (let i = 0; i < size.width * channels; i++) { + dstData[dstOffset + i] = srcData[srcOffset + i]; + } + } + return dstImg; +} + +// Not premultiplied, because ImageData is not premultiplied. +// UNPACK_PREMULTIPLY_ALPHA_WEBGL must be used when uploading to a texture. +class RGBAImage { + constructor(size, data) { + createImage(this, size, 4, data); + } + + resize(size) { + resizeImage(this, size, 4); + } + + replace(data, copy) { + if (copy) { + this.data.set(data); + } else if (data instanceof Uint8ClampedArray) { + this.data = new Uint8Array(data.buffer); + } else { + this.data = data; + } + } + + clone() { + return new RGBAImage({width: this.width, height: this.height}, new Uint8Array(this.data)); + } + + static copy(srcImg, dstImg, srcPt, dstPt, size) { + copyImage(srcImg, dstImg, srcPt, dstPt, size, 4); + } +} + +function getImageData(img, padding) { + const canvas = window.document.createElement('canvas'); + const context = canvas.getContext('2d'); + if (!context) { + throw new Error('failed to create canvas 2d context'); + } + canvas.width = img.width; + canvas.height = img.height; + context.drawImage(img, 0, 0, img.width, img.height); + return context.getImageData(0, 0, img.width, img.height); +} + +function loadSprite(baseUrl) { + const format = window.devicePixelRatio > 1 ? '@2x' : ''; + let json, image; + + const jsonRequest = fetch(`${baseUrl}${format}.json`) + .then(r => r.json()) + .then(r => json = r); + + const imageRequest = fetch(`${baseUrl}${format}.png`) + .then(r => r.blob()) + .then(r => { + image = new Image(); + image.src = URL.createObjectURL(r); + return new Promise((resolve, reject) => { + image.onload = () => resolve(); + image.onerror = () => reject(); + }); + }); + + return Promise.all([jsonRequest, imageRequest]) + .then(() => { + const imageData = getImageData(image); + const result = {}; + + for (const id in json) { + const {width, height, x, y, sdf, pixelRatio, stretchX, stretchY, content} = json[id]; + const data = new RGBAImage({width, height}); + RGBAImage.copy(imageData, data, {x, y}, {x: 0, y: 0}, {width, height}); + result[id] = {data, pixelRatio, sdf, stretchX, stretchY, content}; + } + return result; + }); +} + const SOURCE_ID = 'indoorequal'; /** @@ -277,6 +401,7 @@ const SOURCE_ID = 'indoorequal'; * @param {object} options * @param {url} [options.url] Override the default tiles URL (https://tiles.indoorequal.org/). * @param {string} [options.apiKey] The API key if you use the default tile URL (get your free key at [indoorequal.com](https://indoorequal.com)). + * @param {array} [options.layers] The layers to be used to style indoor= tiles. * @property {string} level The current level displayed * @property {array} levels The levels that can be displayed in the current view * @fires IndoorEqual#levelschange @@ -285,14 +410,15 @@ const SOURCE_ID = 'indoorequal'; */ class IndoorEqual { constructor(map, options = {}) { - const defaultOpts = { url: 'https://tiles.indoorequal.org/' }; - const opts = { ...defaultOpts, ...options }; + const defaultOpts = { url: 'https://tiles.indoorequal.org/', layers }; + const opts = { ...defaultOpts, ...options }; if (opts.url === defaultOpts.url && !opts.apiKey) { throw 'You must register your apiKey at https://indoorequal.com before and set it as apiKey param.'; } this.map = map; this.url = opts.url; this.apiKey = opts.apiKey; + this.layers = opts.layers; this.levels = []; this.level = "0"; this.events = {}; @@ -347,23 +473,56 @@ class IndoorEqual { } /** - * Update the displayed level. + * Set the displayed level. * @param {string} level the level to be displayed * @fires IndoorEqual#levelchange */ - updateLevel(level) { + setLevel(level) { this.level = level; this._updateFilters(); this._emitLevelChange(); } + /** + * Set the displayed level. + * @deprecated + * @param {string} level the level to be displayed + * @fires IndoorEqual#levelchange + */ + updateLevel(level) { + this.setLevel(level); + } + + /** + * Load a sprite and add all images to the map + * @param {string} baseUrl the baseUrl where to load the sprite + * @param {object} options + * @param {url} [options.update] Update existing image (default false) + * @return {Promise} It resolves an hash of images. + */ + loadSprite(baseUrl, options = {}) { + const opts = { update: false, ...options }; + return loadSprite(baseUrl) + .then((sprite) => { + for (const id in sprite) { + const { data, ...options } = sprite[id]; + if (!this.map.hasImage(id)) { + this.map.addImage(id, data, options); + } else if (opts.update) { + this.map.updateImage(id, data); + } + } + return sprite; + }); + } + _addSource() { const queryParams = this.apiKey ? `?key=${this.apiKey}` : ''; this.map.addSource(SOURCE_ID, { type: 'vector', url: `${this.url}${queryParams}` }); - layers.forEach((layer) => { + this.layers.forEach((layer) => { this.map.addLayer({ source: SOURCE_ID, ...layer @@ -378,14 +537,14 @@ class IndoorEqual { } _updateFilters() { - layers.forEach((layer) => { - this.map.setFilter(layer.id, [ ...layer.filter, ['==', 'level', this.level]]); + this.layers.forEach((layer) => { + this.map.setFilter(layer.id, [ ...layer.filter || ['all'], ['==', 'level', this.level]]); }); } _refreshAfterLevelsUpdate() { if (!this.levels.includes(this.level)) { - this.updateLevel('0'); + this.setLevel('0'); } } diff --git a/dist/mapbox-gl-indoorequal.umd.min.js b/dist/mapbox-gl-indoorequal.umd.min.js index 98c83f3..a9ea261 100644 --- a/dist/mapbox-gl-indoorequal.umd.min.js +++ b/dist/mapbox-gl-indoorequal.umd.min.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).IndoorEqual=t()}(this,(function(){"use strict";function e(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function t(e,t){for(var i=0;ie.length)&&(t=e.length);for(var i=0,n=new Array(t);i=0?n=setTimeout(s,t-u):(n=null,i||(a=e.apply(o,r),o=r=null))}null==t&&(t=100);var u=function(){o=this,r=arguments,l=Date.now();var u=i&&!n;return n||(n=setTimeout(s,t)),u&&(a=e.apply(o,r),o=r=null),a};return u.clear=function(){n&&(clearTimeout(n),n=null)},u.flush=function(){n&&(a=e.apply(o,r),o=r=null,clearTimeout(n),n=null)},u}s.debounce=s;var u=s;var c=function(){function t(i){var n=this;e(this,t),this.indoorequal=i,this._cbRefresh=function(){return n._refresh()},this.indoorequal.on("levelschange",this._cbRefresh),this.indoorequal.on("levelchange",this._cbRefresh),this.$el=document.createElement("div"),this.$el.classList.add("mapboxgl-ctrl","mapboxgl-ctrl-group","mapboxgl-ctrl-indoorequal"),this._refresh()}return i(t,[{key:"destroy",value:function(){this.$el.remove(),this.indoorequal.off("levelschange",this._cbRefresh),this.indoorequal.off("levelchange",this._cbRefresh)}},{key:"_refresh",value:function(){var e=this;if(this.$el.innerHTML="",1!==this.indoorequal.levels.length)this.indoorequal.levels.map((function(t){var i=document.createElement("button"),n=document.createElement("strong");n.textContent=t,i.appendChild(n),t==e.indoorequal.level&&i.classList.add("mapboxgl-ctrl-active"),i.addEventListener("click",(function(){e.indoorequal.updateLevel(t)})),e.$el.appendChild(i)}))}}]),t}(),f={type:"symbol","source-layer":"poi",layout:{"icon-image":"{class}_11","text-anchor":"top","text-field":"{name:latin}\n{name:nonlatin}","text-max-width":9,"text-offset":[0,.6],"text-padding":2,"text-size":12},paint:{"text-color":"#666","text-halo-blur":.5,"text-halo-color":"#ffffff","text-halo-width":1}},h=["waste_basket","information"],d=[{id:"indoor-polygon",type:"fill","source-layer":"area",filter:["all",["==","$type","Polygon"],["!=","class","level"]],layout:{visibility:"visible"},paint:{"fill-color":"white"}},{id:"indoor-area",type:"line","source-layer":"area",filter:["all",["in","class","area","corridor","platform"]],layout:{visibility:"visible"},paint:{"line-color":"#bfbfbf","line-width":1}},{id:"indoor-column",type:"fill","source-layer":"area",filter:["all",["==","class","column"]],layout:{visibility:"visible"},paint:{"fill-color":"#bfbfbf"}},{id:"indoor-lines",type:"line","source-layer":"area",filter:["all",["in","class","room","wall"]],layout:{visibility:"visible"},paint:{"line-color":"gray","line-width":2}},{id:"indoor-transportation",type:"line","source-layer":"transportation",filter:["all"],layout:{visibility:"visible"},paint:{"line-color":"gray","line-dasharray":[.4,.75],"line-width":{base:1.4,stops:[[17,2],[20,10]]}}},o(o({id:"indoor-poi-rank1"},f),{},{filter:["all",["==","$type","Point"],["!in","class"].concat(h)]}),o(o({id:"indoor-poi-rank2"},f),{},{minzoom:19,filter:["all",["==","$type","Point"],["in","class"].concat(h)]}),o(o({id:"indoor-poi-vending"},f),{},{minzoom:19,filter:["all",["==","$type","Point"],["==","class","vending_machine"]],layout:o(o({},f.layout),{},{"icon-image":"{subclass}_11"})}),{id:"indoor-name",type:"symbol","source-layer":"area_name",filter:["all"],layout:{"text-field":["get","name"],"text-max-width":5,"text-size":14},paint:{"text-color":"#666","text-halo-color":"#ffffff","text-halo-width":1}}];return function(){function t(i){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};e(this,t);var r={url:"https://tiles.indoorequal.org/"},l=o(o({},r),n);if(l.url===r.url&&!l.apiKey)throw"You must register your apiKey at https://indoorequal.com before and set it as apiKey param.";this.map=i,this.url=l.url,this.apiKey=l.apiKey,this.levels=[],this.level="0",this.events={},this.map.isStyleLoaded()?this._addSource():this.map.on("load",this._addSource.bind(this))}return i(t,[{key:"on",value:function(e,t){this.events[e]||(this.events[e]=[]),this.events[e].push(t)}},{key:"off",value:function(e,t){this.events[e]||(this.events[e]=[]),this.events[e]=this.events[e].filter((function(e){return e!==t}))}},{key:"onAdd",value:function(){return this._control=new c(this),this._control.$el}},{key:"onRemove",value:function(){this._control.destroy(),this._control=null}},{key:"updateLevel",value:function(e){this.level=e,this._updateFilters(),this._emitLevelChange()}},{key:"_addSource",value:function(){var e=this,t=this.apiKey?"?key=".concat(this.apiKey):"";this.map.addSource("indoorequal",{type:"vector",url:"".concat(this.url).concat(t)}),d.forEach((function(t){e.map.addLayer(o({source:"indoorequal"},t))})),this._updateFilters();var i=u(this._updateLevels.bind(this),1e3);this.map.on("load",i),this.map.on("data",i),this.map.on("move",i)}},{key:"_updateFilters",value:function(){var e=this;d.forEach((function(t){e.map.setFilter(t.id,[].concat(l(t.filter),[["==","level",e.level]]))}))}},{key:"_refreshAfterLevelsUpdate",value:function(){this.levels.includes(this.level)||this.updateLevel("0")}},{key:"_updateLevels",value:function(){if(this.map.isSourceLoaded("indoorequal")){var e=function(e){for(var t=[],i=0;i1?t-1:0),n=1;n=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}function l(e){return function(e){if(Array.isArray(e))return s(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return s(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return s(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function s(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n=0?i=setTimeout(s,t-h):(i=null,n||(l=e.apply(o,r),o=r=null))}null==t&&(t=100);var h=function(){o=this,r=arguments,a=Date.now();var h=n&&!i;return i||(i=setTimeout(s,t)),h&&(l=e.apply(o,r),o=r=null),l};return h.clear=function(){i&&(clearTimeout(i),i=null)},h.flush=function(){i&&(l=e.apply(o,r),o=r=null,clearTimeout(i),i=null)},h}h.debounce=h;var u=h;var c=function(){function t(n){var i=this;e(this,t),this.indoorequal=n,this._cbRefresh=function(){return i._refresh()},this.indoorequal.on("levelschange",this._cbRefresh),this.indoorequal.on("levelchange",this._cbRefresh),this.$el=document.createElement("div"),this.$el.classList.add("mapboxgl-ctrl","mapboxgl-ctrl-group","mapboxgl-ctrl-indoorequal"),this._refresh()}return n(t,[{key:"destroy",value:function(){this.$el.remove(),this.indoorequal.off("levelschange",this._cbRefresh),this.indoorequal.off("levelchange",this._cbRefresh)}},{key:"_refresh",value:function(){var e=this;if(this.$el.innerHTML="",1!==this.indoorequal.levels.length)this.indoorequal.levels.map((function(t){var n=document.createElement("button"),i=document.createElement("strong");i.textContent=t,n.appendChild(i),t==e.indoorequal.level&&n.classList.add("mapboxgl-ctrl-active"),n.addEventListener("click",(function(){e.indoorequal.setLevel(t)})),e.$el.appendChild(n)}))}}]),t}(),f={type:"symbol","source-layer":"poi",layout:{"icon-image":"{class}_11","text-anchor":"top","text-field":"{name:latin}\n{name:nonlatin}","text-max-width":9,"text-offset":[0,.6],"text-padding":2,"text-size":12},paint:{"text-color":"#666","text-halo-blur":.5,"text-halo-color":"#ffffff","text-halo-width":1}},d=["waste_basket","information"],p=[{id:"indoor-polygon",type:"fill","source-layer":"area",filter:["all",["==","$type","Polygon"],["!=","class","level"]],paint:{"fill-color":"white"}},{id:"indoor-area",type:"line","source-layer":"area",filter:["all",["in","class","area","corridor","platform"]],paint:{"line-color":"#bfbfbf","line-width":1}},{id:"indoor-column",type:"fill","source-layer":"area",filter:["all",["==","class","column"]],paint:{"fill-color":"#bfbfbf"}},{id:"indoor-lines",type:"line","source-layer":"area",filter:["all",["in","class","room","wall"]],paint:{"line-color":"gray","line-width":2}},{id:"indoor-transportation",type:"line","source-layer":"transportation",filter:["all"],paint:{"line-color":"gray","line-dasharray":[.4,.75],"line-width":{base:1.4,stops:[[17,2],[20,10]]}}},o(o({id:"indoor-poi-rank1"},f),{},{filter:["all",["==","$type","Point"],["!in","class"].concat(d)]}),o(o({id:"indoor-poi-rank2"},f),{},{minzoom:19,filter:["all",["==","$type","Point"],["in","class"].concat(d)]}),o(o({id:"indoor-poi-vending"},f),{},{minzoom:19,filter:["all",["==","$type","Point"],["==","class","vending_machine"]],layout:o(o({},f.layout),{},{"icon-image":"{subclass}_11"})}),{id:"indoor-name",type:"symbol","source-layer":"area_name",filter:["all"],layout:{"text-field":["get","name"],"text-max-width":5,"text-size":14},paint:{"text-color":"#666","text-halo-color":"#ffffff","text-halo-width":1}}];function y(e,t,n,i){var r=t.width,o=t.height;if(i){if(i instanceof Uint8ClampedArray)i=new Uint8Array(i.buffer);else if(i.length!==r*o*n)throw new RangeError("mismatched image size")}else i=new Uint8Array(r*o*n);return e.width=r,e.height=o,e.data=i,e}function v(e,t,n,i,r,o){if(0===r.width||0===r.height)return t;if(r.width>e.width||r.height>e.height||n.x>e.width-r.width||n.y>e.height-r.height)throw new RangeError("out of range source coordinates for image copy");if(r.width>t.width||r.height>t.height||i.x>t.width-r.width||i.y>t.height-r.height)throw new RangeError("out of range destination coordinates for image copy");for(var a=e.data,l=t.data,s=0;s1?"@2x":"",r=fetch("".concat(e).concat(i,".json")).then((function(e){return e.json()})).then((function(e){return t=e})),o=fetch("".concat(e).concat(i,".png")).then((function(e){return e.blob()})).then((function(e){return(n=new Image).src=URL.createObjectURL(e),new Promise((function(e,t){n.onload=function(){return e()},n.onerror=function(){return t()}}))}));return Promise.all([r,o]).then((function(){var e=function(e,t){var n=window.document.createElement("canvas"),i=n.getContext("2d");if(!i)throw new Error("failed to create canvas 2d context");return n.width=e.width,n.height=e.height,i.drawImage(e,0,0,e.width,e.height),i.getImageData(0,0,e.width,e.height)}(n),i={};for(var r in t){var o=t[r],a=o.width,l=o.height,s=o.x,h=o.y,u=o.sdf,c=o.pixelRatio,f=o.stretchX,d=o.stretchY,p=o.content,y=new m({width:a,height:l});m.copy(e,y,{x:s,y:h},{x:0,y:0},{width:a,height:l}),i[r]={data:y,pixelRatio:c,sdf:u,stretchX:f,stretchY:d,content:p}}return i}))}return function(){function t(n){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};e(this,t);var r={url:"https://tiles.indoorequal.org/",layers:p},a=o(o({},r),i);if(a.url===r.url&&!a.apiKey)throw"You must register your apiKey at https://indoorequal.com before and set it as apiKey param.";this.map=n,this.url=a.url,this.apiKey=a.apiKey,this.layers=a.layers,this.levels=[],this.level="0",this.events={},this.map.isStyleLoaded()?this._addSource():this.map.on("load",this._addSource.bind(this))}return n(t,[{key:"on",value:function(e,t){this.events[e]||(this.events[e]=[]),this.events[e].push(t)}},{key:"off",value:function(e,t){this.events[e]||(this.events[e]=[]),this.events[e]=this.events[e].filter((function(e){return e!==t}))}},{key:"onAdd",value:function(){return this._control=new c(this),this._control.$el}},{key:"onRemove",value:function(){this._control.destroy(),this._control=null}},{key:"setLevel",value:function(e){this.level=e,this._updateFilters(),this._emitLevelChange()}},{key:"updateLevel",value:function(e){this.setLevel(e)}},{key:"loadSprite",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=o({update:!1},n);return g(e).then((function(e){for(var n in e){var r=e[n],o=r.data,l=a(r,["data"]);t.map.hasImage(n)?i.update&&t.map.updateImage(n,o):t.map.addImage(n,o,l)}return e}))}},{key:"_addSource",value:function(){var e=this,t=this.apiKey?"?key=".concat(this.apiKey):"";this.map.addSource("indoorequal",{type:"vector",url:"".concat(this.url).concat(t)}),this.layers.forEach((function(t){e.map.addLayer(o({source:"indoorequal"},t))})),this._updateFilters();var n=u(this._updateLevels.bind(this),1e3);this.map.on("load",n),this.map.on("data",n),this.map.on("move",n)}},{key:"_updateFilters",value:function(){var e=this;this.layers.forEach((function(t){e.map.setFilter(t.id,[].concat(l(t.filter||["all"]),[["==","level",e.level]]))}))}},{key:"_refreshAfterLevelsUpdate",value:function(){this.levels.includes(this.level)||this.setLevel("0")}},{key:"_updateLevels",value:function(){if(this.map.isSourceLoaded("indoorequal")){var e=function(e){for(var t=[],n=0;n1?t-1:0),i=1;i