利用标记物对聚类进行着色

3
我可以帮你进行翻译。以下是翻译的内容:

我想知道如何根据其中的图标着色聚类。

我的数据:

remorque       time.stamp      lat      long geolocalisation maintenance temperature appairage
1        21/11/2017 10:36 48.86272 2.2875920          OnMouv        noir                      
2        21/11/2017 10:36 43.60776 1.4421606       StartMouv                   rouge          
3        21/11/2017 10:36 46.58619 0.3388710          OnMouv                   rouge          
4        21/11/2017 10:36 45.76695 3.0556216            Life                  orange          
5        21/11/2017 10:36 45.14555 1.4751652         EndMouv                             rouge
6        21/11/2017 10:36 46.81157 1.6936336            Life                  orange          
7        21/11/2017 10:36 47.36223 0.6751146          alerte                             rouge
8        21/11/2017 10:36 47.36032 1.7441244       StartMouv                                  
9        21/11/2017 10:36 48.85333 1.8215332       StartMouv                                  
10       21/11/2017 10:36 48.84429 1.7913208          alerte                                  
11       21/11/2017 10:36 48.81356 1.6759643         EndMouv                                  

例子:

如果我的集群中有一个图标,其appairage = rouge,则集群的颜色应为红色。

如果没有红色图标,但是我的集群中有一个温度=橙色的图标,则集群的颜色应为橙色。

...对于每个变量(温度,appairage,维护)。

如果集群中的所有图标都具有其变量值,则集群应为绿色。

我的地图如下:

enter image description here

我在网上找到了一种改变集群颜色范围的方法。但是我不想按照聚类中标记数量进行着色。
2个回答

8
可以根据聚集在一起的图标的属性来对其进行着色。最简单的方法可能是使用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. 遍历由聚合标记表示的所有子标记,
  2. 识别那些子标记中最高的等级
  3. 返回一个适当的图标
1. 遍历子标记 对于第一步,我们可以在上面的基础上通过以下方式遍历每个子标记:
cluster.options.iconCreateFunction = function(c) {
    var markers = c.getAllChildMarkers();
    markers.forEach(function(m) {
       // do something for each marker
    })
}

我使用c代表一个群集,m代表每个单独的子标记。

2. 获取最高排名的标记

在列表中的主要挑战是识别子图标的最高排名 - 因为数据未绑定到图标,我们的选择受到限制。假设图标的颜色对应于数据框中项目的颜色代码,我将使用图标的颜色来确定其优先级/排名。确定最高排名的子项后,我将根据该子项的排名对群集进行着色。

我将按以下方式对群集进行着色(因为我认为这是您想要的结果):

  • 如果任何子项图标为红色,则为红色,
  • 如果没有红色但有一些橙色子项,则为橙色,
  • 如果没有橙色或红色子项,则为绿色。

要获取颜色,我需要访问正确的属性。 (awesome)标记的颜色(填充)位于:

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. 返回一个图标

现在我们有了代表颜色的值,可以返回一个图标。Leaflet聚合图标的样式选项有限。它们使用 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://dev59.com/v3I-5IYBdhLWcg3wsKv9#1720483)

不要忘记在样式数组中更新你正在使用的类:

    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>...

给出类似这样的东西:

enter image description here


测试示例

这应该是可复制和粘贴的,以展示除图标中的附加文本之外的所有内容(使用这些文档示例中的代码作为基础):

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) });
 }
}")

1
现在您还可以在markerClusterOptions中使用iconCreateFunction。确保您将要用于着色的变量传递给markerOptions

另请参见:leaflet R,如何使聚合图标的外观与子项的统计数据相关?

示例:

legend_pal <- hcl.colors(10, palette='Spectral', rev = T)

leaflet(quakes) %>% addTiles() %>% addMarkers(
  options = markerOptions(mag = ~mag),
  clusterOptions = markerClusterOptions(
    iconCreateFunction=~JS(paste0("function (cluster) {    
                          var markers = cluster.getAllChildMarkers();
                          var sum = 0; 
                          for (i = 0; i < markers.length; i++) {
                            sum += Number(markers[i].options.mag);
                          }
                          var palette = ['", paste0(legend_pal, collapse="','"),"'];
                          var domain = [", paste0(sort(unique(na.omit(mag))), collapse=','),"];

                          var count = markers.length;
                          var avg = sum/count;
                          c = palette[Math.round(palette.length*(avg-Math.min(...domain))/(Math.max(...domain) - Math.min(...domain)))];


                          return L.divIcon({ 
                            html: '<div style=\"background-color:'+c+'\"><span>'+avg+'</span></div>', 
                            className: 'marker-cluster', 
                            iconSize: new L.Point(40, 40) });
                          }")))) %>% 
  addLegend(pal=colorNumeric(
    palette = legend_pal,
    domain = quakes$mag,
    na.color = 'transparent'), values = ~mag)

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