ericg
ericg

Reputation: 8722

How to fix default marker-icon.png not found in vue 2 leaflet app?

I have a simple, sample project at https://github.com/ericg-vue-questions/leaflet-test/tree/feature/simple-marker

(note the feature/simple-marker branch)

The relevant code is in the LeafletTest.vue file

<template>
    <div id="container">
        <div id="mapContainer"></div>
    </div>
</template>

<script>
import 'leaflet/dist/leaflet.css';
import L from 'leaflet';
import Vue from 'vue';

export default {
    name: 'Map',

    methods: {
        async setupLeafletMap() {
            const center = [37, -122];

            const mapDiv = L.map('mapContainer').setView(center, 13);

            var tiles = new L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
                minZoom: 3,
                maxZoom: 8
            }).addTo(mapDiv);

            L.marker(center).addTo(mapDiv);
        }
    },

    async mounted() {
        await Vue.nextTick();
        await this.setupLeafletMap();
    }
};
</script>

<style scoped>
#mapContainer {
    width: 500px;
    height: 500px;
}
</style>

When the code run, the default marker shows up as:

broken marker

The URL in the img tag that L.marker(center).addTo(mapDiv); adds to the map is

<img src="marker-icon.png" class="leaflet-marker-icon leaflet-zoom-animated leaflet-interactive" alt="Marker" tabindex="0" role="button" style="margin-left: -12px; margin-top: -41px; width: 25px; height: 41px; transform: translate3d(250px, 250px, 0px); z-index: 250;">

I figure there is something extra I need to do in configuring the vue app so it and leaflet can work together in this case.

What do I need to change so the default marker-icon.png will show up by default?

Upvotes: 1

Views: 860

Answers (1)

ericg
ericg

Reputation: 8722

One answer I found was to modify the mounted() method to be:

    async mounted() {
        delete L.Icon.Default.prototype._getIconUrl;

        L.Icon.Default.mergeOptions({
            iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
            iconUrl: require('leaflet/dist/images/marker-icon.png'),
            shadowUrl: require('leaflet/dist/images/marker-shadow.png')
        });

        await Vue.nextTick();
        await this.setupLeafletMap();
    }

The part that was added was:

        delete L.Icon.Default.prototype._getIconUrl;

        L.Icon.Default.mergeOptions({
            iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
            iconUrl: require('leaflet/dist/images/marker-icon.png'),
            shadowUrl: require('leaflet/dist/images/marker-shadow.png')
        });

If I understand correctly what is going on here is that webpack will see the require's and assist in making sure the right thing happens. If anyone has a more detailed explanation of why this works, I would be interested.

Upvotes: 2

Related Questions