Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Geojson layer not clearing (Removal Not noticing) #463

Open
InhyeLee-Data opened this issue Aug 4, 2021 · 5 comments
Open

Geojson layer not clearing (Removal Not noticing) #463

InhyeLee-Data opened this issue Aug 4, 2021 · 5 comments
Assignees
Labels
needs repro 👀 Requires a reproducible example

Comments

@InhyeLee-Data
Copy link

InhyeLee-Data commented Aug 4, 2021

Hi! I'm on a nuxt app with a vue-mapbox wrapper.

"mapbox-gl": "^1.13.1",
"nuxt": "^2.14.6",
"v-mapbox": "^1.7.3"

One interesting issue I have right now is that a geojson layer that is removed in code still pertains to exist in the rendered page.

This is the scenario.

  1. I have one component that is supposed to display one layer at a time. (let's say one circle)
  2. I click on a button to change the layer into a different one.
  3. In chrome Vue devtools, the reflects the changed layer and only shows one layer.
  4. However, on the rendered mapbox, I can visibly see two layers (let's say two circles) appearing simultaneously.
  5. The layers are also individually clickable, if I were to create a pop up on click.

Anybody has an idea why this would happen and how I may be able to work through this?

@vinayakkulkarni vinayakkulkarni self-assigned this Sep 23, 2021
@vinayakkulkarni vinayakkulkarni added the needs repro 👀 Requires a reproducible example label Sep 23, 2021
@vinayakkulkarni
Copy link
Owner

Hey @InhyeLee-Data, can you please create a fork of this codesandbox or this codesandbox & provide a reproducible example?

@stefangeorg
Copy link

stefangeorg commented Oct 6, 2022

I'm having the same issue:
`





Tell us about your files


×




{{file.file.name}} {{file.file.type}}
{{option.display}}



<button type="button" class="btn btn-primary" @click="convertFileToLayers">Add To Map
Close



NUmber files {{files.length}}
<v-map class="w-full h-full" :options="state.map">
    <VLayerMapboxGeojson v-for="(layer, i) in activeLayers" :key="i"
        :sourceId="layer.id"
        :source="layer.source"
        :layerId="layer.id"
        :layer="layer"
        />
    <div id='layers'>
        <div v-for="layer in layers" :key="layer.id" class='list-group'>
            <button class='list-group-item' :class="{active: layer.active}" @click="layer.active = !layer.active">{{layer.id}}</button>
        </div>
    </div>
</v-map>
`

<script>
window.global = window;
import { VMap, VControlNavigation, VLayerMapboxGeojson } from "v-mapbox";
import { reactive } from "vue";

function readFileAsync(file) {
return new Promise((resolve, reject) => {
let reader = new FileReader();

reader.onload = () => {
  resolve(reader.result);
};

reader.onerror = reject;

reader.readAsArrayBuffer(file);

})
}

export default {
name: "App",
components: {
VMap,
VLayerMapboxGeojson,
},
setup() {
const state = reactive({
map: {
accessToken:
"pk.eyJ1Ijoic29jaWFsZXhwbG9yZXIiLCJhIjoiREFQbXBISSJ9.dwFTwfSaWsHvktHrRtpydQ",
style: "mapbox://styles/mapbox/streets-v11?optimize=true",
// style: "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json",
center: [13.4, 52.5],
zoom: 11,
maxZoom: 22,
crossSourceCollisions: false,
failIfMajorPerformanceCaveat: false,
attributionControl: false,
preserveDrawingBuffer: true,
hash: false,
minPitch: 0,
maxPitch: 60,
},
});

return {
  state,
  files: reactive([]),
  layers: reactive([]),
};

},
methods: {
convertFileToLayers() {
this.files.forEach(file => {
try{
file.handler(file.file);
} catch(e) {
console.error(e)
}
})
this.files = reactive([]);
console.log(this.files, this.files.length)
},
onFileAdd(file) {
this.files.push(file);
console.log(file);
this.detectFileType(file);
},
detectFileType(file) {
const fileTypes = {
'application/zip': [{display: 'Compressed Shapefile', handler: this.shapeFileHandler}]
}
const extensions = {
'geojson': [{display: 'Geojson layer', handler: this.geojsonHandler}]
}
const splitted = file.file.name.split('.');
const extension = splitted[splitted.length - 1]
console.log(extension)
if (file.file.type in fileTypes) {
const type = fileTypes[file.file.type]
file.file.options = type
}
if (extension in extensions){
file.file.options = extensions[extension];
}

}, 
shapeFileHandler(file) {
    console.log('called handler', file)
    var reader = new FileReader();
    // convert shapefile to geojson
    reader.onloadend = (e) => {
        console.log(e.target.result)
        shp(e.target.result).then((geojson) => {
            //see bellow for whats here this internally call shp.parseZip()
            this.layers.push({
                source: {'type': 'geojson', data: geojson},
                id: file.name,
                active: true,
                type: "fill",
                paint: {
                    "fill-color": 'red',
                    "fill-opacity": 0.4,
                },
                              
            })
        });
    };
    reader.onerror = function (e) {
        reject(e.target.error);
    };
    reader.readAsArrayBuffer(file);
    
},
async geojsonHandler(file) {
    let contentBuffer = await readFileAsync(file);
    const decoder = new TextDecoder('utf-8');
    const data = JSON.parse(decoder.decode(contentBuffer))
    console.log(data);

    this.layers.push({
        source: {'type': 'geojson', data: data},
        id: file.name,
        active: true,
        type: "fill",
        paint: {
            "fill-color": 'blue',
            "fill-opacity": 0.4,
        },
                        
    })
}

},
computed: {
activeLayers() {
return this.layers.filter(i => i.active)
}
}
};
</script>`

<style lang="scss">
@import "mapbox-gl/dist/mapbox-gl.css";
@import "v-mapbox/dist/v-mapbox.css";
html,
body {
margin: 0;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
.w-screen {
width: 100vw;
}
.h-screen {
height: 100vh;
}
.h-full {
height: 100%;
}
.w-full {
width: 100%;
}
#app .show {
display: block;
}
#map {
position: relative;
}
#layers {
position: absolute;
bottom: 5%;
left: 5%;
width: 200px;
z-index: 100000;
background-color: white;
}
</style>`

I'm allowing users to drag a shapefile or geojson onto the page. Then I show it. But they can deactivate a layer, and it is removed from the Vue inspector, but remains active on the map. Seems no proper destruction is happening when a layer is removed.

@vinayakkulkarni
Copy link
Owner

@stefangeorg can you please create a sandbox for better debugging ?

@stefangeorg
Copy link

@vinayakkulkarni I'll try to setup one, but its relatively simple actually. There is no onUnmounted action. So if the VLayerMapboxGeojson is removed from the parent, the layers and source remain on the map eventhough the component is no longer there. We should cleanup on unMounted to remove the layer and source (or have an options to keep the source but remove the layer)

@stefangeorg
Copy link

stefangeorg commented Oct 11, 2022

Here is how I solved it By extending your component, and passing in the map object as a property.
`

export default defineComponent({
...VLayerMapboxGeojson,
...{
name: "GeoJSONLayer",
extends: VLayerMapboxGeojson,
props: {
...VLayerMapboxGeojson.props,
...{
mapRef: {
type: Object,
required: true,
},
},
},
mounted() {},
unmounted() {
if (!this.mapRef) {
return;
}
if (this.mapRef.getLayer(this.layerId)) {
this.mapRef.removeLayer(this.layerId);
}
if (this.mapRef.getSource(this.sourceId)) {
this.mapRef.removeSource(this.sourceId);
}
},
},
});
`

<GeoJSONLayer v-for="(layer, i) in activeLayers" :key="i" :sourceId="layer.id" :source="layer.source" :layerId="layer.id" :layer="layer" :mapRef="state.mapRef" />

If I inactivate a layer, then it will get removed from the map.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs repro 👀 Requires a reproducible example
Projects
None yet
Development

No branches or pull requests

3 participants