通过内部的标记为群集着色 [英] Coloring clusters by markers inside

查看:96
本文介绍了通过内部的标记为群集着色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何根据群集中的图标为群集着色.

I would like to know, how to color the clusters depending on icon in it.

我的数据:

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,则群集的颜色应为红色.

If there is an icon in my cluster, with appairage = rouge, the color of the cluster should be red.

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

If there is no red icon, If there is an icon in my cluster, with temperature = orange, the color of the cluster should be orange.

...对于每个变量(温度,余量,维护).而且,如果用户中的所有图标的变量都正确,则群集应为绿色.

... for each variable (temperature, appairage, maintenance). And if all icons in the culster have their variables ok, the cluster should be green.

我的地图如下:

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

I found a way to change the range for coloring the clusters on the Internet. But I don't want to color per number of markers in the cluster.

推荐答案

可以根据群集在一起的图标的属性为群集图标着色.最简单的方法可能是使用htmlwidgets并在地图渲染时调用javascript函数.

It is possible to color the clustered icons based on the properties of the icons clustered together. The easiest method might be to use htmlwidgets and call a javascript function on map rendering.

但是,在进入htmlwidget之前,您需要为集群层设置clusterId:

However, before getting to the htmlwidget, you need to set a clusterId for your clustered layer:

addAwesomeMarkers(clusterId = "cluster" ...

现在我们可以在htmlwidget中找到该层:

Now we can find this layer when in the htmlwidget:

function(el, x) {
  map = this;  // the map object
  var cluster = map.layerManager.getLayer('cluster','cluster'); // the cluster layer

在集群层中,我们要为图标属性iconCreateFunction创建一个函数:

Within the cluster layer, we want to create a function for the icon property iconCreateFunction:

cluster.options.iconCreateFunction = function(d) {
    // generate icon
}

此功能应:

  1. 遍历由聚类标记表示的所有子标记,
  2. 确定这些子标记的最高排名
  3. 返回适当的图标

1.遍历子标记

对于第一个,并在上面的基础上,我们可以使用以下命令迭代每个子标记:

For number one, and building on the above, we can iterate through each child marker with:

cluster.options.iconCreateFunction = function(c) {
    var markers = c.getAllChildMarkers();
    markers.forEach(function(m) {
       // do something for each marker
    })
}

我正在使用c表示聚类,使用m表示每个单独的子标记

I'm using c to represent a cluster, m to represent each individual child marker

2.获得排名最高的标记

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

The primary challenge in the list is identifying the highest rank of the child icons - as the data is not bound to the icons we are limited in options. Assuming that the color of the icons corresponds to the color code of the item in the dataframe, I will use the color of the icon to determine its priority/rank. After determining the highest ranking child, I will color the cluster based on that child's rank.

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

I will color the cluster as follows (as I believe this is your intended result):

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

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

To get the color, I need to access the proper property. The color (fill) of an (awesome) marker resides at:

marker.options.icon.options.markerColor

为了比较颜色,我将使用一个对象来代表每种颜色的等级,这将允许对颜色进行简单的比较:

To compare colors, I'll use an object to represent each color's rank, this will allow for a simple comparison of color:

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样式结合使用以生成群集标签时,它们会创建绿色,黄色和橙色的熟悉的圆圈.

Now that we have a value representing a color, we can return an icon. Leaflet clustered icons have limited styling options. They use L.divIcon(), which limits options somewhat. When combined with css styles for clustered labels, they create the familiar circle with green, yellow, and orange colors.

这些默认样式具有以下css类:

These default styles have the following css classes:

.marker-cluster-small // green
.marker-cluster-medium  // yellow
.marker-cluster-large // orange

如果我们对仅使用这些类感到满意,则可以轻松地为聚簇的多边形设置样式:

If we are happy with just using these classes, we can style the clustered polygons with minimal effort:

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


因此,整个小部件看起来像:


The whole widget therefore looks like:

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


定义图标

更改颜色


Refining the Icons

Changing Colors

您可能希望使高优先级图标显示为红色.可以这样做,但是您需要在地图中添加CSS样式.

You probably want to have the high priority icons show up red. This can be done, but you need to add a css style to your map.

与更改上面的图标功能同时执行此操作的一种方法是,在小部件中使用javascript将样式添加到页面.您需要制作两种样式,一种用于保存图标的div,另一种用于图标,您可以一次完成这两种样式:

One way to do this at the same time as changing the icon function above is to append a style to the page with javascript in your widget. You need to make two styles, one for the div holding the icon, and one for the icon, you can do both at once:

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 )

别忘了更新样式数组中正在使用的类:

Don't forget to update what classes you are using in the styles array:

    var styles = [
      'marker-cluster-small', // green
      'marker-cluster-medium',  // yellow
      'red' // red
    ]

在图标中显示更多信息

图标中不限于数字,可以显示1-3-5,表示一个高优先级,三个中等,等等.您只需要跟踪每个优先级中有多少个子图标集群:

You aren't limited to a number in the icon, you could show 1-3-5 , representing one high priority, three medium etc. You just need to keep track of how many child icons of each priority are in each cluster:

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

提供类似的信息:

测试示例

这应该是可复制且可粘贴的,以显示除图标中的其他文本以外的所有内容(使用这些

This should be copy and pastable to show everything except the additional text in the icon (using the code in these documentation examples as a base):

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

这篇关于通过内部的标记为群集着色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