可以根据聚集在一起的图标的属性为聚集的图标着色。最简单的方法可能是使用 htmlwidgets 并在地图渲染上调用 javascript 函数。
但是,在进入 htmlwidget 之前,您需要为您的集群层设置一个 clusterId:
addAwesomeMarkers(clusterId = "cluster" ...
现在我们可以在 htmlwidget 中找到这一层:
function(el, x) {
map = this; // the map object
var cluster = map.layerManager.getLayer('cluster','cluster'); // the cluster layer
在集群层中,我们要为图标属性iconCreateFunction创建一个函数:
cluster.options.iconCreateFunction = function(d) {
// generate icon
}
这个函数应该:
- 遍历聚类标记所代表的所有子标记,
- 确定这些子标记的最高等级
- 返回适当的图标
1.遍历子标记
对于第一个,在上面的基础上,我们可以遍历每个子标记:
cluster.options.iconCreateFunction = function(c) {
var markers = c.getAllChildMarkers();
markers.forEach(function(m) {
// do something for each marker
})
}
我使用c 表示一个簇,m 表示每个单独的子标记
2。获得最高排名标记
列表中的主要挑战是确定子图标的最高等级 - 因为数据未绑定到我们在选项中受限的图标。假设图标的颜色与数据框中项目的颜色代码相对应,我将使用图标的颜色来确定其优先级/等级。在确定排名最高的孩子后,我将根据该孩子的排名对集群进行着色。
我将按如下方式为集群着色(因为我相信这是您的预期结果):
- 如果有任何子图标为红色,则为红色,
- 橙色,如果没有红色但有一些橙色的孩子,并且
- 绿色,如果没有橙色或红色的孩子。
要获得颜色,我需要访问正确的属性。 (真棒)标记的颜色(填充)位于:
marker.options.icon.options.markerColor
为了比较颜色,我将使用一个对象来表示每种颜色的等级,这样可以简单地比较颜色:
var priority = {
'green':0,
'orange':1,
'red':2
}
这允许:
cluster.options.iconCreateFunction = function(c) {
var markers = c.getAllChildMarkers();
var priority = {
'green': 0,
'orange': 1,
'red': 2
};
var highestRank = 0; // defaults to the lowest level to start
markers.forEach(function(m) {
var color = m.options.icon.options.markerColor;
// check each marker to see if it is the highest value
if(priority[color] > highestRank) {
highestRank = priority[color];
}
})
}
3.返回一个图标
现在我们有了一个代表颜色的值,我们可以返回一个图标。传单群集图标的样式选项有限。他们使用L.divIcon(),这在一定程度上限制了选项。当与集群标签的 css 样式结合使用时,它们会创建熟悉的绿色、黄色和橙色圆圈。
这些默认样式具有以下 css 类:
.marker-cluster-small // green
.marker-cluster-medium // yellow
.marker-cluster-large // orange
如果我们对使用这些类感到满意,我们可以轻松地为聚集的多边形设置样式:
var styles = [
'marker-cluster-small', // green
'marker-cluster-medium', // yellow
'marker-cluster-large' // orange
]
var style = styles[highestRank];
var count = markers.length;
return L.divIcon({ html: '<div><span>'+count+'</span></div>', className: 'marker-cluster ' + style, iconSize: new L.Point(40, 40) });
因此整个小部件看起来像:
function(el,x) {
map = this;
var cluster = map.layerManager.getLayer('cluster','cluster');
cluster.options.iconCreateFunction = function(c) {
var markers = c.getAllChildMarkers();
var priority = {
'green': 0,
'orange': 1,
'red': 2
};
var highestRank = 0; // defaults to the lowest level to start
markers.forEach(function(m) {
var color = m.options.icon.options.markerColor;
// check each marker to see if it is the highest value
if(priority[color] > highestRank) {
highestRank = priority[color];
}
})
var styles = [
'marker-cluster-small', // green
'marker-cluster-medium', // yellow
'marker-cluster-large' // orange
]
var style = styles[highestRank];
var count = markers.length;
return L.divIcon({ html: '<div><span>'+count+'</span></div>', className: 'marker-cluster ' + style, iconSize: new L.Point(40, 40) });
}
}
优化图标
改变颜色
您可能希望高优先级图标显示为红色。这可以做到,但您需要在地图中添加 css 样式。
在更改上述图标功能的同时执行此操作的一种方法是在您的小部件中使用 javascript 将样式附加到页面。您需要制作两种样式,一种用于持有图标的 div,一种用于图标,您可以同时进行两种样式:
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.red, .red div { background-color: rgba(255,0,0,0.6); }'; // set both at the same time
document.getElementsByTagName('head')[0].appendChild(style);
(来自https://stackoverflow.com/a/1720483/7106086)
不要忘记更新您在样式数组中使用的类:
var styles = [
'marker-cluster-small', // green
'marker-cluster-medium', // yellow
'red' // red
]
在图标中显示更多信息
您不限于图标中的数字,您可以显示 1-3-5 ,代表一个高优先级,三个中等等。您只需要跟踪每个优先级有多少个子图标集群:
var children = [0,0,0];
markers.forEach(function(m) {
var color = m.options.icon.options.markerColor;
children[priority[color]]++; // increment the appropriate value in the children array.
...
然后显示:
return L.divIcon({ html: '<div><span>'+children.reverse()+'</span>...
赠品如下:
测试示例
这应该是可复制和可粘贴的,以显示除图标中的附加文本之外的所有内容(使用这些documentation examples 中的代码作为基础):
library(leaflet)
# first 20 quakes
df.20 <- quakes[1:50,]
getColor <- function(quakes) {
sapply(quakes$mag, function(mag) {
if(mag <= 4) {
"green"
} else if(mag <= 5) {
"orange"
} else {
"red"
} })
}
icons <- awesomeIcons(
icon = 'ios-close',
iconColor = 'black',
library = 'ion',
markerColor = getColor(df.20)
)
leaflet(df.20) %>% addTiles() %>%
addAwesomeMarkers(~long, ~lat, icon=icons, label=~as.character(mag), clusterOptions = markerClusterOptions(), group = "clustered", clusterId = "cluster") %>%
htmlwidgets::onRender("function(el,x) {
map = this;
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.red, .red div { background-color: rgba(255,0,0,0.6); }'; // set both at the same time
document.getElementsByTagName('head')[0].appendChild(style);
var cluster = map.layerManager.getLayer('cluster','cluster');
cluster.options.iconCreateFunction = function(c) {
var markers = c.getAllChildMarkers();
var priority = {
'green': 0,
'orange': 1,
'red': 2
};
var highestRank = 0; // defaults to the lowest level to start
markers.forEach(function(m) {
var color = m.options.icon.options.markerColor;
// check each marker to see if it is the highest value
if(priority[color] > highestRank) {
highestRank = priority[color];
}
})
var styles = [
'marker-cluster-small', // green
'marker-cluster-large', // orange
'red' // red
]
var style = styles[highestRank];
var count = markers.length;
return L.divIcon({ html: '<div><span>'+count+'</span></div>', className: 'marker-cluster ' + style, iconSize: new L.Point(40, 40) });
}
}")