Leaflet Trigger Event на кластерном маркере по внешнему элементу

Я только начинаю узнавать о Leaflet.js для своего будущего проекта.

Что я пытаюсь выполнить: мне нужно составить список маркеров, которые отображаются на карте, и когда элемент списка наведен (или наведен указатель мыши), он будет отображаться где позиция на карте (для одиночного маркера он должен изменить свой цвет. Для кластерного маркера он должен отобразить линию покрытия, например, как она ведет себя при наведении на нее .. и, возможно, тоже изменит ее цвет, если возможно). Карта не должна меняться, как и уровень масштабирования, проще говоря, мне нужно выделить маркер / кластер на карте.

Что я сделал сейчас: я могу сделать это с помощью одиночного маркера. введите описание изображения здесь

что меня очень расстроило: мне не удалось найти способ сделать это с помощью кластерного маркера.

Я использую глобальный объект var для хранения любого созданного маркера.

function updateMapMarkerResult(data) {
  markers.clearLayers();
  for (var i = 0; i < data.length; i++) {
    var a = data[i];
    var myIcon = L.divIcon({
      className: 'prop-div-icon',
      html: a.Description
    });
    var marker = L.marker(new L.LatLng(a.Latitude, a.Longitude), {
      icon: myIcon
    }, {
      title: a.Name
    });
    marker.bindPopup('<div><div class="row"><h5>Name : ' + a.Name + '</h5></div><div class="row">Lat : ' + a.Latitude + '</div><div class="row">Lng : ' + a.Longitude + '</div>' + '</div>');
    marker.on('mouseover', function(e) {
      if (this._icon != null) {
        this._icon.classList.remove("prop-div-icon");
        this._icon.classList.add("prop-div-icon-shadow");
      }
    });
    marker.on('mouseout', function(e) {
      if (this._icon != null) {
        this._icon.classList.remove("prop-div-icon-shadow");
        this._icon.classList.add("prop-div-icon");
      }
    });
    markersRef[a.LocId] = marker;   // <-- Store Reference
    markers.addLayer(marker);

    updateMapListResult(a, i + 1);
  }
  map.addLayer(markers);
}

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

...
li.addEventListener("mouseover", function(e) {
    jQuery(this).addClass("btn-info");
    markersRef[this.getAttribute('marker')].fire('mouseover'); // --> Trigger Marker Event "mouseover"
    // TODO : Trigger ClusteredMarker Event "mouseover"
  });
...

Это мой текущий https://jsfiddle.net/oryza_anggara/2gze75L6/, любое зацепление может быть очень большая помощь. Спасибо.

Примечание: я знаком только с JQuery, у меня нет никаких знаний о других библиотеках, таких как Angular.js.


person OAN    schedule 19.09.2017    source источник


Ответы (1)


Вы, вероятно, ищете метод markers.getVisibleParent(marker), чтобы получить содержащий кластер, если ваш маркер кластеризован.

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

function _fireEventOnMarkerOrVisibleParentCluster(marker, eventName) {
  var visibleLayer = markers.getVisibleParent(marker);

  if (visibleLayer instanceof L.MarkerCluster) {
    // In case the marker is hidden in a cluster, have the clusterGroup
    // show the regular coverage polygon.
    markers.fire(eventName, {
      layer: visibleLayer
    });
  } else {
    marker.fire(eventName);
  }
}

var marker = markersRef[this.getAttribute('marker')];
_fireEventOnMarkerOrVisibleParentCluster(marker, 'mouseover');

Обновленный JSFiddle: https://jsfiddle.net/2gze75L6/5/

При этом я думаю, что еще одним интересным пользовательским интерфейсом вместо отображения обычного многоугольника покрытия, который вы получаете при наведении курсора на кластер «вручную», было бы spiderfy кластер и выделение вашего маркера. Не очень-то просто реализовать, но результат мне кажется приятным. Вот быстрая попытка, возможно, потребуется дополнительная работа, чтобы сделать его пуленепробиваемым:

Демо: https://jsfiddle.net/2gze75L6/6/

function _fireEventOnMarkerOrVisibleParentCluster(marker, eventName) {
  if (eventName === 'mouseover') {
    var visibleLayer = markers.getVisibleParent(marker);

    if (visibleLayer instanceof L.MarkerCluster) {
      // We want to show a marker that is currently hidden in a cluster.
      // Make sure it will get highlighted once revealed.
      markers.once('spiderfied', function() {
        marker.fire(eventName);
      });
      // Now spiderfy its containing cluster to reveal it.
      // This will automatically unspiderfy other clusters.
      visibleLayer.spiderfy();
    } else {
      // The marker is already visible, unspiderfy other clusters if
      // they do not contain the marker.
      _unspiderfyPreviousClusterIfNotParentOf(marker);
      marker.fire(eventName);
    }
  } else {
    // For mouseout, marker should be unclustered already, unless
    // the next mouseover happened before?
    marker.fire(eventName);
  }
}

function _unspiderfyPreviousClusterIfNotParentOf(marker) {
  // Check if there is a currently spiderfied cluster.
  // If so and it does not contain the marker, unspiderfy it.
  var spiderfiedCluster = markers._spiderfied;

  if (
    spiderfiedCluster
    && !_clusterContainsMarker(spiderfiedCluster, marker)
  ) {
    spiderfiedCluster.unspiderfy();
  }
}

function _clusterContainsMarker(cluster, marker) {
  var currentLayer = marker;

  while (currentLayer && currentLayer !== cluster) {
    currentLayer = currentLayer.__parent;
  }

  // Say if we found a cluster or nothing.
  return !!currentLayer;
}
person ghybs    schedule 19.09.2017
comment
оно работает! определенно то, что я ищу. И функция Spiderfy действительно потрясающая! хотел бы использовать его, нужно подумать о большем количестве маркера. Но ты действительно справился с этим, даже больше .. спасибо, ты только сэкономил неделю моего дня головной боли. - person OAN; 20.09.2017