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). -->
+ diff --git a/src/components/v-mapbox-layer.js b/src/components/v-mapbox-layer.js index 6d84651..c3a67d7 100644 --- a/src/components/v-mapbox-layer.js +++ b/src/components/v-mapbox-layer.js @@ -1,44 +1,80 @@ export default { name: 'v-mapbox-layer', - render () { }, - data () { - return { - }; - }, + + inject: ['getMap'], + + render: () => null, + props: { options: { - default: () => { - return {}; - }, - type: [Object, String] + type: Object, + default: () => ({}) }, - // allows to place a layer before another + + // Allows to place a layer before another before: { type: String, - required: false + default: undefined } }, - 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; + } + }, + + renderLayer() { + this.removeLayer(); + this.addLayer(); + }, + + addLayer() { + const map = this.getMap(); + map.addLayer(this.options, this.before); + }, + + removeLayer() { + const map = this.getMap(); + if(map) { + const layerId = this.options.id; + const layer = map.getLayer(layerId); + if(layer) { + const layerSource = layer.source; + map.removeLayer(layerId); + if(layerSource && !map.getStyle().layers.some(({ source }) => source === layerSource)) { + map.removeSource(layerSource); + } } } - // 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) + }, + }, + + 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: { + options: { + deep: true, + handler() { + this.renderLayer(); } - let layer = map.getLayer(this.options.id) } } }; diff --git a/src/stories/index.stories.js b/src/stories/index.stories.js index 5ab1f29..f204a02 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 = ` + + ` @@ -177,13 +184,10 @@ const styleAndLayerTemplate = ` style="height: 300px;" :center="[0, 0]" > - - + ` - - storiesOf('Map', module) .add('map', () => { return { @@ -200,7 +204,7 @@ storiesOf('Map', module) }, template: zoomTemplate, mounted () { - button('random center', () => { + button('random center', () => { this.center = [Math.random() * 50, Math.random() * 50] }) } @@ -225,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' @@ -237,6 +240,7 @@ storiesOf('Map', module) } } }) + .add('map with navigation control', () => { return { template: navigationTemplate @@ -330,6 +334,7 @@ storiesOf('Map', module) } } }) + .add('layer order', () => { return { template: sortingTemplate, @@ -342,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,