【问题标题】:Coloring clusters by markers inside通过内部标记为簇着色
【发布时间】:2017-11-27 09:42:00
【问题描述】:

我想知道,如何根据其中的图标为簇着色。

我的数据:

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,那么集群的颜色应该是红色的。

如果没有红色图标,如果我的集群中有图标,温度=橙色,集群的颜色应该是橙色。

... 对于每个变量(温度、设备、维护)。如果集群中的所有图标的变量都正常,那么集群应该是绿色的。

我的地图看起来像:

我在互联网上找到了一种更改集群着色范围的方法。但我不想为集群中的每个标记数着色。

【问题讨论】:

    标签: r shiny leaflet


    【解决方案1】:

    可以根据聚集在一起的图标的属性为聚集的图标着色。最简单的方法可能是使用 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。获得最高排名标记

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

    我将按如下方式为集群着色(因为我相信这是您的预期结果):

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

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

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

    【讨论】:

      【解决方案2】:

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

      另请参阅:leaflet R, how to make appearance of clustered icon related to statistics of the children?

      一个例子是:

      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)
      

      【讨论】:

        猜你喜欢
        • 2021-06-03
        • 1970-01-01
        • 2012-06-27
        • 1970-01-01
        • 2020-05-30
        • 2023-03-19
        • 2016-08-19
        • 2017-10-03
        • 2013-05-29
        相关资源
        最近更新 更多