Leaflet 0.7.7 Zoombased переключение слоев по темам

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

Мы уже пытались заставить эту работу работать несколькими способами, но без особого успеха. Используя L.Control.Layers, мы не могли сгруппировать разные слои вместе с помощью одного переключателя и переключать их в зависимости от масштабирования, поскольку элемент управления слоем, встроенный в листовку, всегда разделяет их на отдельные. Даже использование L.layerGroup для объединения нескольких переменных слоя или создание нескольких слоев в одну переменную, а затем добавление их на карту с помощью l.control.layer.

Мы также пытались использовать L.easyButton (https://github.com/CliffCloud/Leaflet.EasyButton). Это позволило нам разместить переменные под одной кнопкой и добавить внутри нее переключение слоев на основе масштабирования. Однако проблема здесь в том, что мы не можем деактивировать эту функцию после активации. В результате несколько из них активны в одной точке и перекрывают друг друга.

Если возможно, мы хотели бы знать, следует ли нам использовать другой подход или может ли работать функция управления листовкой или использование easyButton и как?

Это пример кода для одной из кнопок, которая может появляться несколько раз, но отображать другую тему:

        L.easyButton( '<span class="star">&starf;</span>', function (polygon) {

                    var ejerlav_polygon = new L.tileLayer.betterWms(
                    'http://[IP]:[PORT]/geoserver/prlayer/wms', {
                    layers: 'prlayer:ejerlav',
                    transparent: true,
                    styles: 'polygon',          
                    format: 'image/png'});

                    var municipality_polygon = new L.tileLayer.betterWms(
                    'http://[IP]:[PORT]/geoserver/prlayer/wms', {
                    layers: 'prlayer:municipality',
                    transparent: true,
                    styles: 'polygon',
                    format: 'image/png'});                      

                    map.on("zoomend", function() {
                        if (map.getZoom() <= 10 && map.getZoom() >= 2) {
                            map.addLayer(municipality_polygon);
                        } else if (map.getZoom() > 10 || map.getZoom() < 2) {
                            map.removeLayer(municipality_polygon);
                        }
                        });

                            map.on("zoomend", function() {
                        if (map.getZoom() <= 11 && map.getZoom() >= 11) {
                            map.addLayer(ejerlav_polygon);

                        } else if (map.getZoom() > 11 || map.getZoom() < 11) {
                            map.removeLayer(ejerlav_polygon);
                        }
                        });

        }).addTo(map);

person Community    schedule 19.12.2015    source источник


Ответы (1)


Если я правильно понимаю, вы хотели бы дать пользователю возможность переключаться между «темами» (своего рода группа слоев, которые переключаются в зависимости от текущего уровня масштабирования карты), возможно, используя Leaflet Layers Control?

А что касается переключателя, основанного на масштабировании карты, вы не можете просто изменить URL-адрес шаблона мозаичного слоя, потому что вы используете какой-то WMS?

Что касается последней функции (переключение слоев в группе / теме на основе масштаба карты), «простым» решением было бы создать свой собственный тип слоя, который будет прослушивать событие карты "zoomend" и соответственно изменять Tile Layer WMS.

L.LayerSwitchByZoom = L.Class.extend({
  initialize: function (layersArray) {
    var self = this;

    this._layersByZoom = layersArray;
    this._maxZoom = layersArray.length - 1;

    this._switchByZoomReferenced = function () {
      self._switchByZoom();
    };
  },

  onAdd: function (map) {
    this._map = map;

    map.on("zoomend", this._switchByZoomReferenced);
    this._switchByZoom();
  },

  onRemove: function (map) {
    map.off("zoomend", this._switchByZoomReferenced);
    this._removeCurrentLayer();

    this._map = null;
  },

  addTo: function (map) {
    map.addLayer(this);
    return this;
  },

  _switchByZoom: function () {
    var map = this._map,
        z = Math.min(map.getZoom(), this._maxZoom);

    this._removeCurrentLayer();
    this._currentLayer = this._layersByZoom[z];
    map.addLayer(this._currentLayer);
  },

  _removeCurrentLayer: function () {
    if (this._currentLayer) {
      map.removeLayer(this._currentLayer);
    }
  }
});

Затем вы создадите экземпляр этой «темы» / группы слоя, указав массив слоев (ваш WMS Tile Layers), где индекс массива соответствует уровню масштабирования, при котором этот слой Tile Layer должен появиться.

var myLayerSwitchByZoomA = new L.LayerSwitchByZoom([
  osmMapnik, // zoom 0, osmMapnik is a Tile Layer or any other layer
  osmDE, // zoom 1
  osmFR, // zoom 2
  osmHOT // zoom 3, etc.
]);

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

L.control.layers({
  "OpenStreetMap": myLayerSwitchByZoomA,
  "ThunderForest": myLayerSwitchByZoomB
}).addTo(map);

Демо: http://jsfiddle.net/ve2huzxw/85/

Обратите внимание, что вы можете дополнительно улучшить реализацию L.LayerSwitchByZoom, чтобы избежать мерцания при изменении слоя после завершения масштабирования и т. Д.

person ghybs    schedule 19.12.2015
comment
Большое спасибо за Ваш ответ! Мы внедряем ваш подход в течение последних нескольких дней, и он очень хорошо работает. Мерцание не так уж и плохо, поскольку мы используем наши собственные слои с геосервера через запрос wms, и они не такие уж тяжелые. Нам было интересно, можно ли перевернуть все слои? С этого момента всегда будет один активный. - person ; 21.12.2015
comment
Очень простой обходной путь, чтобы не отображать слой, - это создать фиктивный слой и добавить его в элемент управления слоями. Например: myLayerControl.addBaseLayer(L.layerGroup(), "No layer"). - person ghybs; 21.12.2015