Vale Vale - 25 days ago 15
Javascript Question

How to implement OverlappingMarkerSpiderfier 'click' trigger in MarkerClusterer

It is known that MarkerClusterer is "bugged" in treating markers in the same exact spot, so I added the OMS library in my project.

My goal is to have a cluster "spiderfy" if all of its markers if they are all in the same position.

I must say, my maxZoom level is 22, because otherwise all of the markers are overlapped and you can't actually tell there are more than one.

I managed to arrive at the "if they are all in the same position", but I cannot spiderfy the cluster.

The code to intercept the event is a mixture between this answer (all in the same position)
and this one (override the clickcluster event).

The suggested way to trigger the click event doesn't seem to do the trick for me. Here is the overriding function I wrote:

var mc = new MarkerClusterer(map,markers,options);
mc.onClickZoom = function(mc) {
var marker = mc.cluster_.markers_[0];
console.log("clicking marker");
google.maps.event.trigger(marker, 'click',{});
};


The console indeed logs the "clicking marker", but then the map and the cluster just stay there; nothing happens.

EDIT:
Here are the code modification I have made.


  • Inside the MarkerClusterer source code, I have added a prototype function tu the MarkerClusterer.prototype like so:

    MarkerClusterer.prototype.onClickZoom = function(mcc) {
    return true;
    };

  • Then I added another function to the prototype, which checks if the markers are in the same spot:

    MarkerClusterer.prototype.allInTheSamePosition = function(markers){
    var cont=0;
    var latitudMaster=markers[0].getPosition().lat();
    var longitudMaster=markers[0].getPosition().lng();
    for(var i=0;i<markers.length;i++){
    if(markers[i].getPosition().lat() === latitudMaster & markers[i].getPosition().lng() === longitudMaster ){
    cont++;
    }else{
    return false;
    }
    }
    return (cont==markers.length)
    }

  • Inside the function
    ClusterIcon.prototype.triggerClusterClick
    , after the triggering of the clusterclick, I added these lines to use the above function:

    if (markerClusterer.allInTheSamePosition(this.cluster_.markers_)){
    return markerClusterer.onClickZoom(this);
    }

  • When I instanciated the MarkerClusterer, I rewrote the onClickZoom function to have the code I posted in the original question, so this:

    var mc = new MarkerClusterer(map,markers,options);
    mc.onClickZoom = function(mc) {
    var marker = mc.cluster_.markers_[mc.cluster_.markers_.length-1];
    console.log("clicking marker");
    google.maps.event.trigger(marker, 'click',{});
    };


    Where options is an object containing the styles of the icons and a maxZoom of 22, to be sure the cluster icon is continually displayed.






The code works until I reach the point where the cluster should "spider up". A couple of gifs:
cluster (4) should spider up

Here I click on the first cluster (5) and it successfully takes me to the smaller set, but the click on the (4) does nothing. Click maniacally simply zooms in but does nothing to the cluster

like this, but with the number

This is the code with the markerClusterer.maxZoom set to 14, so the 4 before isn't recognised as a cluster. I just would like to make it understandable that there are 4 more marker under there. I tried to have the marker show the number, then open the spider on click, then close and have the cluster icon again

At this point I'm just desperate to show that the spiderable cluster is clickable, just something that says "there are more in the same location".

Answer

So, apparently 1/2 questions in the comments (and a bunch I consulted before) didn't have a working example, but mine had to, for some reason. I tried to use JFiddle, but it wasn't working for some reason, so I simply solved it by myself. I seriously hope this won't mean another ban, but what do I know.
Here is how to do this:
So the problem is that MarkerCluster creates a single cluster, so activating the click event on it does nothing for OverlappingMarkerSpiderfier.

Follow the steps in my question to edit the MarkerClusterer source, then

  1. (Optional: will require two clicks) Center and zoom on the cluster
  2. (if you did 1, after a second click) Put the markers back on the map (there may be a better way to do it, but I was tight on time)
  3. Hide the cluster icon
  4. Wait for the above steps to be completed (TODO: instead of a setTimeout, find a flag)
  5. Trigger the click event.

Here is the code to be implemented in the MarkerClusterer declaration.:

var mc = new MarkerClusterer(map,markers,options);
//this code overrides the prototype method declared in the source
            mc.onClickZoom = function(mc) {
                var cluster = mc.cluster_;
                var markers = cluster.getMarkers();
                map.setCenter(markers[0].getPosition());
                if(map.getZoom()<17){
                    map.setZoom(17);
                }
                for(i in markers){
                    markers[i].setMap(cluster.getMap());
                    marker = markers[i];
                }
                cluster.clusterIcon_.hide();
                console.log(marker);
                setTimeout(function(){
                    google.maps.event.trigger(marker, 'click');
                },100);

                //documentMap.applyOverlappingIcons();
            };

Please, if you have a better solution, I'm here to learn: comment and I will edit this answer!