1

Is there a way to cluster markers within openlayers as there is within leaflet.

I have many markers which display the various listed buildings within wales and I am wondering if I am able to cluster them and then as a user zooms in the clusters get smaller until an individual marker is left. And then on zoom out a the markers regroup/cluster showing a cluster with numbers on such as how many markers are within a set distance of lets say 10 miles or so?


Is there also a way to ensure that when a cluster size is at 1 it could show the LSMarker style being that of the original cross showed in the image below?

Link to current project so you can see what I mean by the need to cluster data: https://ces-web2.southwales.ac.uk/students/18018815/mitchtut/giscw2/openlayer.htm

Mobile chrome showing previous amount of markers

UPDATE 1 (THIS ISSUE HAS BEEN SOLVED)
Currently getting the error current code

Uncaught ha {message: "Assertion failed. See https://openlayers.org/en/v4.6.5/doc/errors/#58 for details.", code: 58, name: "AssertionError"}

UPDATE 2 Error fixed but geo data not loading within correct area

Current code

var distance = document.getElementById('distance'); //getting the distance from the slider

<!-- var count = 1000; -->
<!-- var features = new Array(count); //creating an array to hold the amount of features for the cluster -->

<!-- var e = 4000; -->
<!-- for (var i = 0; i<count; i++){ -->
<!-- var coordinates = [2 * e * Math.random() - e, 2 * e * Math.random() - e]; -->
<!-- features [i] = new ol.Feature(new ol.geom.Point(coordinates)); -->
<!-- } -->


    
var clusterSource = new ol.source.Cluster({
        distance: parseInt(distance.value,10),
        source: new ol.source.Vector({
                url: 'geoJSON/LSB.kml',
                format: new ol.format.KML({
                extractStyles:false,
            }),
        })
    });

var styleCache = {};

var clusters = new ol.layer.Vector({
    source: clusterSource,
    style: function (feature) {
        var size = feature.get('features').length;
        var 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({
                        colo:'#3399CC'
                    })
                }),
                text: new ol.style.Text({
                    text: size.toString(),
                    fill: new ol.style.Fill({
                        color:'#fff'
                    })
                })
            });
            
            styleCache[size] = style;
        }
            return style;
    }
});

var raster = new ol.layer.Tile({
    source:new ol.source.OSM()
    });
    
distance.addEventListener('input', function(){
    clusterSource.setDistance(parseInt(distance.value));
});



//instantiation of the map within the div class 'mapspce'
var Omap = new ol.Map({
    layers:[raster, clusters],
    target:'mapspce',
    view: new ol.View({
        center: ol.proj.transform(cWales,'EPSG:4326','EPSG:3857'),
        zoom: 8
    })
});
    
4
  • 1
    Yes, place your KML source inside a cluster source as in openlayers.org/en/v4.6.5/examples/cluster.html – Mike Feb 12 at 23:48
  • Thank you, tried adapting that but got some errors, could be because its late but thank you – WMTS Feb 13 at 1:03
  • The source for your ol.source.Cluster should be the ol.source.Vector for the KML not just its url. – Mike Feb 13 at 9:58
  • @Mike I have included this within my code but the points locations are not loading in the correct geographic area now – WMTS Feb 13 at 18:59
1

If your KML source is not working with a cluster source it may contain features which are not Point geometry. You can add a geometryFunction to the cluster source options to ensure only point features are used when clustering:

var clusterSource = new ol.source.Cluster({
        distance: parseInt(distance.value,10),
        geometryFunction: function (feature) {
          var geometry = feature.getGeometry();
          if (geometry.getType() === "Point") {
            return geometry;
          } else if (geometry.getType() === "MultiPoint") {
            return geometry.getPoint(0);
          }
        },
        source: new ol.source.Vector({
                url: 'geoJSON/LSB.kml',
                format: new ol.format.KML({
                extractStyles:false,
            }),
        })
    });
4
  • The KML data does appear to be point data however , I cannot seem to get it to show even with your script, I can get it to work with random coordinate data but the data no longer appears to load, any chance of something missing? Live Code here: ces-web2.southwales.ac.uk/students/18018815/mitchtut/giscw2/… – WMTS Feb 17 at 16:18
  • Could it be that the KML coordinate data within the file is listed like <MultiGeometry><Point><coordinates>-3.08246357229187,53.2285595916199</coordinates></Point></MultiGeometry> is multigeometry the issue? – WMTS Feb 17 at 17:02
  • The error was to do with the KML file, Its fixed, thank you for the help – WMTS Feb 17 at 17:55
  • 1
    A MultiGeometry consisting only of points would result in a MultiPoint geometry in OpenLayers, The geometry function could extract the point from that. You can reduce any geometry to a point using new ol.geom.Point(ol.extent.getCenter(feature.getGeometry().getExtent())) – Mike Feb 17 at 19:15
0

Clustering function now complete issue being that the KML coordinate data within the file is listed as

<MultiGeometry><Point><coordinates>-3.08246357229187,53.2285595916199</coordinates></Point></MultiGeometry>

With Multigeometry data not being picked up by leaflet as this must be a single point

//clustering 2 Eletricboogaloo
var distance = document.getElementById('distance');      

var Source = new ol.source.Vector({
            url:'geoJSON/LSB.KML',
            format: new ol.format.KML({
                extractStyles:false
        })
});

var clusterSource = new ol.source.Cluster({
    distance: parseInt(distance.value,10),
    source: Source
});

vector = new ol.layer.Vector({
    source: clusterSource,
    style: LSMarker
});

var raster = new ol.layer.Tile({
    source:new ol.source.OSM()
    });

//instantiation of the map within the div class 'mapspce'
var Omap = new ol.Map({
    layers:[raster, vector],
    target:'mapspce',
    view: new ol.View({
        center: ol.proj.transform(cWales,'EPSG:4326','EPSG:3857'),
        zoom: 8
    })
});

distance.addEventListener('input',function() {
    clusterSource.setDistance(parseInt(distance.value,10));
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.