vue-mapbox icon indicating copy to clipboard operation
vue-mapbox copied to clipboard

Update MglGeojsonLayer after set mapStyle

Open Alexx1992 opened this issue 6 years ago • 3 comments

HI! I have a MglGeojsonLayer component with polygon

<MglGeojsonLayer sourceId="sourceId" :source="source" layerId="layerId" :layer="layer" :clearSource="false" />

And some method like this: this.mapStyle = 'mapbox://styles/mapbox/light-v9';

After map style is changed, the polygon disappears. What is the right way to update source and layer in MglGeojsonLayer component to show polygon again?

Alexx1992 avatar Mar 11 '19 10:03 Alexx1992

How I do it is I use computed value for the source and use .sync. When this.features change the layer is updated automatically with new content.

<template lang="pug">
.......

 mgl-geojson-layer(
      :layerId="getLayerId"
      :sourceId="getSourceId",
      :source.sync="getSource"
      :layer="getLayer"
)

.......

computed: {
.......
     getSource() {
      return {
        data: {
          type: 'FeatureCollection',
          features: this.features,
        },
      };
    },
.......
}

......

aarepuu avatar Mar 27 '19 17:03 aarepuu

I tried calling $_deferredMount() (see https://github.com/soal/vue-mapbox/blob/master/src/components/layer/GeojsonLayer.js#L104) after the map event style.load (which seems like it is emitted after a new style is fully loaded). That seemed to work initially (the layer was visible again), but the watchers on the source data were broken, so changes to the source no longer affected the layer.

I tried a variety of things that didn't work and ended up hitting it with a hammer. I put a key property on each geoJsonLayer, and I update it after style.load, forcing all of the geoJsonLayers to be recreated. Doing this on the map works, too, but that'll mean another map load (which is how usage is billed).

So something like this:

<MglMap
  :mapStyle="mapStyle"
  @load="onMapLoaded"
>
  <MglGeojsonLayer
    :sourceId="tripsGeoJson.data.id"
    :source.sync="tripsGeoJson"
    :replace-source="true"
    :layerId="tripsGeoJson.data.id"
    :layer="tripLineLayer"
    :key="'trips' + mapKey"
  />
</MglMap>

async onMapLoaded(event) {
  event.map.on('style.load', async () => {
    this.mapKey = Date.now();
  });
}

There's probably a cleaner way to do this. If you find it, please share.

rognstad avatar Jun 30 '20 19:06 rognstad

I agree this feels like too much of a hack, but it works! The click handler remains intact which is important in my case.

I tried the suggested method of calling this.map.addLayer() from #146 referencing the geoJsonSource object, but that didn't work. No errors, but the layer wasn't rendered after the style change. I dug a little deeper and found this solution which at least works even if it feels less elegant.

richdunajewski avatar Aug 22 '20 05:08 richdunajewski