繁体   English   中英

使用 map.animatedcluster 在 Openlayers 中集群:层的样式和集群

[英]Cluster in Openlayers with map.animatedcluster: style and cluster of layers

我需要使用 Openlayers 对要显示在我的 map 上的点进行分组。 我正在关注示例http://viglino.github.io/ol-ext/examples/animation/map.animatedcluster.html

我能够更改它,以便我的层是 WFS 层。 在下图中,我有两个层,但是,它们并没有将两者组合在一起,而是分开。 在以红色突出显示的部分中,我们可以看到绿色和橙色的分组非常接近,每个分组都代表一个层。 如何对 map 上显示的所有层进行聚类? 在此处输入图像描述

几个月前我已经发了一篇关于这个例子的帖子 Openlayers: cluster with different layers

另一件事,层层有不同的风格。 I would like to keep this style, when the cluster is selected and/or when there is only one point in the cluster. 有小费吗?

[编辑]

// Cluster Source
var clusterSource1=new ol.source.Cluster({
  distance: 60,
  source:  new ol.source.Vector({
        format: new ol.format.GeoJSON(),
        url: function(extent) {
        return urlGeoserver + 'wfs?service=WFS&' +
            'version='+versionGeoserver+'&request=GetFeature&typename=geo:MyLAYER1&' +
            'outputFormat=application/json&srsname=EPSG:4326&' +
            'all=' + extent.join(',') + ',EPSG:4326';
        },
        strategy: ol.loadingstrategy.all
    })
});
// Animated cluster layer
var clusterLayer1 = new ol.layer.AnimatedCluster({
  name: 'Cluster1',
  source: clusterSource1,
  animationDuration: 700, 
  style: getStyle
});

