Переключатели зума управления в листовке? - PullRequest
1 голос
/ 02 апреля 2020

Я пытаюсь добавить что-то (например, элемент управления миникарты), которое позволит пользователю осознать, что более глубокие уровни масштабирования имеют совершенно другой набор маркеров.

Я также хотел бы предоставить пользователю легкий доступ к этим уровням глубокого увеличения, ie, чтобы добраться туда без необходимости go через все промежуточные уровни. Например, для того, чтобы щелкнуть мышью по этому элементу управления, похожему на мини-карту, и сразу перейти к целевому уровню масштабирования.

В данный момент я сделал элемент управления мини-карты, показывающий высокий уровень масштабирования вместе с некоторыми маркерами (синий circleMarkers). Это нормально, но я хотел бы добавить «что-то» (на той же миникарте, другой элемент управления с переключателями, или миниатюры, чего я не знаю ...), которое было бы указано c для более глубокие уровни масштабирования, когда контент (маркеры) совершенно новый. Обратите внимание, что главная карта заполнена синими маркерами (по всему миру), когда уровень масштабирования варьируется от 0 до 8, в противном случае отображаются красные маркеры (только для большей части Европы).

Есть идеи, пожалуйста?

Я также хотел бы добавить, что на практике маркеры высокого уровня (синие точки здесь) - около 60000, но более детальная информация (красные точки) - пара миллионов! По этой причине я не могу загрузить все красные точки в одну go, но я загружаю некоторую часть моих данных, когда масштабирование достаточно велико и браузер может справиться с громкостью. В моем реальном коде (не включенном в этот пример) я также установил дополнительный фильтр, который разрезает данные (красные маркеры здесь) на основе активного окна просмотра карты.

<!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>

1 Ответ

0 голосов
/ 02 апреля 2020

Поскольку вы добавили тег mapbox, я полагаю, что вам также интересно услышать предложения по использованию технологий mapbox.

Подход только OSM:

Похоже, проблема в том, что слой красной точки с миникартой. Я изменил вашу миникарту, чтобы показывать слой красной точки вместо слоя с синей точкой, и снизил уровень масштабирования. Вы можете добавить это в качестве второй миникарты на карту. Таким образом, у вас будет миникарта с красными точками и одна с высоким уровнем масштабирования с синими точками.

Почему вы хотите сделать миникарту кликабельной? Если вы сделаете это, вы не сможете прокрутить его. Вы можете добавить другой элемент управления. При событии onClick вы можете установить масштаб карты на заданный уровень c, используя map.setZoom(<ZoomLevel>);

<!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) сделать определенные слои видимыми только в указанных диапазонах увеличения c. Вам не нужно заботиться об этом в своем коде JS. Изменяя масштаб на вашей мини-карте, вы можете увидеть красные точки при низком увеличении. (Увеличенной в)

...