Reputation: 1264
I'm quite new to html, css, javascript and leaflet.
I try to create a html file which has multiple tabs, and on every tab I like to show a different map (left side) with information to the things the map is showing (right side).
I found this link on how to do the tab part and I already have a working example on the map part, but with only one map on the html file.
Now I tried to combine these two things, but only one map is working properly (the first one), the other maps only show gray and maybe a tiny piece of map in the upper left corner. But even when I try to pan the "broken" maps only parts of the tiles are shown.
Can someone please give me a hint on how to do that? Is it even possible to have multiple maps on one html file with leaflet?
Here's my html file so far, including html, css and javascript.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin=""/>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA==" crossorigin=""></script>
<style>
/* Set height of body and the document to 100% to enable "full page tabs" */
body, html {
height: 100%;
margin: 0;
font-family: sans-serif;
}
/* Style tab links */
.tablink {
background-color: #9f9f9f;
color: black;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 5px;
font-size: 16px;
width: 33.33%;
}
.tablink:hover {
background-color: #7f7f7f;
}
/* Style the tab content (and add height:100% for full page content) */
.tabcontent {
color: black;
background-color: white;
display: none;
padding: 15px 5px;
height: 95%;
}
.map {
float: left;
width: 34.8%;
height: 100%;
border-radius: 5px 5px 0px 0px;
border-width: 1px;
border-style: dotted;
border-color: #000000;
}
</style>
</head>
<body>
<button class="tablink" onclick="openPage('Europe', this)" id="defaultOpen">Europe</button>
<button class="tablink" onclick="openPage('Asia', this)">Asia</button>
<button class="tablink" onclick="openPage('Africa', this)">Africa</button>
<div id="Europe" class="tabcontent">
<div id="mapEurope" class="map"></div>
</div>
<div id="Asia" class="tabcontent">
<div id="mapAsia" class="map"></div>
</div>
<div id="Africa" class="tabcontent">
<div id="mapAfrica" class="map"></div>
</div>
<script>
function openPage(pageName, elmnt) {
// Hide all elements with class="tabcontent" by default */
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Remove the background color of all tablinks/buttons
tablinks = document.getElementsByClassName("tablink");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].style.backgroundColor = "";
}
// Show the specific tab content
document.getElementById(pageName).style.display = "block";
// Add the specific color to the button used to open the tab content
elmnt.style.backgroundColor = "#ffffff";
}
// Get the element with id="defaultOpen" and click on it
document.getElementById("defaultOpen").click();
//Create maps
var centerLatEurope = 55.0;
var centerLngEurope = 18.0;
var initialZoomEurope = 4;
var mapEurope = L.map('mapEurope', {
center: [centerLatEurope, centerLngEurope],
zoom: initialZoomEurope
});
//set one map tiles source
googleStreetsEurope = L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}', {
attribution: '<a href="https://www.google.com/maps">Google Maps</a>',
maxZoom: 20,
subdomains:['mt0','mt1','mt2','mt3']
});
googleStreetsEurope.addTo(mapEurope);
var centerLatAsia = 49.0;
var centerLngAsia = 88.0;
var initialZoomAsia = 2;
var mapAsia = L.map('mapAsia', {
center: [centerLatAsia, centerLngAsia],
zoom: initialZoomAsia
});
//set one map tiles source
googleStreetsAsia = L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}', {
attribution: '<a href="https://www.google.com/maps">Google Maps</a>',
maxZoom: 20,
subdomains:['mt0','mt1','mt2','mt3']
});
googleStreetsAsia.addTo(mapAsia);
var centerLatAfrica = 0.0;
var centerLngAfrica = 18.0;
var initialZoomAfrica = 4;
var mapAfrica = L.map('mapAfrica', {
center: [centerLatAfrica, centerLngAfrica],
zoom: initialZoomAfrica
});
//set one map tiles source
googleStreetsAfrica = L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}', {
attribution: '<a href="https://www.google.com/maps">Google Maps</a>',
maxZoom: 20,
subdomains:['mt0','mt1','mt2','mt3']
});
googleStreetsAfrica.addTo(mapAfrica);
</script>
</body>
</html>
I know that I can do the maps with less variables using arrays, but right now I'm only interested in getting these multiple maps to work. I care about the prettiness of the code later.
Upvotes: 3
Views: 2234
Reputation: 1565
There is workaround to invalidateSize for maps. You can add proper method when changing tab:
function openPage(pageName, elmnt) {
...
setTimeout(function(){
mapAsia.invalidateSize();
mapAfrica.invalidateSize();
}, 0);
}
With this setTimeout your map will be refreshed after each tab change, of course yo can make it more inteligent to refresh only needed map based on clicked tab and not all of them. updated fiddle: https://jsfiddle.net/kev7m4d3/1/
Keep in mind this a a workaround and probably there is another solution for that.
invalidateSize( animate) - Checks if the map container size changed and updates the map if so — call it after you've changed the map size dynamically, also animating pan by default.
This is probably needed bacasue when using tab map is hidden an cannot correctly calculate own size, the other solution may be for example initialize map after clicking proper tab and each time map will be initialized when tab and proper space for map will be visible.
Upvotes: 5