Skip to content
Advertisement

Multiple tile issue google maps API v3 JS

I have a map where user from an admin panel can add many tiled layers to the map. Those layers will be added to the map in the form of loop. The user can switch the layer on and off based on their selection.

After adding the layers via the loop when I select the first layer the second layer renders but if I don’t add the layers via the loop but add them separately the layer selection works fine.

Here is my code

   <!DOCTYPE html>
    <html>

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Welcome- Land Cover Maps</title>
        <script src="https://code.jquery.com/jquery-3.5.1.min.js"
            integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
        <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>

        <style>
            #over_map {
                display: flex;
                flex-direction: column;
                position: absolute;
                top: 20vh;
                left: 10px;
                z-index: 99;
            }

            body {
                display: flex;
                flex-direction: column;
                min-height: 100vh;
            }

            .navbar {
                flex-grow: 0;
            }

            #map {
                flex-grow: 1;
            }


            .gm-ui-hover-effect {
                width: 45px !important;
                height: 45px !important;
            }

            .gm-ui-hover-effect>img {
                width: 30px !important;
                height: 30px !important;
            }

            .gm-style-iw {
                height: 60vh;
            }

            .gm-style-iw-c {
                height: 60vh;
            }

            .gm-style-iw {
                max-height: 50vh !important;
                overflow-y: auto;
                display: flex;
            }

            .sidebar {
                height: 50%;
                /* 100% Full-height */
                width: 0;
                /* 0 width - change this with JavaScript */
                position: fixed;
                /* Stay in place */
                z-index: 1;
                /* Stay on top */
                bottom: 0;
                left: 0;
                background-color: white;
                /* Black*/
                overflow-x: hidden;
                /* Disable horizontal scroll */
                padding-top: 90px;
                /* Place content 60px from the top */
                transition: 0.5s;
                /* 0.5 second transition effect to slide in the sidebar */

            }

            /* The sidebar links */
            .sidebar a {
                padding: 8px 8px 8px 32px;
                text-decoration: none;
                font-size: 15px;
                color: grey;
                display: block;
                transition: 0.3s;
            }

            /* When you mouse over the navigation links, change their color */
            .sidebar a:hover {
                color: #f1f1f1;
            }

            /* Position and style the close button (top right corner) */
            .sidebar .closebtn {
                position: absolute;
                top: 0;
                right: 25px;
                font-size: 36px;
                margin-left: 50px;
            }

            /* The button used to open the sidebar */
            .openbtn {
                top: 30px;
                font-size: 20px;
                cursor: pointer;
                background-color: #111;
                color: white;
                padding: 10px 15px;
                border: none;
            }

            .openbtn:hover {
                background-color: #444;
            }

            /* Style page content - use this if you want to push the page content to the right when you open the side navigation */
            #main {
                transition: margin-left .5s;
                /* If you want a transition effect */
                padding: 20px;
            }

            /* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
            @media screen and (max-height: 450px) {
                .sidebar {
                    padding-top: 15px;
                }

                .sidebar a {
                    font-size: 18px;
                }
            }
        </style>

    </head>

    <body>
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
            <a class="navbar-brand" href="#">
                Try Test

            </a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown"
                aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNavDropdown">
                <ul class="navbar-nav list-inline mx-auto justify-content-center">


                    <li class="nav-item dropdown">
                        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button"
                            data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                            Layers
                        </a>
                        <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                            <a href="#" class="btn  btn-secondary" id="stamen" onclick="switchimagery('watercolor',0)"
                                style="padding:10px; width:90%;margin:10px;">Water Color</a>
                            <a href="#" class="btn  btn-secondary" id="landcover2020" onclick="switchimagery('toner',1)"
                                style=" padding:10px; width:90%;margin:10px;">Background Toner</a>

                        </div>
                    </li>
                </ul>
            </div>

        </nav>


        <div id="map"></div>

        <script>
            var TILE_URL = 'http://c.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg';
            var TILE_URL1 = 'http://tile.stamen.com/toner-background/{z}/{x}/{y}.png';
            var layers = [{
                "tile_id": "3",
                "tile_name": "stamen_watercolor",
                "tile_alias": "watercolor",
                "tile_location": "http://c.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg",
                "tile_status": "active",
                "min_zoom": "1",
                "max_zoom": "11"
            }, {
                "tile_id": "2",
                "tile_name": "toner_background",
                "tile_alias": "toner",
                "tile_location": "http://tile.stamen.com/toner-background/{z}/{x}/{y}.png",
                "tile_status": "active",
                "min_zoom": "1",
                "max_zoom": "11"
            }];
            var layerarray = [],
                imagerylayer = [],
                imagerylayerid = [];

            var map;
            var mapEl;
            var layer;
            var layerID = 'stamen';

            window.initMap = function () {
                // Select the element with id="map".
                mapEl = document.querySelector('#map');

                // Create a new map.
                map = new google.maps.Map(mapEl, {
                    center: new google.maps.LatLng(39.8282, -98.5795),
                    zoom: 4
                });
                console.log({
                    layers
                });
                for (var i = 0; i < 2; i++) {

                    var path = "";
                    path = layers[i].tile_location;

                    var tname = layers[i].tile_alias;
                    var min = layers[i].min_zoom;
                    var max = layers[i].max_zoom;
                    var tempimagelayer = "";

                    console.log(path);
                    

                    imagerylayer[i] = new google.maps.ImageMapType({
                        name: tname,
                        getTileUrl: function (coord, zoom) {

                            var url = path
                                .replace('{x}', coord.x)
                                .replace('{y}', coord.y)
                                .replace('{z}', zoom);


                            return url;
                        },
                        tileSize: new google.maps.Size(256, 256),
                        minZoom: min,
                        maxZoom: max
                    });
                    if(i==0)
                    {
                      map.overlayMapTypes.push(imagerylayer[i]);
                    }
                }
            };

            function switchimagery(imgid, id) {
                console.log("Imgid:"+imgid+"  id:"+id);
                console.log(imagerylayer[id].name, imagerylayer[id].getTileUrl);
                map.overlayMapTypes.clear();

                map.overlayMapTypes.push(imagerylayer[id]);

                for (var j = 0; j < imagerylayer.length; j++) {
                    var buttonname = "#" + imagerylayer[j].name;
                    if (imagerylayer[j].name == imgid) {


                        $(buttonname).addClass("btn-success");
                        $(buttonname).removeClass("btn-secondary");

                    } else {
                        $(buttonname).removeClass("btn-success");
                        $(buttonname).addClass("btn-secondary");
                    }
                    //map.overlayMapTypes.pop(imagerylayer[i]);
                }
            }
        </script>

        <!-- NOTE: The 'key' parameter should be replaced with your Google Maps API Key. -->
        <script src="https://maps.googleapis.com/maps/api/js?callback=initMap&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk">
        </script>

    </body>

    </html>

Advertisement

Answer

To make your loop work (with modern browsers), use the let keyword to define the path:

for (var i = 0; i < 2; i++) {
    let path = layers[i].tile_location;
    // ...

watercolor layer:

watercolor layer

toner layer:

toner layer

working live example

complete code:

<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Welcome- Land Cover Maps</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"
        integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>

    <style>
        #over_map {
            display: flex;
            flex-direction: column;
            position: absolute;
            top: 20vh;
            left: 10px;
            z-index: 99;
        }

        body {
            display: flex;
            flex-direction: column;
            min-height: 100vh;
        }

        .navbar {
            flex-grow: 0;
        }

        #map {
            flex-grow: 1;
        }


        .gm-ui-hover-effect {
            width: 45px !important;
            height: 45px !important;
        }

        .gm-ui-hover-effect>img {
            width: 30px !important;
            height: 30px !important;
        }

        .gm-style-iw {
            height: 60vh;
        }

        .gm-style-iw-c {
            height: 60vh;
        }

        .gm-style-iw {
            max-height: 50vh !important;
            overflow-y: auto;
            display: flex;
        }

        .sidebar {
            height: 50%;
            /* 100% Full-height */
            width: 0;
            /* 0 width - change this with JavaScript */
            position: fixed;
            /* Stay in place */
            z-index: 1;
            /* Stay on top */
            bottom: 0;
            left: 0;
            background-color: white;
            /* Black*/
            overflow-x: hidden;
            /* Disable horizontal scroll */
            padding-top: 90px;
            /* Place content 60px from the top */
            transition: 0.5s;
            /* 0.5 second transition effect to slide in the sidebar */

        }

        /* The sidebar links */
        .sidebar a {
            padding: 8px 8px 8px 32px;
            text-decoration: none;
            font-size: 15px;
            color: grey;
            display: block;
            transition: 0.3s;
        }

        /* When you mouse over the navigation links, change their color */
        .sidebar a:hover {
            color: #f1f1f1;
        }

        /* Position and style the close button (top right corner) */
        .sidebar .closebtn {
            position: absolute;
            top: 0;
            right: 25px;
            font-size: 36px;
            margin-left: 50px;
        }

        /* The button used to open the sidebar */
        .openbtn {
            top: 30px;
            font-size: 20px;
            cursor: pointer;
            background-color: #111;
            color: white;
            padding: 10px 15px;
            border: none;
        }

        .openbtn:hover {
            background-color: #444;
        }

        /* Style page content - use this if you want to push the page content to the right when you open the side navigation */
        #main {
            transition: margin-left .5s;
            /* If you want a transition effect */
            padding: 20px;
        }

        /* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
        @media screen and (max-height: 450px) {
            .sidebar {
                padding-top: 15px;
            }

            .sidebar a {
                font-size: 18px;
            }
        }
    </style>

</head>

<body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <a class="navbar-brand" href="#">
            Try Test

        </a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown"
            aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNavDropdown">
            <ul class="navbar-nav list-inline mx-auto justify-content-center">


                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button"
                        data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        Layers
                    </a>
                    <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                        <a href="#" class="btn  btn-secondary" id="stamen" onclick="switchimagery('watercolor',0)"
                            style="padding:10px; width:90%;margin:10px;">Water Color</a>
                        <a href="#" class="btn  btn-secondary" id="landcover2020" onclick="switchimagery('toner',1)"
                            style=" padding:10px; width:90%;margin:10px;">Background Toner</a>

                    </div>
                </li>
            </ul>
        </div>

    </nav>


    <div id="map"></div>

    <script>
        var TILE_URL = 'http://c.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg';
        var TILE_URL1 = 'http://tile.stamen.com/toner-background/{z}/{x}/{y}.png';
        var layers = [{
            "tile_id": "3",
            "tile_name": "stamen_watercolor",
            "tile_alias": "watercolor",
            "tile_location": "http://c.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg",
            "tile_status": "active",
            "min_zoom": "1",
            "max_zoom": "11"
        }, {
            "tile_id": "2",
            "tile_name": "toner_background",
            "tile_alias": "toner",
            "tile_location": "http://tile.stamen.com/toner-background/{z}/{x}/{y}.png",
            "tile_status": "active",
            "min_zoom": "1",
            "max_zoom": "11"
        }];
        var layerarray = [],
            imagerylayer = [],
            imagerylayerid = [];

        var map;
        var mapEl;
        var layer;
        var layerID = 'stamen';

        window.initMap = function () {
            // Select the element with id="map".
            mapEl = document.querySelector('#map');

            // Create a new map.
            map = new google.maps.Map(mapEl, {
                center: new google.maps.LatLng(39.8282, -98.5795),
                zoom: 4
            });
            console.log({
                layers
            });
            for (var i = 0; i < 2; i++) {

                let path = layers[i].tile_location;

                var tname = layers[i].tile_alias;
                var min = layers[i].min_zoom;
                var max = layers[i].max_zoom;
                var tempimagelayer = "";
                console.log(path);
                imagerylayer[i] = new google.maps.ImageMapType({
                    name: tname,
                    getTileUrl: function (coord, zoom) {

                        var url = path
                            .replace('{x}', coord.x)
                            .replace('{y}', coord.y)
                            .replace('{z}', zoom);
                        console.log(url);

                        return url;
                    },
                    tileSize: new google.maps.Size(256, 256),
                    minZoom: min,
                    maxZoom: max,
            opacity: 0.5
                });
                if(i==0)
                {
                  map.overlayMapTypes.push(imagerylayer[i]);
                }
            }
        };

        function switchimagery(imgid, id) {
            console.log("Imgid:"+imgid+"  id:"+id);
            console.log(imagerylayer[id].name, imagerylayer[id].getTileUrl);
            map.overlayMapTypes.clear();

            map.overlayMapTypes.push(imagerylayer[id]);

            for (var j = 0; j < imagerylayer.length; j++) {
                var buttonname = "#" + imagerylayer[j].name;
                if (imagerylayer[j].name == imgid) {


                    $(buttonname).addClass("btn-success");
                    $(buttonname).removeClass("btn-secondary");

                } else {
                    $(buttonname).removeClass("btn-success");
                    $(buttonname).addClass("btn-secondary");
                }
                //map.overlayMapTypes.pop(imagerylayer[i]);
            }
        }
    </script>

    <!-- NOTE: The 'key' parameter should be replaced with your Google Maps API Key. -->
    <script src="https://maps.googleapis.com/maps/api/js?callback=initMap&key=API_KEY">
    </script>

</body>

</html>
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement