Предотвращение перекрытия нескольких значков markerClusterGroup в Leaflet

У меня есть две отдельные группы markerClusterGroups, которые иногда перекрываются. Есть ли способ предотвратить это? В моем фактическом коде я использую пользовательский значок для одной из групп кластеров, чтобы я мог определить разницу между двумя типами кластеров. Однако для этого примера в этом не было необходимости, поэтому я пропустил эту часть для простоты.

var map = L.map("map");

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

map.setView([48.85, 2.35], 12);
var mcg = L.markerClusterGroup().addTo(map);
var mcg2 = L.markerClusterGroup().addTo(map);

L.marker([48.85, 2.35]).addTo(mcg);
L.marker([48.85, 2.34]).addTo(mcg);
  
for(var i=0;i<40;i++){
    L.marker([48.85, 2.34091]).addTo(mcg2);
}

Вот пример того, что я имею в виду:

http://plnkr.co/edit/yqIhI7RMsp9A7I3AwGnY?p=preview

Скриншот

Требование гласит, что маркеры категории 1 должны группироваться отдельно от маркеров категории 2. Однако оба типа должны отображаться на карте одновременно.


person Abu Sulaiman    schedule 20.09.2018    source источник
comment
Спасибо за разъяснение вашего требования. Мне кажется, что вам следует запросить более подробную информацию о маркерах категории 1, которые должны группироваться отдельно от маркеров категории 2. Например. что должно произойти, если у вас есть маркер A из категории 1 в том же положении, что и маркер B из категории 2? С текущим кодом они будут просто перекрываться (даже не кластеризоваться). Звучит как плохой пользовательский интерфейс для меня.   -  person ghybs    schedule 21.09.2018
comment
Да, я уже вижу, как это происходит. Я следую вашему совету и вернусь, чтобы получить дополнительные разъяснения, особенно когда маркеры находятся в точном положении. Спасибо за вашу помощь.   -  person Abu Sulaiman    schedule 21.09.2018


Ответы (1)


Есть ли способ предотвратить это?

Не с несколькими группами Leaflet.markercluster, как вы.

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

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

Например, популярной альтернативой показу различных категорий при кластеризации является плагин PruneCluster:

PruneCluster — это быстрая библиотека для кластеризации маркеров в реальном времени.

Он работает с Leaflet как альтернатива Leaflet.markercluster.

Скриншот карты с категориями значков PruneCluster Выдержка с домашней страницы PruneCluster

Другим возможным обходным решением может быть объединение всех категорий в одну группу кластеров маркеров, но с иконкой кластера последней настраивается так, чтобы они отображались так же, как на приведенном выше снимке экрана PruneCluster, или даже отображали поддельные значки для каждой категории:

Снимок экрана Leaflet.markercluster с настроенными значками кластера для каждой категории

function customClusterIcon(cluster) {
  // Count number of markers from each category.
  var markers = cluster.getAllChildMarkers();
  var cat1count = 0;
  var cat2count = 0;
  for (var marker of markers) {
    var category = marker.options.category;
    if (category && category === 'cat2') {
      cat2count += 1;
    } else {
      cat1count += 1;
    }
  }
  // Generate the cluster icon depending on presence of Markers from different categories.
  if (cat2count === 0) {
    return L.divIcon({
      html: cat1count,
      className: 'cat1cluster cluster',
      iconSize: [20, 20]
    });
  } else if (cat1count === 0) {
    return L.divIcon({
      html: cat2count,
      className: 'cat2cluster cluster',
      iconSize: [20, 20]
    });
  } else {
    return L.divIcon({
      html: `
        <div class="cat1cluster cluster">${cat1count}</div>
        <div class="cat2cluster cluster">${cat2count}</div>
      `,
      className: '',
      iconSize: [45, 20]
    });
  }
}

var paris = [48.86, 2.35];
var parisLeft = [48.86, 2.25];
var parisRight = [48.86, 2.45];
var map = L.map('map', {
  maxZoom: 18
}).setView(paris, 11);

var mcg = L.markerClusterGroup({
  iconCreateFunction: customClusterIcon
}).addTo(map);
var category1 = L.layerGroup();
var category2 = L.layerGroup();

var cat2style = {
  color: 'red',
  category: 'cat2'
};

var markerA = L.circleMarker(paris).addTo(category1);
var markerB = L.circleMarker(paris).addTo(category1);
var markerC = L.circleMarker(paris, cat2style).addTo(category2);
var markerD = L.circleMarker(paris, cat2style).addTo(category2);

var markerE = L.circleMarker(parisLeft).addTo(category1);
var markerF = L.circleMarker(parisLeft).addTo(category1);

var markerG = L.circleMarker(parisRight, cat2style).addTo(category2);
var markerH = L.circleMarker(parisRight, cat2style).addTo(category2);

mcg.addLayers([category1, category2]);


L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
html,
body,
#map {
  height: 100%;
  margin: 0;
}

.cat1cluster {
  background-color: #3388ff;
}

.cat2cluster {
  background-color: red;
}

.cluster {
  width: 20px;
  height: 20px;
  display: inline-block;
  text-align: center;
}
<!-- Leaflet assets -->
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-+ZaXMZ7sjFMiCigvm8WjllFy6g3aou3+GZngAtugLzrmPFKFK7yjSri0XnElvCTu/PrifAYQuxZTybAEkA8VOA==" crossorigin=""></script>

<!-- Leaflet.markercluster assets -->
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/MarkerCluster.css">
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/MarkerCluster.Default.css">
<script src="https://unpkg.com/[email protected]/dist/leaflet.markercluster-src.js"></script>


<div id="map"></div>

Затем, если вы хотите, вы можете дополнительно настроить паукообразную информацию, чтобы она отображала маркеры только из щелкнутого значка кластера категории и аналогично для парящего многоугольника.

person ghybs    schedule 21.09.2018
comment
И есть интересный вырожденный случай: что, если есть четыре точки данных, по две для каждой категории, в одних и тех же точных координатах? - person IvanSanchez; 21.09.2018
comment
Я добавил требование к вопросу. Я был бы очень признателен, если бы вы могли указать мне на другие библиотеки или обходные пути. Большое спасибо. - person Abu Sulaiman; 21.09.2018
comment
Я понимаю, что ты говоришь @IvanSanchez. - person Abu Sulaiman; 21.09.2018
comment
@AbuSulaiman: добавлена ​​ссылка на альтернативный PruneCluster и пример настраиваемого значка кластера для отображения различных категорий. - person ghybs; 23.09.2018
comment
@ghybs Спасибо за ссылку и пример. Я никогда не сталкивался с PruneCluster. Это действительно круто, и я думаю, что это именно то, что мы ищем. Замена может занять некоторое время, но я думаю, что это того стоит. Большое спасибо. Это круто! - person Abu Sulaiman; 24.09.2018
comment
@ghybs Ваш пример MarkerCluster тоже хорош. Теперь у меня есть варианты, еще раз спасибо! - person Abu Sulaiman; 24.09.2018