Fluster2 0.1.1 with significant performance improvements

Filed under: Google Maps — Matthias Burtscher @ 16. December 2009 20:43 | Comments (32)

Fluster2 in action It’s five days since Fluster2 was released and I had the chance to use it in production the first time. When working on this I realized that it was quite slow, the map didn’t work properly when using >1000 markers (changing zoom mode or dragging the map was very slow, even in Google Chrome). So I tried out some things and found a solution. This is Fluster2 0.1.1 now.

Two things changed:

  • Markers must not be added to the map, only to Fluster. Then Fluster only assigns markers to the map which have to be displayed. This speeds up the whole map (when changing zoom mode or dragging the map) and makes it about 15 times faster (measured with the 200 markers example included in the download package).
  • Fluster only calculates markers and clusters which are in the viewport of the map. When increasing zoom mode, fewer markers/clusters have to be processed. When dragging the map, calculation of the needed markers is triggered.

Download

From now you can download Fluster2 from SourceForge.

Tags: , ,

32 Comments »

  1. Comment by Damien — 28. December 2009 @ 17:54

    I think it’s still slower than markerclusterer by Xiaoxi Wu, but anyway thank for sharing this, it’s a lot great feature :)

  2. Comment by TTA — 31. December 2009 @ 12:15

    Thanks for the script.

    is there any way to remove markers added to Fluster2 ?
    Like the way we add fluster.addMarker(marker), I can’t find any fluster.removeMarker().

    Many Thanks

  3. Comment by AAMK — 4. January 2010 @ 17:55

    This is great and exactly what I was after. Better still it worked first time.

    Could fluster be expanded to:-
    a) include a click event on a single marker so that an infoWindow could be displayed.
    b) that a parameter could be passed so that clusters are only formed when there are say more than x markers. i.e. you would never see a cluster with x or less markers ‘in’ it.

  4. Comment by Brian — 14. January 2010 @ 23:39

    Very nice, but I noticed a conflict with polygon overlays (I’ve only tried this with a polygon). The clusters are no longer clickable. I tried to see if I could change the z-index of the div/marker cluster but no effect.

    Thanks.

  5. Comment by Brian — 14. January 2010 @ 23:58

    Follow-up: I notice this seems to be an issue in markerclusterer, too.

    http://code.google.com/p/gmaps-utility-library-dev/issues/detail?id=152

  6. Comment by Brian — 15. January 2010 @ 17:36

    This fix worked for me:

    In Fluster2.packed.js/Fluster2ClusterMarker.prototype.draw :
    Changed
    this.getPanes().overlayLayer.appendChild(this.div);
    To
    this.getPanes().overlayMouseTarget.appendChild(this.div);

  7. Comment by Pavlo — 2. March 2010 @ 10:29

    thanks for the script! it works very good with my map. i have only one question: where do i have to put a limit on zoom level so that clusters did not show on every zoom level until zoom 19? i would like clusters to show up until apprx. zoom 16, and then i\’d allow for all the markers to show. could you please help me with that small piece of code? thank you!

  8. Comment by DLM — 13. March 2010 @ 11:54

    First, thanks for this great tool. Works great already with xml-loader. However i’m trying to add an extra infoWindow with a mousover event to a cluster by adding an extra addDomListener.

    google.maps.event.addDomListener(this.div, ‘click’, function() {
    me.map.fitBounds(me.cluster.getMarkerBounds());
    });

    google.maps.event.addDomListener(this.div, ‘mouseover’, function() {
    console.log(‘Show infowindow with 3 randoms from cluster’);
    });

    I tried some options already but without succes.
    Will appreciate any help.

  9. Comment by DLM — 15. March 2010 @ 22:33

    Nevermind previous post. Made a workaround that works fine now. Thx anyway.

  10. Comment by JDW — 7. May 2010 @ 18:25

    Great work! I’ve been able to set this up, along with the community-contributed clearAll() function mentioned in an earlier thread on this site, to set up a nice cluster map, complete with filtering by different datasets. Brilliant!

    I thought I’d mention another slight tweak I’ve made. I noticed that whenever I dragged the map, any individual markers would “flicker” off and on. The cluster icons stay put, this only affects single markers.

    I managed to avoid the flicker by amending line 81 of Fluster2Cluster.js from this:

    this.markers[0].setMap(me.map);

    To this:

    if(! this.markers[0].getVisible()) this.markers[0].setMap(me.map);

    Which simply does a check first to see if the marker is already visible.

    Cheers!

  11. Comment by JDW — 7. May 2010 @ 18:47

    Nevermind that last post! Something is not right with my amend, the markers do not come back after zooming in and out (it appears as though once they’re consolidated into a cluster, they still claim to be “visible”, and my logic check is foiled). Anyway, if I fix it I’ll post a solution, otherwise ignore everything I’ve said!

  12. Comment by JDW — 7. May 2010 @ 19:07

    OK, I *think* I’ve solved the flicker, but I don’t know if this hurts performance. It also seems like a shortcoming in the maps API. From what I can tell, when you remove a marker from a map (via .setMap(null)), the marker’s “visibility” is not toggled. So the marker’s getVisibility() method returns a false positive.

    What I’ve done therefore is to explicitly set the visibility status when showing and hiding a marker, via the marker’s setVisibility() method.

    So line 81 becomes:

    if(! this.markers[0].getVisible()) {
    this.markers[0].setMap(me.map);
    this.markers[0].setVisible(true);
    }

    And then what was line 88 becomes:

    this.markers[i].setMap(null);
    this.markers[i].setVisible(false);

    Hope that all made sense…

  13. Comment by Tom — 6. July 2010 @ 09:58

    Hi, first of all, thanks for sharing, but I got a big problem, the sums of the markers are never the same according to the zoom level !

    And sometimes the markers just disappear !

    Here my test URL:

    http://stage.ebuildy.eu/laurent/demo_fluster/commercial1.php

  14. Comment by Grace — 12. July 2010 @ 21:55

    Hi, thanks for this library!
    I’m having a problem using this on mobile devices. It seems that _fluster.getProjection() is undefined when it is first called. Increasing the delay before calling createClusters() seems to solve the problem, but I’m not sure why. Do you have any ideas as to what might be causing this?

  15. Comment by Mike — 16. July 2010 @ 00:24

    @Brian, thank you – I was having that exact same problem!

  16. Comment by Grace — 19. July 2010 @ 16:41

    It seems like I solved my problem. Here is my solution in case anyone runs into similar issues.

    The call to createClusters should be moved to the draw method of Fluster2ProjectionOverlay instead of being called after an arbitrary delay. Draw is called automatically when the projection is ready. This also makes the explicit zoom handler (and its delay) unnecessary, as overlay.draw() is called whenever the view changes.

    Without the arbitrary delays the clusters work correctly on slow hardware.

  17. Comment by Peter — 31. July 2010 @ 00:58

    Has anyone come up with a solution to AAMK’s feature request?
    AAMK:
    “a) include a click event on a single marker so that an infoWindow could be displayed.
    b) that a parameter could be passed so that clusters are only formed when there are say more than x markers. i.e. you would never see a cluster with x or less markers ‘in’ it.”

  18. Comment by Peter — 2. August 2010 @ 16:02

    I solved part b in case anyone is interested. Here are the steps and code to add (I’m using Fluster2.packed.js so this is the changes for that version, use a text search to find the quoted code):
    1. open Fluster2.packed.js
    2. change:
    function Fluster2(_map,_debug){
    to:
    function Fluster2(_map,_nummarkers,_debug){
    3. change:
    if(!done){var cluster=new Fluster2Cluster(me,marker);
    to:
    if(!done){var cluster=new Fluster2Cluster(me,marker,_nummarkers);
    4.change:
    if(this.markers.length==1){this.markers[0].setMap(me.map)}else if(this.markers.length>1){
    to:
    if(this.markers.length=nummarkers){

  19. Comment by Peter — 2. August 2010 @ 16:04

    5. change your fluster code on the webpage where your map is loaded (ie index.php):
    var fluster = new Fluster2(map,50);
    where 50 is the cutoff number of markers you want displayed without clustering.
    Done!

  20. Comment by Peter — 3. August 2010 @ 20:40

    I solved part a if anyone needs that. Add the following code after var marker in your page calling the map:

    var name = markers[i].getAttribute(“name”);
    var text = name, markers[i].getAttribute(“address”);

    var infowindow = new google.maps.InfoWindow({
    content: text
    });

    var marker = new google.maps.Marker({position: latlng,
    title: name});

    google.maps.event.addListener(marker, “click”, function() {
    infowindow.open(map,marker);
    });

  21. Comment by Alex Hall — 4. August 2010 @ 14:50

    In reference to a question about stopping marker creation after a zoom level I used the following:

    // Add a listener to the zoom change event so we can change the grid size
    // of the cluster script. Should be dynamic!
    google.maps.event.addListener(map, “zoom_changed”, function() {

    var zoomLevel = map.getZoom();

    switch(true){
    case zoomLevel > 13:
    fluster.gridSize = 0;
    break;
    case zoomLevel > 12:
    fluster.gridSize = 10;
    break;
    case zoomLevel > 7:
    fluster.gridSize = 20;
    break;
    case zoomLevel > 5:
    fluster.gridSize = 40;
    break;
    default:
    fluster.gridSize = 60;
    break;
    }

    });

    It basically checks the current zoom and if it’s above 13 (quite close), it won’t cluster anything. You can change the rest to whatever you want. This worked well for me.

  22. Comment by Peter — 5. August 2010 @ 00:35

    @Grace. Can you give me a hint about where this is in Fluster2.packed.js ?

    “It seems like I solved my problem. Here is my solution in case anyone runs into similar issues.

    The call to createClusters should be moved to the draw method of Fluster2ProjectionOverlay instead of being called after an arbitrary delay. Draw is called automatically when the projection is ready. This also makes the explicit zoom handler (and its delay) unnecessary, as overlay.draw() is called whenever the view changes.

    Without the arbitrary delays the clusters work correctly on slow hardware.”

  23. Comment by Peter — 6. August 2010 @ 15:42

    never mind. solved my own question. In Fluster2.packed.js the call in “function Fluster2ProjectionOverlay(map){” should be “this.createClusters;”

  24. Comment by Simon — 12. August 2010 @ 09:46

    I am trying to change the images for the backgrounds but no matter what I change the image url’s to it will always use the origonal google radial images. How can I change them?

  25. Comment by Krishna sagar — 19. August 2010 @ 07:08

    Can any one pls suggest me how to retrieve the number of clusters in the click event of the cluster so that I can determine the zoom level proportional to the number of markers in the cluster. Thanks

  26. Comment by Luis — 23. August 2010 @ 22:54

    Hi all…

    I could make this script work fine but now I have got a issue that we need to solve, here we go and I hope someone can help us:

    We have a number for each point wich is going to be added on the map, so what we need to do is sum each one of this number when more than a point is clustered. For example, if we have two points and they both have numbers 3 and 4 when it is clustered we will have number 7 on the marker.

    Does anyone have an idea to help us doing that?

    Kind Regards. Luis!

  27. Comment by TuteC — 9. October 2010 @ 00:01

    Hi! Thanks for this library!

    I’m using it on a map with ~7500 markers, and it swallows my CPU when given a close zoom. With zooms < 8 it computes fast, but when getting closer, it stalls many seconds.

    I tried the solution given by Alex Hall to no avail. And I thought it didn't compute non visible areas, so I can't explain the behaviour.

    How can we fix this?

    Kind regards,

    Eugenio.

  28. Comment by Simon — 12. November 2010 @ 22:15

    @TuteC I am having the same issue with thousands of points to display on the map. It might just be the raw number of points that makes this hard. I was thinking I might have to requery the points based on the visible area of the map and accomplishing it this way using ajax or something.

    Did you find a solution to what you were trying to do?

    Thanks!

    Simon.

  29. Comment by Simon — 13. November 2010 @ 16:54

    Hello All! Just wanted to say I love the Fluster code and it is working well for me! I have it implemeted on one of my sites, a running site that tracks running routes all around the world. If you want to see Fluster in acton have a look at RunMyRoute @ http://www.RunMyRoute.com.

    Simon.

  30. Comment by Simon — 13. November 2010 @ 16:55

    @Grace and @Peter,

    I was trying to correct the issue with the delay and moving the call to the createClusters to Fluster2ProjectionOverlay and haven’t been able to get it to work. Can you expand on what you did here to get it functioning?

    Thanks!

    Simon.

  31. Comment by TuteC — 13. February 2011 @ 00:32

    @Simon, I didn’t get it better yet, so I’m looking forward to find/cooperate with a soluction!
    Regards,
    Tute.

  32. Comment by TuteC — 9. March 2011 @ 19:13

    I’m using with 8.000 marks the following similar library, and now it works good!
    Thank you all very much.

    http://google-maps-utility-library-v3.googlecode.com/svn/tags/markerclusterer/1.0/examples/

Leave a comment