最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Getting Features from Clusters in OpenLayers? - Stack Overflow

programmeradmin5浏览0评论

I have an array with lots of different locations, with names and pictures and of course longitude and latitude. If I put these onto the map directly, it gets cluttered. So I try to use the Clusters.

Start with creating features:

 for(var i = 0; i < points.length; i++){
     features[i] = new ol.Feature({
     population: 4000,
     name : points[i].name,
     geometry: new ol.geom.Point(
     ol.proj.transform([
     points[i].long,
     points[i].lat],
     'EPSG:4326', oProjection))
     });
 }

I then populate the clusters with a vector with features:

var vSource = new ol.source.Vector({ features: features});

var vFeatures = vSource.getFeatures();

var clusterSource = new ol.source.Cluster({
                   distance: 20,
                   source: vSource});

I then style the clusters with some icons

var clusters = new ol.layer.Vector({
          source: clusterSource,
          style : new ol.style.Style({
                image: new ol.style.Icon(({
                src: 'image/image.png'})),
          text: new ol.style.Text({
                font: '18px Helvetica, Arial Bold, sans-serif',
                text: size.toString(),
                fill: new ol.style.Fill({
                color: '#fff'
                })
})
 map.add(clusters)

I later have an onclick method that should get the "name" from the Feature, but the only thing it can print out is the geometry, it is like the name on the object disapears from Clusters. For example, doing a clusterSource.getFeatures() returns an empty vector, [].

function addOverlays(points){
    for(var i = 0; i<points.length;i++){
        var element = document.getElementById(points[i].id);
        var popup = new ol.Overlay({
            element: element,
            positioning: 'bottom-center',
            stopEvent: false
        });
        map.addOverlay(popup);
        // display popup on click
    }

    // display popup on click
    map.on('click', function(evt) {
        var feature = map.forEachFeatureAtPixel(evt.pixel,
            function(feature, layer) {
                console.log("feature on click: ",feature);
                return feature;
            });
        if (feature) {
            var geometry = feature.getGeometry();
            var coord = geometry.getCoordinates();
            popup.setPosition(coord);
            console.log(feature.get('name'));
            $(element).popover({
                'placement': 'bottom',
                'html': true,
                'content': feature.get('name') //THIS IS THE TROUBLE
            });
            $(element).popover('show');
        } else {
            $(element).popover('destroy');
        }
    });
}

The addOverlay method cannot get the name of the feature, it returns "undefined" which is very strange. Help? Any help please? It is like the features stop existing when added in the cluster.

I have an array with lots of different locations, with names and pictures and of course longitude and latitude. If I put these onto the map directly, it gets cluttered. So I try to use the Clusters.

Start with creating features:

 for(var i = 0; i < points.length; i++){
     features[i] = new ol.Feature({
     population: 4000,
     name : points[i].name,
     geometry: new ol.geom.Point(
     ol.proj.transform([
     points[i].long,
     points[i].lat],
     'EPSG:4326', oProjection))
     });
 }

I then populate the clusters with a vector with features:

var vSource = new ol.source.Vector({ features: features});

var vFeatures = vSource.getFeatures();

var clusterSource = new ol.source.Cluster({
                   distance: 20,
                   source: vSource});

I then style the clusters with some icons

var clusters = new ol.layer.Vector({
          source: clusterSource,
          style : new ol.style.Style({
                image: new ol.style.Icon(({
                src: 'image/image.png'})),
          text: new ol.style.Text({
                font: '18px Helvetica, Arial Bold, sans-serif',
                text: size.toString(),
                fill: new ol.style.Fill({
                color: '#fff'
                })
})
 map.add(clusters)

I later have an onclick method that should get the "name" from the Feature, but the only thing it can print out is the geometry, it is like the name on the object disapears from Clusters. For example, doing a clusterSource.getFeatures() returns an empty vector, [].

function addOverlays(points){
    for(var i = 0; i<points.length;i++){
        var element = document.getElementById(points[i].id);
        var popup = new ol.Overlay({
            element: element,
            positioning: 'bottom-center',
            stopEvent: false
        });
        map.addOverlay(popup);
        // display popup on click
    }

    // display popup on click
    map.on('click', function(evt) {
        var feature = map.forEachFeatureAtPixel(evt.pixel,
            function(feature, layer) {
                console.log("feature on click: ",feature);
                return feature;
            });
        if (feature) {
            var geometry = feature.getGeometry();
            var coord = geometry.getCoordinates();
            popup.setPosition(coord);
            console.log(feature.get('name'));
            $(element).popover({
                'placement': 'bottom',
                'html': true,
                'content': feature.get('name') //THIS IS THE TROUBLE
            });
            $(element).popover('show');
        } else {
            $(element).popover('destroy');
        }
    });
}

The addOverlay method cannot get the name of the feature, it returns "undefined" which is very strange. Help? Any help please? It is like the features stop existing when added in the cluster.

Share Improve this question edited Apr 23, 2016 at 15:24 Jose Gómez 3,2242 gold badges36 silver badges55 bronze badges asked Oct 24, 2014 at 9:09 peturpetur 1,3864 gold badges22 silver badges43 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 10

So with clustering, OL3 creates a new feature that wraps all the clustered features underneath it. If you look at a clustered feature you see this under the values attribute:

values_: Object
  features: Array[19]
  geometry: ol.geom.Point

This is why getFeatures() does not work, when working with cluster features, they only have these two values when they are created.

function isCluster(feature) {
  if (!feature || !feature.get('features')) { 
        return false; 
  }
  return feature.get('features').length > 1;
}

map.on('click', function(evt) {
  var feature = map.forEachFeatureAtPixel(evt.pixel, 
                  function(feature) { return feature; });
  if (isCluster(feature)) {
    // is a cluster, so loop through all the underlying features
    var features = feature.get('features');
    for(var i = 0; i < features.length; i++) {
      // here you'll have access to your normal attributes:
      console.log(features[i].get('name'));
    }
  } else {
    // not a cluster
    console.log(feature.get('name'));
  }
});

I cant add ments yet (not enough reputation), but I want to add my solution on which e.g. Popups will be shown on clustered and unclustered features . Like the example of @Timh.

But when it es to a lower zoom level and the clustering is "dissolved" the popup will just show undefined when you click the feature which was (and technially still is) in a cluster.

So, you can do the same with

if (typeof feature.get('features') === 'undefined') {
  // feature.get('whatever');
} else {
  var cfeatures = feature.get('features');
  for(var i = 0; i < cfeatures.length; i++) {
    //like in  the example of timh
  }
}

and getting e.g Popups from clustered, unclustered and from features which are not clustered (in a visual way) at the moment.

Edit: Example with Popups

Pay attention to your layers and their source, my mistake is that i should set:

layer.getSource().getSource().getFeatures()

instead of:

layer.getSource().getFeatures()

I cannot ment since I don't have the rep but this is a ment to Timh's solution which is good but has a flaw (which is why radhoo has problems with single features as described in his ment).

The "isCluster" function should not check if there are one or more features since it's still a cluster even if it only contains one feature

function isCluster(feature) {
  return !feature || !feature.get('features');
}

So it's better to handle all clusters in the same way and optionally handle feature objects separately.

发布评论

评论列表(0)

  1. 暂无评论