Skip to content

Commit 1e80b23

Browse files
Merge pull request #24 from openearth/feat/dynamic-layers-v2
Feat/dynamic layers v2
2 parents fac1bc6 + 749e84d commit 1e80b23

File tree

3 files changed

+110
-41
lines changed

3 files changed

+110
-41
lines changed

src/components/VMapbox.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
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).
55
-->
66
<div>
7+
<!-- Are these named slots actually ever used?-->
78
<slot name="layers"></slot>
89
<slot name="sources"></slot>
910
<slot></slot>

src/components/v-mapbox-layer.js

Lines changed: 64 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,80 @@
11
export default {
22
name: 'v-mapbox-layer',
3-
render () { },
4-
data () {
5-
return {
6-
};
7-
},
3+
4+
inject: ['getMap'],
5+
6+
render: () => null,
7+
88
props: {
99
options: {
10-
default: () => {
11-
return {};
12-
},
13-
type: [Object, String]
10+
type: Object,
11+
default: () => ({})
1412
},
15-
// allows to place a layer before another
13+
14+
// Allows to place a layer before another
1615
before: {
1716
type: String,
18-
required: false
17+
default: undefined
1918
}
2019
},
21-
mounted () {
22-
},
20+
21+
data: () => ({
22+
isInitialized: false
23+
}),
24+
2325
methods: {
24-
deferredMountedTo(map) {
25-
// if we were already mounted, we need to remove the old layr
26-
let oldLayer = map.getLayer(this.options.id)
27-
if (oldLayer) {
28-
map.removeLayer(this.options.id)
29-
try {
30-
map.removeSource(oldLayer.source)
31-
} catch {
32-
console.warn('could not remove source', oldLayer.source)
26+
deferredMountedTo() {
27+
if(!this.isInitialized) {
28+
this.renderLayer();
29+
this.isInitialized = true;
30+
}
31+
},
32+
33+
renderLayer() {
34+
this.removeLayer();
35+
this.addLayer();
36+
},
37+
38+
addLayer() {
39+
const map = this.getMap();
40+
map.addLayer(this.options, this.before);
41+
},
42+
43+
removeLayer() {
44+
const map = this.getMap();
45+
if(map) {
46+
const layerId = this.options.id;
47+
const layer = map.getLayer(layerId);
48+
if(layer) {
49+
const layerSource = layer.source;
50+
map.removeLayer(layerId);
51+
if(layerSource && !map.getStyle().layers.some(({ source }) => source === layerSource)) {
52+
map.removeSource(layerSource);
53+
}
3354
}
3455
}
35-
// if we want to add a layer before another layer, use the before option
36-
if (this.before) {
37-
map.addLayer(this.options, this.before)
38-
} else {
39-
map.addLayer(this.options)
56+
},
57+
},
58+
59+
mounted() {
60+
const map = this.getMap();
61+
// We can immediately initialize if we have the map ready
62+
if(map && map.isStyleLoaded()) {
63+
this.renderLayer();
64+
this.isInitialized = true;
65+
}
66+
},
67+
68+
destroyed() {
69+
this.removeLayer();
70+
},
71+
72+
watch: {
73+
options: {
74+
deep: true,
75+
handler() {
76+
this.renderLayer();
4077
}
41-
let layer = map.getLayer(this.options.id)
4278
}
4379
}
4480
};

src/stories/index.stories.js

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
/* eslint-disable react/react-in-jsx-scope */
22

3-
import { storiesOf, addDecorator } from '@storybook/vue';
4-
import { action } from '@storybook/addon-actions';
5-
import { withKnobs, text, number, boolean, array, select, color, date, button } from '@storybook/addon-knobs';
6-
import { linkTo } from '@storybook/addon-links';
3+
import { storiesOf } from '@storybook/vue';
4+
import { withKnobs, button } from '@storybook/addon-knobs';
75

86
import 'mapbox-gl/dist/mapbox-gl.css'
97
// needed for the v-mapbox-geocoder
@@ -32,7 +30,6 @@ const zoomTemplate = `
3230
/>
3331
`
3432

35-
3633
const navigationTemplate = `
3734
<v-mapbox
3835
map-style="mapbox://styles/mapbox/satellite-streets-v10"
@@ -88,7 +85,6 @@ const canvasTemplate = `
8885
</div>
8986
`
9087

91-
9288
const injectTemplate = `
9389
<v-mapbox
9490
map-style="mapbox://styles/mapbox/satellite-streets-v10"
@@ -128,6 +124,7 @@ const layerA = {
128124
'fill-opacity': 1
129125
}
130126
}
127+
131128
const layerB = {
132129
'id': 'b',
133130
'type': 'fill',
@@ -166,7 +163,17 @@ const sortingTemplate = `
166163
<!-- green (we want this on top) -->
167164
<v-mapbox-layer :options="layerA"></v-mapbox-layer>
168165
<!-- red -->
169-
<v-mapbox-layer before="a" :options="layerB"></v-mapbox-layer>
166+
<v-mapbox-layer :options="layerB"></v-mapbox-layer>
167+
</v-mapbox>
168+
`
169+
170+
const dynamicLayersTemplate = `
171+
<v-mapbox
172+
:map-style="style"
173+
access-token="pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw"
174+
style="height: 300px;"
175+
>
176+
<v-mapbox-layer v-for="layer in layers" :options="layer" :key="layer.id" />
170177
</v-mapbox>
171178
`
172179

@@ -177,13 +184,10 @@ const styleAndLayerTemplate = `
177184
style="height: 300px;"
178185
:center="[0, 0]"
179186
>
180-
<!-- green (we want this on top) -->
181-
<v-mapbox-layer :options="layerA"></v-mapbox-layer>
187+
<v-mapbox-layer :options="layerA"></v-mapbox-layer>
182188
</v-mapbox>
183189
`
184190

185-
186-
187191
storiesOf('Map', module)
188192
.add('map', () => {
189193
return {
@@ -200,7 +204,7 @@ storiesOf('Map', module)
200204
},
201205
template: zoomTemplate,
202206
mounted () {
203-
button('random center', () => {
207+
button('random center', () => {
204208
this.center = [Math.random() * 50, Math.random() * 50]
205209
})
206210
}
@@ -225,7 +229,6 @@ storiesOf('Map', module)
225229
map.setPaintProperty('a', 'fill-opacity', opacity)
226230
})
227231
button('toggle visibility', () => {
228-
let opacity = Math.random()
229232
let visibility = map.getLayoutProperty('a', 'visibility')
230233
if (visibility === 'visible') {
231234
visibility = 'none'
@@ -237,6 +240,7 @@ storiesOf('Map', module)
237240
}
238241
}
239242
})
243+
240244
.add('map with navigation control', () => {
241245
return {
242246
template: navigationTemplate
@@ -330,6 +334,7 @@ storiesOf('Map', module)
330334
}
331335
}
332336
})
337+
333338
.add('layer order', () => {
334339
return {
335340
template: sortingTemplate,
@@ -342,6 +347,33 @@ storiesOf('Map', module)
342347
},
343348
}
344349
})
350+
351+
.add('add and remove layers', () => {
352+
return {
353+
template: dynamicLayersTemplate,
354+
data: () => ({
355+
style: 'mapbox://styles/global-data-viewer/cjtss3jfb05w71fmra13u4qqm',
356+
layers: []
357+
}),
358+
mounted() {
359+
button('Toggle layer A', this.toggleLayerA),
360+
button('Toggle layer B', this.toggleLayerB)
361+
},
362+
methods: {
363+
toggleLayerA() {
364+
const hasLayerA = this.layers.some(({ id }) => id === 'a');
365+
if(hasLayerA) this.layers = this.layers.filter(({ id }) => id !== 'a');
366+
else this.layers = [ ...this.layers, layerA];
367+
},
368+
toggleLayerB() {
369+
const hasLayerB = this.layers.some(({ id }) => id === 'b');
370+
if(hasLayerB) this.layers = this.layers.filter(({ id }) => id !== 'b');
371+
else this.layers = [ ...this.layers, layerB];
372+
}
373+
}
374+
}
375+
})
376+
345377
.add('preserve drawing buffer order', () => {
346378
return {
347379
template: canvasTemplate,

0 commit comments

Comments
 (0)