var clusterSource2=new ol.source.Cluster({
  distance: 60,
  source:  new ol.source.Vector({
        format: new ol.format.GeoJSON(),
        url: function(extent) {
        return urlGeoserver + 'wfs?service=WFS&' +
            'version='+versionGeoserver+'&request=GetFeature&typename=geo:MyLAYER2&' +
            'outputFormat=application/json&srsname=EPSG:4326&' +
            'all=' + extent.join(',') + ',EPSG:4326';
        strategy: ol.loadingstrategy.all
    })
});


var clusterLayer2 = new ol.layer.AnimatedCluster({
  name: 'Cluster2',
  source:  clusterSource2,
  animationDuration: 700, 
  style: getStyle
});
map.addLayer(clusterLayer1);
map.addLayer(clusterLayer2);

谢谢

这就是我解决这个问题的方法。 您将在一个功能集中拥有来自不同来源的所有功能。 每个功能都被标记,因此您没有不同的层。 您设置一个属性来区分您的功能。 如果你想删除一个“层”,你只需从源中删除该功能,如果它在那里,则将其推回。 希望这就是你想要的。

https://jsfiddle.net/komarara/8jbzL019/

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <style>
    .map {
      height: 100%;
      width: 100%;
    }

    html,
    body {
      height: 100%
    }
  </style>
  <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.11.0/build/ol.js"></script>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.11.0/css/ol.css">
</head>

<body>
  <Button onClick="handleVisibilityLayer1()">Layer1</Button>
  <Button onClick="handleVisibilityLayer2()">Layer2</Button>
  <div id="map" class="map"></div>

  <script type="text/javascript"> 
    let source;
    let featureCollection = [];
    
    document.addEventListener("DOMContentLoaded", function () {
        drawMap();
    });
    
    function handleVisibilityLayer1(){
    
        for(const feature of featureCollection){
            const layerId = feature.get('layer');
            
            if(layerId === 'layer1' && source.hasFeature(feature)){
                source.removeFeature(feature);
            
            } else if(layerId === 'layer1' && !source.hasFeature(feature)){
                source.addFeature(feature);
            }
        }
    }
    
    function handleVisibilityLayer2(){
        for(const feature of featureCollection){
            const layerId = feature.get('layer');
            
            if(layerId === 'layer2' && source.hasFeature(feature)){
                source.removeFeature(feature);
            
            } else if(layerId === 'layer2' && !source.hasFeature(feature)){
                source.addFeature(feature);
            }
        }
    }

    function drawMap() {
        
    const feature1 = new ol.Feature({
        geometry: new ol.geom.Point([818131.46, 5846162.87]),
        layer: 'layer1',
    });
    
    const feature2 = new ol.Feature({
        geometry: new ol.geom.Point([818130.46, 5846162.87]),
        layer: 'layer1',
    });
    
    const feature11 = new ol.Feature({
        geometry: new ol.geom.Point([818131.46, 5846161.87]),
        layer: 'layer2',
    });
    
    const feature22 = new ol.Feature({
        geometry: new ol.geom.Point([818130.46, 5846161.87]),
        layer: 'layer2',
    });
    
    featureCollection = [feature1, feature2, feature11, feature22];
        
    source = new ol.source.Vector({
        features: featureCollection,
    });
        
    const clusterSource = new ol.source.Cluster({
        source: source,
    });
        
    const styleCache = {};
    const clusterLayer = new ol.layer.Vector({
      source: clusterSource,
      style: function (feature) {
        const size = feature.get('features').length;
        let style = styleCache[size];
        if (!style) {
          style = new ol.style.Style({
            image: new ol.style.Circle({
              radius: 10,
              stroke: new ol.style.Stroke({
                color: '#fff',
              }),
              fill: new ol.style.Fill({
                color: '#3399CC',
              }),
            }),
            text: new ol.style.Text({
              text: size.toString(),
              fill: new ol.style.Fill({
                color: '#fff',
              }),
            }),
          });
          styleCache[size] = style;
        }
        return style;
      },
    });
    
    const osmLayer = new ol.layer.Tile({
        source: new ol.source.OSM({
            attributions: '© OpenStreetMap',
        })
    });
      
    map = new ol.Map({
        target: 'map',
        layers: [
            osmLayer,
            clusterLayer
        ],
        view: new ol.View(),
    });

    map.getView().fit(source.getExtent());
    
    }
        
  </script>
</body>

</html>

我有几个层,我可以选择一个或多个显示在map上。图中,我是两次,每个都有不同的标签。

每一层都有一个对应的源,也就是一个WFS。

var layer 1 = new ol.layer.Vector({
    source: new ol.source.Vector({
      //code })
 })

当你点击任何一点时,它会显示一个带有特定图层信息的弹出窗口。

在此处输入图像描述 我想要的是? 将此信息分组以避免污染 map。我已经使用 Leaflet 进行了开发,但我没有使用 Openlayers。 在宣传册中,我使用了 L.markerClusterGroup.layerSupport

在此处输入图像描述 我按照代码http://viglino.github.io/ol-ext/examples/animation/map.animatedcluster.html开始了测试。 我什至发布了我的初始测试代码,但它没有对来自不同层的数据进行分组,我没有给出即将进行的更改的顺序。

[编辑] 如何将一个来源的特征添加到另一个来源? 不管用

    // Cluster Source
var clusterSource_=new ol.source.Cluster({
    distance: 40,
    source: new ol.source.Vector()
});
// Animated cluster layer
var clusterLayer_ = new ol.layer.AnimatedCluster(
{   name: 'Cluster',
    source: clusterSource_,
    style: getStyle
});
map.addLayer(clusterLayer_);


var teste =  new ol.source.Vector({
        format: new ol.format.GeoJSON(),
        url: function(extent) {
        return urlGeoserver + 'wfs?service=WFS&' +
            'version='+versionGeoserver+'&request=GetFeature&typename=geo:MYLAYER1&' +
            'outputFormat=application/json&srsname=EPSG:4326&' +
            'all=' + extent.join(',') + ',EPSG:4326';
        },
        strategy: ol.loadingstrategy.all
})
var features = teste.getFeatures();
alert(features.length); //this alerts '0', but there's more than 10 features!!


clusterSource_.getSource().clear();
clusterSource_.getSource().addFeatures(teste.getSource().getFeatures());

只有一个集群源/层的多层。 我只是将所有功能推送到一个阵列。 然而,这只是一个概念验证,在一定数量的功能下,你会遇到性能问题,因此还有改进的空间。

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <style>
    .map {
      height: 100%;
      width: 100%;
    }

    html,
    body {
      height: 100%
    }
  </style>
  <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css"> 
</head>

<body>
  <input type="checkbox" onChange="handleLayerVisibility('layer1', this.checked)">Layer1</input>
  <input type="checkbox" onChange="handleLayerVisibility('layer2', this.checked)">Layer2</Checkbox>
  <div id="map" class="map"></div>

  <script type="text/javascript"> 
    let intermediateClusterSource;

    const feature1 = new ol.Feature({
        geometry: new ol.geom.Point([818131.46, 5846162.87]),
        layer: 'layer2'
    });
    const feature2 = new ol.Feature({
        geometry: new ol.geom.Point([818130.46, 5846162.87]),
        layer: 'layer2'
    });
    const feature3 = new ol.Feature({
        geometry: new ol.geom.Point([818131.46, 5846161.87]),
        layer: 'layer2'
    });
    const feature4 = new ol.Feature({
        geometry: new ol.geom.Point([818130.46, 5846161.87]),
        layer: 'layer2'
    });
    
    const featureCollection = [feature1, feature2, feature3, feature4];
    
    document.addEventListener("DOMContentLoaded", function () {
        drawMap();
    });
    
    function handleLayerVisibility(layerId, checked){
        for(const feature of featureCollection){
            const id = feature.get('layer');
            if(id !== layerId){
                continue;
            }
            if(checked){
                intermediateClusterSource.addFeature(feature);
            } else {
                intermediateClusterSource.removeFeature(feature);
            }
        }
    }
    
    function drawMap() {
    
        const source1 = new ol.source.Vector({
            format: new ol.format.GeoJSON(),
            loader: function(extent, resolution, projection, success, failure) {
                     var proj = projection.getCode();
                     var url = 'https://ahocevar.com/geoserver/wfs?service=WFS&' +
                         'version=1.1.0&request=GetFeature&typename=osm:water_areas&' +
                         'outputFormat=application/json&srsname=' + proj;
                         
                     var xhr = new XMLHttpRequest();
                     xhr.open('GET', url);
                     var onError = function() {
                       source1.removeLoadedExtent(extent);
                       failure();
                     }
                     xhr.onerror = onError;
                     xhr.onload = function() {
                       if (xhr.status == 200) {
                         var features = source1.getFormat().readFeatures(xhr.responseText);
                         for(const [index, feature] of features.entries()){
                            const geometry = feature.getGeometry();
                            if(geometry instanceof ol.geom.SimpleGeometry){
                                if(index < 100){
                                    const coords = geometry.getCoordinates()[0][0][0];
                                    if(coords && coords.length === 2){
                                        const feat = new ol.Feature({
                                            geometry: new ol.geom.Point(coords),
                                            layer: 'layer1'
                                        });
                                        featureCollection.push(feat);
                                    }
                                }
                            }
                         }
                         
                         success(features);
                       } else {
                         onError();
                       }
                     }
                     xhr.send();
            },
        });

        const layer1 = new ol.layer.Vector({
            id: 'layer1',
            source: source1,
        })
        
        const source2 = new ol.source.Vector({
            features: [feature1, feature2, feature3, feature4]
        })
        
        const layer2 = new ol.layer.Vector({
            id: 'layer2',
            source: source2,
            visible: false,
        })
        
        intermediateClusterSource = new ol.source.Vector();
            
        const clusterSource = new ol.source.Cluster({
            source: intermediateClusterSource,
        });
            
        const styleCache = {};
        const clusterLayer = new ol.layer.Vector({
          source: clusterSource,
          style: function (feature) {
            const size = feature.get('features').length;
            let style = styleCache[size];
            if (!style) {
              style = new ol.style.Style({
                image: new ol.style.Circle({
                  radius: 10,
                  stroke: new ol.style.Stroke({
                    color: '#fff',
                  }),
                  fill: new ol.style.Fill({
                    color: '#3399CC',
                  }),
                }),
                text: new ol.style.Text({
                  text: size.toString(),
                  fill: new ol.style.Fill({
                    color: '#fff',
                  }),
                }),
              });
              styleCache[size] = style;
            }
            return style;
          },
        });
        
        const osmLayer = new ol.layer.Tile({
            source: new ol.source.OSM({
                attributions: '© OpenStreetMap',
            })
        });
          
        map = new ol.Map({
            target: 'map',
            layers: [
                osmLayer,
                layer1,
                layer2,
                clusterLayer
            ],
            view: new ol.View({
                projection: 'EPSG:3857',
                zoom: 1,
                center: [0,0],
            }),
        });
    }
     
  </script>
</body>

</html>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM