【问题标题】:Zoom switching controls in leaflet?传单中的缩放切换控件?
【发布时间】:2020-07-13 21:09:57
【问题描述】:

我正在尝试添加一些东西(可能是小地图控件),让用户意识到更深的缩放级别具有完全不同的标记集。

我还想为用户提供对这些深度缩放级别的轻松访问,即无需通过中间的所有级别即可到达那里。因此,例如单击“类似小地图”的控件并直接跳转到目标缩放级别。

我目前所做的是一个小地图控件,显示高缩放级别以及一些标记(蓝色圆圈标记)。这很好,但我现在想要的是添加“一些东西”(在同一个小地图上??另一个带有单选按钮或缩略图的控件??我真的不知道......)这将特定于更深的缩放级别内容(标记)是全新的。请注意,当缩放级别在 0 到 8 之间变化时,主地图会填充蓝色标记(遍及整个世界),否则会呈现红色标记(仅限欧洲大部分地区)。

有什么想法吗?

我还想补充一点,在实践中,高级标记(此处为蓝点)约为 60000,但更精细的信息(红点)为几百万!这就是我不能一次性加载所有红点的原因,但是当缩放足够深并且浏览器可以处理音量时,我会加载一些数据片段。在我的实际代码(未包含在此示例中)中,我还放置了一个额外的过滤器,它根据地图的活动查看窗口对数据(此处为红色标记)进行切片。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <!--jquery -->
    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>

    <!--d3 -->
    <script src='https://d3js.org/d3.v4.min.js'></script>

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

    <!-- minimap -->
    <link rel="stylesheet" href='https://cdnjs.cloudflare.com/ajax/libs/leaflet-minimap/3.6.1/Control.MiniMap.min.css'/>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/leaflet-minimap/3.6.1/Control.MiniMap.min.js'></script>

    <!-- clone layer -->
    <script src='https://cdn.jsdelivr.net/npm/leaflet-clonelayer@1.0.7/index.min.js'></script>

    <style>
        body {
            padding: 0;
            margin: 0;
        }

        html, body, #map {
            height: 100%;
        }

    </style>

</head>
<body>

<div id="map"></div>
<script>
    function make_dots(color, N) {
        if (color === 'blue'){
            var a = -90,
                b = 180,
                c = -180,
                d = 360;
        }
        else {
            var a = -11,
                b = 38,
                c = 34,
                d = 24;
        }
        var dots = {
            type: "FeatureCollection",
            features: []
        };
        for (var i = 0; i < N; ++i) {
            var g = {
                "type": "Point",
                "coordinates": [a + b * Math.random(), c + d * Math.random()]
            };

            var p = {
                color: color,
            };

            dots.features.push({
                "geometry": g,
                "type": "Feature",
                "properties": p
            });
        }
        return dots;
    }


    function removeLayer(layer) {
        if (map.hasLayer(layer)) {
            map.removeLayer(layer);
            console.log('Layer removed')
        }
    }

    function moveend(evt) {
            console.log('moveend event fired');

            var zoomlevel = map.getZoom();
            if (zoomlevel <= 8) {
                removeLayer(red_layer);
                blue_layer.addTo(map);
            }

            if (zoomlevel > 8) {
                removeLayer(blue_layer);
                red_layer.addTo(map);
            }
    }

    blue_dots = make_dots('blue', 10000);
    red_dots = make_dots('red', 10000);
    var map = new L.Map('map');
    map.on('moveend', moveend);
    var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
    var osm = new L.TileLayer(osmUrl, {minZoom: 0, maxZoom: 18});

    var blue_renderer = L.canvas({
        padding: 0.5,
    });
    var blue_layer = L.geoJson(blue_dots, {
        pointToLayer: function (feature, latlng) {
            return new L.CircleMarker(latlng, {
                fillColor: feature.properties.color,
                color: feature.properties.color,
                renderer: blue_renderer,
            });
        }
    });

    var red_renderer = L.canvas({
        padding: 0.5,
    });
    var red_layer = L.geoJson(red_dots, {
        pointToLayer: function (feature, latlng) {
            return new L.CircleMarker(latlng, {
                fillColor: feature.properties.color,
                color: feature.properties.color,
                renderer: red_renderer,
            });
        }
    });

    map.addLayer(osm);
    map.setView(new L.LatLng(50, 1.0), 5);

    var osm2 = new L.TileLayer(osmUrl, {minZoom: 0, maxZoom: 13});
    var blue_renderer_2 = L.canvas({
        padding: 0.5,
    });
    var blue_dots2 = L.geoJson(blue_dots, {
        pointToLayer: function (feature, latlng) {
            return new L.CircleMarker(latlng, {
                radius: 2,
                fillColor: feature.properties.color,
                color: feature.properties.color,
                renderer: blue_renderer_2,
            });
        }
    });

    var layers = new L.LayerGroup([osm2, blue_dots2]);

    var miniMap = new L.Control.MiniMap(layers, {
        toggleDisplay: true,
        minimized: false,
        position: 'topright',
        zoomLevelFixed: 2,
    });
    miniMap.addTo(map);

</script>

</body>
</html>

【问题讨论】:

    标签: d3.js leaflet mapbox


    【解决方案1】:

    既然您已经添加了 mapbox 标签,我假设您也有兴趣听取使用 mapbox 技术的建议。

    仅 OSM 方法:

    看来问题在于小地图的红点图层。我已更改您的小地图以显示红点图层而不是蓝点图层,并降低了缩放级别。您可以将此作为第二张小地图添加到您的地图中。因此,您将拥有一个带有红点的小地图和一个带有蓝点的高缩放级别的小地图。

    为什么要让小地图可点击?如果这样做,您将无法在其中滚动。您可以添加不同的控件。在其 'onClick' 事件中,您可以使用 map.setZoom(&lt;ZoomLevel&gt;); 将地图缩放设置为特定级别

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    
        <!--jquery -->
        <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
    
        <!--d3 -->
        <script src='https://d3js.org/d3.v4.min.js'></script>
    
        <!-- leaflet -->
        <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css"/>
        <script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js"></script>
    
        <!-- minimap -->
        <link rel="stylesheet" href='https://cdnjs.cloudflare.com/ajax/libs/leaflet-minimap/3.6.1/Control.MiniMap.min.css'/>
        <script src='https://cdnjs.cloudflare.com/ajax/libs/leaflet-minimap/3.6.1/Control.MiniMap.min.js'></script>
    
        <!-- clone layer -->
        <script src='https://cdn.jsdelivr.net/npm/leaflet-clonelayer@1.0.7/index.min.js'></script>
    
        <style>
            body {
                padding: 0;
                margin: 0;
            }
    
            html, body, #map {
                height: 100%;
            }
    
        </style>
    
    </head>
    <body>
    
    <div id="map"></div>
    <button id="button">Re-draw circle</button>
    <script>
        function make_dots(color, N) {
            if (color === 'blue'){
                var a = -90,
                    b = 180,
                    c = -180,
                    d = 360;
            }
            else {
                var a = -11,
                    b = 38,
                    c = 34,
                    d = 24;
            }
            var dots = {
                type: "FeatureCollection",
                features: []
            };
            for (var i = 0; i < N; ++i) {
                var g = {
                    "type": "Point",
                    "coordinates": [a + b * Math.random(), c + d * Math.random()]
                };
    
                var p = {
                    color: color,
                };
    
                dots.features.push({
                    "geometry": g,
                    "type": "Feature",
                    "properties": p
                });
            }
            return dots;
        }
    
    
        function removeLayer(layer) {
            if (map.hasLayer(layer)) {
                map.removeLayer(layer);
                console.log('Layer removed')
            }
        }
    
        function moveend(evt) {
                console.log('moveend event fired');
    
                var zoomlevel = map.getZoom();
                if (zoomlevel <= 8) {
                    removeLayer(red_layer);
                    blue_layer.addTo(map);
                }
    
                if (zoomlevel > 8) {
                    removeLayer(blue_layer);
                    red_layer.addTo(map);
                }
        }
    
        blue_dots = make_dots('blue', 10000);
        red_dots = make_dots('red', 10000);
        var map = new L.Map('map');
        map.on('moveend', moveend);
        var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
        var osm = new L.TileLayer(osmUrl, {minZoom: 0, maxZoom: 18});
    
        var blue_renderer = L.canvas({
            padding: 0.5,
        });
        var blue_layer = L.geoJson(blue_dots, {
            pointToLayer: function (feature, latlng) {
                return new L.CircleMarker(latlng, {
                    fillColor: feature.properties.color,
                    color: feature.properties.color,
                    renderer: blue_renderer,
                });
            }
        });
    
        var red_renderer = L.canvas({
            padding: 0.5,
        });
        var red_layer = L.geoJson(red_dots, {
            pointToLayer: function (feature, latlng) {
                return new L.CircleMarker(latlng, {
                    fillColor: feature.properties.color,
                    color: feature.properties.color,
                    renderer: red_renderer,
                });
            }
        });
    
        map.addLayer(osm);
        map.setView(new L.LatLng(50, 1.0), 5);
    
        var osm2 = new L.TileLayer(osmUrl, {minZoom: 0, maxZoom: 13});
        var blue_renderer_2 = L.canvas({
            padding: 0.5,
        });
        var blue_dots2 = L.geoJson(blue_dots, {
            pointToLayer: function (feature, latlng) {
                return new L.CircleMarker(latlng, {
                    radius: 2,
                    fillColor: feature.properties.color,
                    color: feature.properties.color,
                    renderer: blue_renderer_2,
                });
            }
        });
    
        var layers = new L.LayerGroup([osm2, red_layer]);
    
        var miniMap = new L.Control.MiniMap(layers, {
            toggleDisplay: true,
            minimized: false,
            position: 'topright',
            zoomLevelFixed: 9,
        });
    	
        miniMap.addTo(map);
    
    </script>
    
    </body>
    </html>

    Mapbox 方法:

    另一种方法是使用 Mapbox 技术并将红点和蓝点添加到您的地图样式中。在这种方法中,您可以选择(使用 Mapbox)使某些图层仅在特定缩放范围内可见。您不必在 JS 代码中关心这一点。通过更改小地图的缩放,您可以在低缩放时看到红点。 (放大)

    【讨论】:

    • 谢谢莫里茨,我可能没有完全理解你的解决方案,我可能还没有很清楚地解释我的问题。我想让用户能够从缩放级别切换,比如说 3 到 8。当用户以 zoom=3 查看地图时,他不知道在更深的缩放级别有不同类型的信息,除非他手动经历从 3 到 8 的所有级别。如果由于某种原因没有发生这种情况,用户将不会知道级别 > 8 的额外、更精细的信息。这就是我想做的,它不一定是一个可点击的小地图,我只是不知道怎么做。
    • 好的,我明白了。我分享的代码将更改您的小地图,以缩放级别 9 显示世界并显示 red_dot 图层。同时,大地图将处于显示 blue_dot 图层的缩放级别。我建议创建一个单独的控件,如果单击它会将您的大地图设置为不同的缩放级别。如果有不清楚的地方,请告诉我!我很乐意解释:)
    猜你喜欢
    • 2016-07-21
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 1970-01-01
    相关资源
    最近更新 更多