r - 通过内部标记为簇着色

标签 r shiny leaflet

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

我的数据:

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

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

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

我的 map 看起来像:

enter image description here

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

最佳答案

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

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

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

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

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

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

优化图标

改变颜色

您可能希望高优先级图标显示为红色。这可以做到,但您需要在 map 中添加 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>...

赠品如下:

enter image description here


测试示例

这应该是可复制和可粘贴的,以显示除图标中的附加文本之外的所有内容(使用这些 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) });
 }
}")

关于r - 通过内部标记为簇着色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47507854/

相关文章:

r - 使用ggbiplot向PCA的变量名添加下标?

r - 如果没有可用的 UI 输入,则防止在 Shiny 中发生事件

javascript - meteor 上的传单空白屏幕,但单个非 meteor test.html 上没有

R:带有时间 slider 的 map ?

R:在 ifelse 函数中使用 "()"内的逻辑语句在 data.table 中分配变量

r - 将曲线拟合到直方图 ggplot

r - 假设检验R中的偏度和/或峰度

r - 如何在 Shiny App (R) 中更改 gvisTable 的背景颜色

r - 使用 for 循环动态调用 Shiny 模块多次

javascript - 网络制图传单库