用分组圆圈对传单聚类标记组

3

我正在尝试对一些带有圆圈的标记进行聚类。

聚类功能正常工作。但是,一旦放大到足够显示标记而不是聚类时,圆圈就不会出现。

示例代码:

const lMap = L.map('map').setView([51.508, -0.128], 11);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
  maxZoom: 19,
  attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(lMap);
const mainItems = [L.marker([51.508, -0.128]), L.marker([51.5, -0.14]), L.marker([51.51, -0.1])];
const subItems = [L.circle([51.508, -0.128], {
  color: '#38f',
  fillColor: '#38f',
  fillOpacity: 0.2,
  radius: 60
}), L.circle([51.5, -0.14], {
  color: '#38f',
  fillColor: '#38f',
  fillOpacity: 0.2,
  radius: 40
}), L.circle([51.51, -0.1], {
  color: '#38f',
  fillColor: '#38f',
  fillOpacity: 0.2,
  radius: 50
})];
const mainGroup = L.featureGroup(mainItems);
const subGroup = L.featureGroup.subGroup(mainGroup, subItems);

const mainCluster = L.markerClusterGroup();
mainCluster.addLayer(mainGroup);
lMap.addLayer(mainCluster);
lMap.addLayer(subGroup);

如果我移除聚类,那么圆圈就会出现。
// const mainCluster = L.markerClusterGroup();
// mainCluster.addLayer(mainGroup);
lMap.addLayer(mainGroup);
lMap.addLayer(subGroup);

我正在尝试的事情可能吗? 怎样才是正确的做法?
2个回答

1
尽管没有明确说明,但 Leaflet.markercluster 仅对图层组提供部分支持

实际上,将组添加到 MarkerClusterGroup 中只会添加它们非组的子图层。

因此,当你将 subGroup 添加到地图上,并将 subItems 添加到 mainGroup 中时,这并不会导致它们被传递添加到 mainCluster 标记聚类组 (MCG)。

如果我理解正确,你想要“装饰”你的标记点,使其带有一些圆形,但你不能直接将它们添加到 MCG 中,否则它们将增加计数并触发蜘蛛化;而你仍然希望根据所装饰的标记点相应地显示或隐藏它们?

在这种情况下,你有几种解决方法,其中之一是直接拥有包含自己装饰的自定义图标,正如 RobertHardy's answer 所建议的那样。

另一个可能的解决方案,更接近您使用实际圆圈进行装饰的原意,是监听地图中 Marker 事件的添加移除(由 MCG 处理聚类):

map.on('layeradd', (e) => {
    mainItems.forEach((marker, index) => {
        if (e.layer === marker) {
            // Assumes subItems are in same order as mainItems
            map.addLayer(subItems[index]);
        }
    });
});

map.on('layerremove', (e) => {
    mainItems.forEach((marker, index) => {
        if (e.layer === marker) {
            // Assumes subItems are in same order as mainItems
            map.removeLayer(subItems[index]);
        }
    });
});

现场演示:https://plnkr.co/edit/8XfhHuh3YU3ZlgtK?preview


另一种解决方案,可能更通用和稳健的方法是创建一个特殊的标记,当它未被聚类时,“知道”它应该携带一个关联的装饰层,并在聚类时将其收回。
// Variation of Leaflet Marker that comes along with an
// associated "decorationLayer" whenever it is added to the map,
// and goes away with it when removed.
// Typically useful when added to a MarkerClusterGroup,
// so that the decoration does not count, but still follows
// the Marker (un)clustering.
// Limitation: when spiderfied, decoration remains on original coordinates.
// Could be improved with custom setLagLng method?
L.Marker.Decorated = L.Marker.extend({
    options: {
        decorationLayer: null, // Could even be a Layer Group!
    },
    onAdd(map) {
        L.Marker.prototype.onAdd.call(this, map);

        // If decoration has been provided, add it to the map as well
        this.options.decorationLayer?.addTo(map);
    },
    onRemove(map) {
        L.Marker.prototype.onRemove.call(this, map);

        // If decoration has been provided, remove it from the map as well
        this.options.decorationLayer?.remove();
    },
});

const mainItems = [
    new L.Marker.Decorated([51.508, -0.128], {
        decorationLayer: L.circle([51.508, -0.128], {
            color: '#38f',
            fillColor: '#38f',
            fillOpacity: 0.2,
            radius: 500,
        }),
    }),
    // Etc.
];

演示链接: https://plnkr.co/edit/Utr7WC110oIzaATl?preview


0

如果你只是想在一个圆圈内显示每个标记,并与标记聚类结合,那么一个更简单的方法是定义一个自定义标记图标。这意味着你不需要添加单独的圆圈项,也不需要使用leaflet subgroup插件。需要注意的一点是,据我所知,自定义图标必须是PNG格式(光栅图像)。所以你可能还想考虑添加一个视网膜版本


这个解决方案的问题在于每个圆圈对应的标记点都是动态大小的。 我会更新问题以使其更清晰明了。 - Votemike
谢谢 这个解决方案的问题是每个圆圈对应的标记点大小都是动态的。 我会更新问题以使其更清晰。 - Votemike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接