Nostromo
Nostromo

Reputation: 1264

How to show multiple maps on one html page

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

Answers (1)

Łukasz Blaszyński
Łukasz Blaszyński

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

Related Questions