Data-Toggle Tab Does Not Download Leaflet Map

Data-toggle tab does not download Leaflet map

Welcome to SO!

If your Leaflet map suddenly works correctly after you resize your browser window, then you experience the classic "map container size not valid at map initialization": in order to work correctly, Leaflet reads the map container size when you initialize the map (L.map("mapContainerId")).

If your application hides that container (typically through CSS display: none;, or some framework tab / modal / whatever…) or later changes its dimensions, Leaflet will not be aware of the new size. Hence it will not render correctly. Typically, it downloads tiles only for the fraction of the container it thinks is shown. This can be a single tile in the top left corner in the case of a container that was entirely hidden at map initialization time.

This mistake often arises when embedding the map container in a "tab" or "modal" panel, possibly using popular frameworks (Bootstrap, Angular, Ionic, etc.).

Leaflet listens to browser window resize event, and reads again the container size when it happens. This explains why the map suddenly works on window resizing.

You can also manually trigger this update by calling map.invalidateSize() when the tab panel is displayed (e.g. add a listener on the tab button click), at least the first time the container is rendered with its correct dimensions.

As for implementing the tab button click listener, perform a new search on SO on that topic: you should have plenty resources available for that matter, for most of the popular frameworks.

I'm having problems showing leaflet map in a bootstrap tab

You forgot to include the CSS file for Leaflet.

Let me quote the Leaflet docs:

The latest stable Leaflet release is hosted on a CDN — to start using it straight away, place this in the head of your HTML code:

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.2/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.0.2/dist/leaflet.js"></script>

Leaflet map not loading in Bulma tab using Vue.js

As explained in Data-toggle tab does not download Leaflet map, the issue is caused by the fact that your map container does not have yet its full size when you initialize it. You may understand it more easily if your map had been in an initially hidden tab (e.g. in tab 2).

As for your initially active tab (i.e. tab 1), it is probable that Buefy / Bulma still takes some time to reveal the tab content.

Since there is no event when the tab transition completes, you have to wait for the transition duration before calling the invalidateSize method. In your case, 300ms seems to be fine.

Then you should also call it again when the user changes the tab (see Buefy tabs events), otherwise should the browser had changed size while your tab was hidden, the same issue would happen again.

Demo with maps in the 2 tabs:

new Vue({

el: '#app',

data: {

map: null,

map2: null,

tabMaps: []

},

methods: {

invalidateSize: function(tabIndex) {

setTimeout(() => {

if (typeof tabIndex === "number") {

this.tabMaps[tabIndex].invalidateSize();

} else {

// invalidate all maps

this.tabMaps.forEach(map => {

map.invalidateSize();

});

}

}, 300);

}

},

mounted() {

this.map = L.map('map').setView([38.63, -90.23], 12);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(this.map);

// map2 in tab2

this.map2 = L.map(this.$refs.map2).setView([38.63, -90.23], 12);

L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").addTo(

this.map2

);

this.tabMaps.push(this.map); // 0

this.tabMaps.push(this.map2); // 1

this.invalidateSize();

}

})
<link rel="stylesheet" href="https://unpkg.com/buefy@0.7/dist/buefy.min.css">

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css">

<div class="section">

<div class="container" id="app">

<b-tabs @change="invalidateSize" position="is-centered">

<b-tab-item label="Tab 1">

<div class="section">

Tab 1

<div class="map" id="map" style="height: 400px; width: 100%"></div>

<button class="button is-info" @click="invalidateSize()">invalidateSize</button>

</div>

</b-tab-item>

<b-tab-item label="Tab 2">

<div class="section">

Tab 2

<div class="map" ref="map2" style="height: 400px; width: 100%"></div>

</div>

</b-tab-item>

</b-tabs>

</div>

</div>

<script src="https://unpkg.com/vue@2"></script>

<script src="https://unpkg.com/buefy@0.7/dist/buefy.min.js"></script>

<script src="https://unpkg.com/leaflet@1.3.4/dist/leaflet.js"></script>


Related Topics



Leave a reply



Submit