[GIS] Comparing several Overlay Layers with Base Layer in Leaflet

leafletswipe

I write web app for comparing several Overlay Layers (in example OSM tile layers) with Base Layer (in example Bing Aerial layer) in Leaflet.

It's work in 'first loaded' level zoom. But when I 'zoomIn' or 'zoomOut' I receive exception and don't possible move map.

Example: http://spatialhast.github.io/leaflet.swipe.html (swipe tool don't visible in IE)

Code example:

    <script>
    var BingLayer = L.TileLayer.extend({
        getTileUrl: function(tilePoint) {
            this._adjustTilePoint(tilePoint);
            return L.Util.template(this._url, {
                s: this._getSubdomain(tilePoint),
                q: this._quadKey(tilePoint.x, tilePoint.y, this._getZoomForUrl())
            });
        },
        _quadKey: function(x, y, z) {
            var quadKey = [];
            for (var i = z; i > 0; i--) {
                var digit = '0';
                var mask = 1 << (i - 1);
                if ((x & mask) != 0) {
                    digit++;
                }
                if ((y & mask) != 0) {
                    digit++;
                    digit++;
                }
                quadKey.push(digit);
            }
            return quadKey.join('');
        }
    });;

    var testGeom = {
        "type": "Polygon",
        "coordinates": [
            [
                [5.9559111595, 45.8179931641],
                [5.9559111595, 47.808380127],
                [10.4920501709, 47.808380127],
                [10.4920501709, 45.8179931641],
                [5.9559111595, 45.8179931641]
            ]
        ]
    };

    var latLngGeom = [],
        r, k;
    for (r = 0; r < testGeom.coordinates.length; r++) {
        latLngGeom[r] = [];
        for (k = 0; k < testGeom.coordinates[r].length; k++) {
            latLngGeom[r].push(new L.LatLng(testGeom.coordinates[r][k][1], testGeom.coordinates[r][k][0]));
        }
    };

    var layerBA = new BingLayer('http://t{s}.tiles.virtualearth.net/tiles/a{q}.jpeg?g=2732', {
        maxZoom: 19,
        subdomains: ['0', '1', '2', '3', '4'],
        attribution: '&copy; <a href="http://bing.com/maps">Bing Maps</a>'
    });

    var layer01 = new L.TileLayer.boundaryCanvas('http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
        boundary: latLngGeom,
        attribution: 'Tiles &copy; <a href="http://hot.openstreetmap.org/">Humanitarian OpenStreetMap Team</a>; Map data &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    });

    var layer02 = new L.TileLayer.boundaryCanvas('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        boundary: latLngGeom,
        attribution: '&copy; Map Data <a href="https://openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    });

    var layer03 = new L.TileLayer.boundaryCanvas("http://{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png", {
        subdomains: ["otile1", "otile2", "otile3", "otile4"],
        boundary: latLngGeom,
        attribution: '&copy; Tiles courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a>. &copy; Map data <a href="http://www.openstreetmap.org/" target="_blank">OpenStreetMap</a> contributors'
    });

    var layer04 = new L.TileLayer.boundaryCanvas('http://{s}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png', {
        boundary: latLngGeom,
        attribution: '&copy; <a href="http://www.opencyclemap.org">OpenCycleMap</a>, &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
    });

    var layer05 = new L.TileLayer.boundaryCanvas('http://{s}.hikebike.gpsies.com/{z}/{x}/{y}.png', {
        boundary: latLngGeom,
        attribution: '&copy; <a href="http://hikebikemap.org/">HikeBikeMap</a>, &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
    });

    var map = L.map('map', {
        layers: [layerBA],
        zoom: 8,
        minZoom: 5,
        maxZoom: 19,
        center: [47, 8]
    });


    $('.button').click(function() {
        $('.button').removeClass('selected');
        $(this).addClass('selected');

        if ($(this).attr('id') === "a1") {
            var overlay = layer01.addTo(map);

            var range = document.getElementById('range');

            function clip() {
                var nw = map.containerPointToLayerPoint([0, 0]),
                    se = map.containerPointToLayerPoint(map.getSize()),
                    clipX = nw.x + (se.x - nw.x) * range.value;
                overlay.getContainer().style.clip = 'rect(' + [nw.y, clipX, se.y, nw.x].join('px,') + 'px)';
            }
            range['oninput' in range ? 'oninput' : 'onchange'] = clip;
            map.on('move', clip);

        } else {
            map.removeLayer(layer01);
        };

        if ($(this).attr('id') === "a2") {
            var overlay = layer02.addTo(map);

            var range = document.getElementById('range');

            function clip() {
                var nw = map.containerPointToLayerPoint([0, 0]),
                    se = map.containerPointToLayerPoint(map.getSize()),
                    clipX = nw.x + (se.x - nw.x) * range.value;
                overlay.getContainer().style.clip = 'rect(' + [nw.y, clipX, se.y, nw.x].join('px,') + 'px)';
            }

            range['oninput' in range ? 'oninput' : 'onchange'] = clip;
            map.on('move', clip);

        } else {
            map.removeLayer(layer02);
        };

        if ($(this).attr('id') === "a3") {
            var overlay = layer03.addTo(map);

            var range = document.getElementById('range');

            function clip() {
                var nw = map.containerPointToLayerPoint([0, 0]),
                    se = map.containerPointToLayerPoint(map.getSize()),
                    clipX = nw.x + (se.x - nw.x) * range.value;
                overlay.getContainer().style.clip = 'rect(' + [nw.y, clipX, se.y, nw.x].join('px,') + 'px)';
            }
            range['oninput' in range ? 'oninput' : 'onchange'] = clip;
            map.on('move', clip);

        } else {
            map.removeLayer(layer03);
        };

        if ($(this).attr('id') === "a4") {
            var overlay = layer04.addTo(map);

            var range = document.getElementById('range');

            function clip() {
                var nw = map.containerPointToLayerPoint([0, 0]),
                    se = map.containerPointToLayerPoint(map.getSize()),
                    clipX = nw.x + (se.x - nw.x) * range.value;
                overlay.getContainer().style.clip = 'rect(' + [nw.y, clipX, se.y, nw.x].join('px,') + 'px)';
            }
            range['oninput' in range ? 'oninput' : 'onchange'] = clip;
            map.on('move', clip);

        } else {
            map.removeLayer(layer04);
        };

        if ($(this).attr('id') === "a5") {
            var overlay = layer05.addTo(map);

            var range = document.getElementById('range');

            function clip() {
                var nw = map.containerPointToLayerPoint([0, 0]),
                    se = map.containerPointToLayerPoint(map.getSize()),
                    clipX = nw.x + (se.x - nw.x) * range.value;
                overlay.getContainer().style.clip = 'rect(' + [nw.y, clipX, se.y, nw.x].join('px,') + 'px)';
            }
            range['oninput' in range ? 'oninput' : 'onchange'] = clip;
            map.on('move', clip);

        } else {
            map.removeLayer(layer05);
        };

        //console.log(map.hasLayer(layer02));
        //console.log($(this).attr('id'));

    });

    /*      
            var overlay = layer01.addTo(map);
            var range = document.getElementById('range');

            function clip() {
              var nw = map.containerPointToLayerPoint([0, 0]),
                  se = map.containerPointToLayerPoint(map.getSize()),
                  clipX = nw.x + (se.x - nw.x) * range.value;
              overlay.getContainer().style.clip = 'rect(' + [nw.y, clipX, se.y, nw.x].join('px,') + 'px)';
            }

            range['oninput' in range ? 'oninput' : 'onchange'] = clip;
            map.on('move', clip);

    */

    map.setView([47, 8.1], 8);
</script>

How do I do it?

Best Answer

I find solution, code below (or live example http://spatialhast.github.io/leaflet.swipe.html):

    <script>
    var BingLayer = L.TileLayer.extend({
        getTileUrl: function(tilePoint) {
            this._adjustTilePoint(tilePoint);
            return L.Util.template(this._url, {
                s: this._getSubdomain(tilePoint),
                q: this._quadKey(tilePoint.x, tilePoint.y, this._getZoomForUrl())
            });
        },
        _quadKey: function(x, y, z) {
            var quadKey = [];
            for (var i = z; i > 0; i--) {
                var digit = '0';
                var mask = 1 << (i - 1);
                if ((x & mask) != 0) {
                    digit++;
                }
                if ((y & mask) != 0) {
                    digit++;
                    digit++;
                }
                quadKey.push(digit);
            }
            return quadKey.join('');
        }
    });;

    var testGeom = {
        "type": "Polygon",
        "coordinates": [
            [
                [5.9559111595, 45.8179931641],
                [5.9559111595, 47.808380127],
                [10.4920501709, 47.808380127],
                [10.4920501709, 45.8179931641],
                [5.9559111595, 45.8179931641]
            ]
        ]
    };

    var latLngGeom = [],
        r, k;
    for (r = 0; r < testGeom.coordinates.length; r++) {
        latLngGeom[r] = [];
        for (k = 0; k < testGeom.coordinates[r].length; k++) {
            latLngGeom[r].push(new L.LatLng(testGeom.coordinates[r][k][1], testGeom.coordinates[r][k][0]));
        }
    };

    var layerBA = new BingLayer('http://t{s}.tiles.virtualearth.net/tiles/a{q}.jpeg?g=2732', {
        maxZoom: 19,
        subdomains: ['0', '1', '2', '3', '4'],
        attribution: '&copy; <a href="http://bing.com/maps">Bing Maps</a>'
    });

    var layer01 = new L.TileLayer.boundaryCanvas('http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
        boundary: latLngGeom,
        attribution: 'Tiles &copy; <a href="http://hot.openstreetmap.org/">Humanitarian OpenStreetMap Team</a>; Map data &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    });

    var layer02 = new L.TileLayer.boundaryCanvas('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        boundary: latLngGeom,
        attribution: '&copy; Map Data <a href="https://openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    });

    var layer03 = new L.TileLayer.boundaryCanvas("http://{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png", {
        subdomains: ["otile1", "otile2", "otile3", "otile4"],
        boundary: latLngGeom,
        attribution: '&copy; Tiles courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a>. &copy; Map data <a href="http://www.openstreetmap.org/" target="_blank">OpenStreetMap</a> contributors'
    });

    var layer04 = new L.TileLayer.boundaryCanvas('http://{s}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png', {
        boundary: latLngGeom,
        attribution: '&copy; <a href="http://www.opencyclemap.org">OpenCycleMap</a>, &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
    });

    var layer05 = new L.TileLayer.boundaryCanvas('http://{s}.hikebike.gpsies.com/{z}/{x}/{y}.png', {
        boundary: latLngGeom,
        attribution: '&copy; <a href="http://hikebikemap.org/">HikeBikeMap</a>, &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
    });

    var map = L.map('map', {
        layers: [layerBA],
        zoom: 8,
        minZoom: 5,
        maxZoom: 19,
        center: [47, 8]
    });

    var overlay = layer01.addTo(map);

    $('.button').click(function() {
        $('.button').removeClass('selected');
        $(this).addClass('selected');
        if ($(this).attr('id') === "a1") {
            overlay = layer01.addTo(map);
        } else {
            map.removeLayer(layer01);
        };
        if ($(this).attr('id') === "a2") {
            overlay = layer02.addTo(map);
        } else {
            map.removeLayer(layer02);
        };
        if ($(this).attr('id') === "a3") {
            overlay = layer03.addTo(map);
        } else {
            map.removeLayer(layer03);
        };
        if ($(this).attr('id') === "a4") {
            overlay = layer04.addTo(map);
        } else {
            map.removeLayer(layer04);
        };
        if ($(this).attr('id') === "a5") {
            overlay = layer05.addTo(map);
        } else {
            map.removeLayer(layer05);
        };
    });


    var range = document.getElementById('range');

    function clip() {
        var nw = map.containerPointToLayerPoint([0, 0]),
            se = map.containerPointToLayerPoint(map.getSize()),
            clipX = nw.x + (se.x - nw.x) * range.value;
        overlay.getContainer().style.clip = 'rect(' + [nw.y, clipX, se.y, nw.x].join('px,') + 'px)';
    }
    range['oninput' in range ? 'oninput' : 'onchange'] = clip;
    map.on('move', clip);

    map.setView([47, 8.1], 8);
</script>