From 989b4ccbfd32bdce7d2da8f50ad0ee7921b1ee69 Mon Sep 17 00:00:00 2001 From: Bob Bol Date: Thu, 30 Jul 2020 12:10:06 +0200 Subject: [PATCH 1/7] allow for layers to be added and removed --- src/components/v-mapbox-layer.js | 91 ++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 29 deletions(-) diff --git a/src/components/v-mapbox-layer.js b/src/components/v-mapbox-layer.js index 6d84651..edf544f 100644 --- a/src/components/v-mapbox-layer.js +++ b/src/components/v-mapbox-layer.js @@ -1,44 +1,77 @@ export default { name: 'v-mapbox-layer', - render () { }, - data () { - return { - }; - }, + + inject: ['getMap'], + + render: () => null, + props: { - options: { - default: () => { - return {}; - }, - type: [Object, String] + layer: { + type: Object, + default: () => ({}) }, - // allows to place a layer before another + + // Allows to place a layer before another before: { type: String, - required: false + default: null } }, - mounted () { - }, + + data: () => ({ + isInitialized: false + }), + methods: { - deferredMountedTo(map) { - // if we were already mounted, we need to remove the old layr - let oldLayer = map.getLayer(this.options.id) - if (oldLayer) { - map.removeLayer(this.options.id) - try { - map.removeSource(oldLayer.source) - } catch { - console.warn('could not remove source', oldLayer.source) + deferredMountedTo() { + if(!this.isInitialized) { + this.renderLayer(); + this.isInitialized = true; + } + }, + + addLayer() { + const map = this.getMap(); + map.addLayer(this.layer, this.before); + }, + + removeLayer() { + const map = this.getMap(); + if(map) { + const layerId = this.layer.id; + const layer = map.getLayer(layerId); + if(layer) { + map.removeLayer(layerId); + map.removeSource(layer.source); } } - // if we want to add a layer before another layer, use the before option - if (this.before) { - map.addLayer(this.options, this.before) - } else { - map.addLayer(this.options) + }, + + renderLayer() { + this.removeLayer(); + this.addLayer(); + } + }, + + mounted () { + const map = this.getMap(); + // We can immediately initialize if we have the map ready + if(map && map.isStyleLoaded()) { + this.renderLayer(); + this.isInitialized = true; + } + }, + + destroyed() { + this.removeLayer(); + }, + + watch: { + layer: { + deep: true, + handler() { + this.renderLayer(); } - let layer = map.getLayer(this.options.id) } } }; From cd56886f0c5866337429500fee2ccfabbec4c52b Mon Sep 17 00:00:00 2001 From: Bob Bol Date: Thu, 30 Jul 2020 12:33:23 +0200 Subject: [PATCH 2/7] updated stories to use `layer` instead of `options` prop --- src/components/v-mapbox-layer.js | 12 ++++++------ src/stories/index.stories.js | 9 +++------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/components/v-mapbox-layer.js b/src/components/v-mapbox-layer.js index edf544f..ceecc73 100644 --- a/src/components/v-mapbox-layer.js +++ b/src/components/v-mapbox-layer.js @@ -30,6 +30,11 @@ export default { } }, + renderLayer() { + this.removeLayer(); + this.addLayer(); + }, + addLayer() { const map = this.getMap(); map.addLayer(this.layer, this.before); @@ -46,14 +51,9 @@ export default { } } }, - - renderLayer() { - this.removeLayer(); - this.addLayer(); - } }, - mounted () { + mounted() { const map = this.getMap(); // We can immediately initialize if we have the map ready if(map && map.isStyleLoaded()) { diff --git a/src/stories/index.stories.js b/src/stories/index.stories.js index 5ab1f29..a7474c6 100644 --- a/src/stories/index.stories.js +++ b/src/stories/index.stories.js @@ -164,9 +164,9 @@ const sortingTemplate = ` :center="[0, 0]" > - + - + ` @@ -177,13 +177,10 @@ const styleAndLayerTemplate = ` style="height: 300px;" :center="[0, 0]" > - - + ` - - storiesOf('Map', module) .add('map', () => { return { From 54b2d9b1bcecf360d8f0d959c12c4a5816fa04f5 Mon Sep 17 00:00:00 2001 From: Bob Bol Date: Thu, 30 Jul 2020 15:04:15 +0200 Subject: [PATCH 3/7] story for adding and removing layers dynamically --- src/stories/index.stories.js | 51 ++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/src/stories/index.stories.js b/src/stories/index.stories.js index a7474c6..4ffc19b 100644 --- a/src/stories/index.stories.js +++ b/src/stories/index.stories.js @@ -1,9 +1,7 @@ /* eslint-disable react/react-in-jsx-scope */ -import { storiesOf, addDecorator } from '@storybook/vue'; -import { action } from '@storybook/addon-actions'; -import { withKnobs, text, number, boolean, array, select, color, date, button } from '@storybook/addon-knobs'; -import { linkTo } from '@storybook/addon-links'; +import { storiesOf } from '@storybook/vue'; +import { withKnobs, button } from '@storybook/addon-knobs'; import 'mapbox-gl/dist/mapbox-gl.css' // needed for the v-mapbox-geocoder @@ -32,7 +30,6 @@ const zoomTemplate = ` /> ` - const navigationTemplate = ` ` - const injectTemplate = ` ` +const dynamicLayersTemplate = ` + + + +` + const styleAndLayerTemplate = ` { + button('random center', () => { this.center = [Math.random() * 50, Math.random() * 50] }) } @@ -222,7 +229,6 @@ storiesOf('Map', module) map.setPaintProperty('a', 'fill-opacity', opacity) }) button('toggle visibility', () => { - let opacity = Math.random() let visibility = map.getLayoutProperty('a', 'visibility') if (visibility === 'visible') { visibility = 'none' @@ -234,6 +240,7 @@ storiesOf('Map', module) } } }) + .add('map with navigation control', () => { return { template: navigationTemplate @@ -327,6 +334,7 @@ storiesOf('Map', module) } } }) + .add('layer order', () => { return { template: sortingTemplate, @@ -339,6 +347,33 @@ storiesOf('Map', module) }, } }) + + .add('add and remove layers', () => { + return { + template: dynamicLayersTemplate, + data: () => ({ + style: 'mapbox://styles/global-data-viewer/cjtss3jfb05w71fmra13u4qqm', + layers: [] + }), + mounted() { + button('Toggle layer A', this.toggleLayerA), + button('Toggle layer B', this.toggleLayerB) + }, + methods: { + toggleLayerA() { + const hasLayerA = this.layers.some(({ id }) => id === 'a'); + if(hasLayerA) this.layers = this.layers.filter(({ id }) => id !== 'a'); + else this.layers = [ ...this.layers, layerA]; + }, + toggleLayerB() { + const hasLayerB = this.layers.some(({ id }) => id === 'b'); + if(hasLayerB) this.layers = this.layers.filter(({ id }) => id !== 'b'); + else this.layers = [ ...this.layers, layerB]; + } + } + } + }) + .add('preserve drawing buffer order', () => { return { template: canvasTemplate, From e5680aae11b3b0a4a993ea2c3f5204749221c354 Mon Sep 17 00:00:00 2001 From: Bob Bol Date: Mon, 24 Aug 2020 10:13:56 +0200 Subject: [PATCH 4/7] revert naming 'layer' back to 'options' --- src/components/v-mapbox-layer.js | 8 ++++---- src/stories/index.stories.js | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/v-mapbox-layer.js b/src/components/v-mapbox-layer.js index ceecc73..86063c1 100644 --- a/src/components/v-mapbox-layer.js +++ b/src/components/v-mapbox-layer.js @@ -6,7 +6,7 @@ export default { render: () => null, props: { - layer: { + options: { type: Object, default: () => ({}) }, @@ -37,13 +37,13 @@ export default { addLayer() { const map = this.getMap(); - map.addLayer(this.layer, this.before); + map.addLayer(this.options, this.before); }, removeLayer() { const map = this.getMap(); if(map) { - const layerId = this.layer.id; + const layerId = this.options.id; const layer = map.getLayer(layerId); if(layer) { map.removeLayer(layerId); @@ -67,7 +67,7 @@ export default { }, watch: { - layer: { + options: { deep: true, handler() { this.renderLayer(); diff --git a/src/stories/index.stories.js b/src/stories/index.stories.js index 4ffc19b..f204a02 100644 --- a/src/stories/index.stories.js +++ b/src/stories/index.stories.js @@ -161,9 +161,9 @@ const sortingTemplate = ` :center="[0, 0]" > - + - + ` @@ -173,7 +173,7 @@ const dynamicLayersTemplate = ` access-token="pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw" style="height: 300px;" > - + ` @@ -184,7 +184,7 @@ const styleAndLayerTemplate = ` style="height: 300px;" :center="[0, 0]" > - + ` From 1a7efaf851fad745baf893db8495151e98c1ee59 Mon Sep 17 00:00:00 2001 From: Bob Bol Date: Mon, 24 Aug 2020 10:31:27 +0200 Subject: [PATCH 5/7] prop default: null -> undefined --- src/components/v-mapbox-layer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/v-mapbox-layer.js b/src/components/v-mapbox-layer.js index 86063c1..15b88ae 100644 --- a/src/components/v-mapbox-layer.js +++ b/src/components/v-mapbox-layer.js @@ -14,7 +14,7 @@ export default { // Allows to place a layer before another before: { type: String, - default: null + default: undefined } }, From d137a7356bc8737f0bd0e11fbea74ca8122d0958 Mon Sep 17 00:00:00 2001 From: Bob Bol Date: Mon, 24 Aug 2020 10:58:41 +0200 Subject: [PATCH 6/7] only remove source if it is not being used by other layers --- src/components/v-mapbox-layer.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/v-mapbox-layer.js b/src/components/v-mapbox-layer.js index 15b88ae..c3a67d7 100644 --- a/src/components/v-mapbox-layer.js +++ b/src/components/v-mapbox-layer.js @@ -46,8 +46,11 @@ export default { const layerId = this.options.id; const layer = map.getLayer(layerId); if(layer) { + const layerSource = layer.source; map.removeLayer(layerId); - map.removeSource(layer.source); + if(layerSource && !map.getStyle().layers.some(({ source }) => source === layerSource)) { + map.removeSource(layerSource); + } } } }, From 749e84d45433a694f8d1899f2491d77bf9547308 Mon Sep 17 00:00:00 2001 From: Bob Bol Date: Tue, 1 Sep 2020 10:33:30 +0200 Subject: [PATCH 7/7] question about slots --- src/components/VMapbox.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/VMapbox.vue b/src/components/VMapbox.vue index d23c7c6..117d14e 100644 --- a/src/components/VMapbox.vue +++ b/src/components/VMapbox.vue @@ -4,6 +4,7 @@ Note: If you put a id on the main element it won't work with multiple maps on one page (for example with compare plugin). -->
+