Giter Site home page Giter Site logo

sintef-9012 / prunecluster Goto Github PK

View Code? Open in Web Editor NEW
551.0 35.0 131.0 68.52 MB

Fast and realtime marker clustering for Leaflet

License: MIT License

JavaScript 9.90% TypeScript 87.05% CSS 3.06%
leaflet realtime cluster markers maps markercluster realtime-marker-clustering

prunecluster's Introduction

PruneCluster

PruneCluster is a fast and realtime marker clustering library.

Example 1: 150 000 randomly moving markers.

Example 2: Realtime clusters of tweets.

It's working with Leaflet as an alternative to Leaflet.markercluster.

The library is designed for large datasets or live situations. The memory consumption is kept low and the library is fast on mobile devices, thanks to a new algorithm inspired by collision detection in physical engines.

Features

Realtime

The clusters can be updated in realtime. It's perfect for live datasets or datasets you want to filter at runtime.

Fast

Number of markers First step Update (low zoom level) Update (high zoom level)
100 instant instant instant
1 000 instant instant instant
10 000 14ms 3ms 2ms
60 000 70ms 23ms 9ms
150 000 220ms 60ms 20ms
1 000 000 1.9s 400ms 135ms

These values are tested with random positions, on a recent laptop, using Chrome 38. One half of markers is moving randomly and the other half is static. It is also fast enough for mobile devices.

If you prefer real world data, the 50k Leaflet.markercluster example is computed in 60ms (original).

Weight

You can specify the weight of each marker.

For example, you may want to add more importance to a marker representing an incident, than a marker representing a tweet.

Categories

You can specify a category for the markers. Then a small object representing the number of markers for each category is attached to the clusters. This way, you can create cluster icons adapted to their content.

Dynamic cluster size

The size of a cluster can be adjusted on the fly (Example)

Filtering

The markers can be filtered easily with no performance cost.

Usage

Classic Way

	<!-- In <head> -->
	<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
  integrity="sha512-M2wvCLH6DSRazYeZRIm1JnYyh22purTM+FDB5CsyxtQJYeKq83arPe5wgbNmcFXGqiSH2XR8dT/fJISVA1r/zQ=="
  crossorigin=""/>

	<!-- In <head> or before </body> -->
	<script src="https://unpkg.com/[email protected]/dist/leaflet.js"
  integrity="sha512-lInM/apFSqyy1o6s89K4iQUKg6ppXEgsVxT35HbzUupEVRh2Eu9Wdl4tHj7dZO0s1uvplcYGmt3498TtHq+log=="
  crossorigin=""></script>
	<script src="PruneCluster/dist/PruneCluster.js"></script>

Webpack & NPM

npm install exports-loader prunecluster

import { PruneCluster, PruneClusterForLeaflet } from 'exports-loader?PruneCluster,PruneClusterForLeaflet!prunecluster/dist/PruneCluster.js'

Example

var pruneCluster = new PruneClusterForLeaflet();

...
var marker = new PruneCluster.Marker(59.8717, 11.1909);
pruneCluster.RegisterMarker(marker);
...

leafletMap.addLayer(pruneCluster);

PruneClusterForLeaflet constructor

PruneClusterForLeaflet([size](#set-the-clustering-size), margin);

You can specify the size and margin which affect when your clusters and markers will be merged.

size defaults to 120 and margin to 20.

Update a position

marker.Move(lat, lng);

Deletions

// Remove all the markers
pruneCluster.RemoveMarkers();

// Remove a list of markers
pruneCluster.RemoveMarkers([markerA,markerB,...]);

Set the category

The category can be a number or a string, but in order to minimize the performance cost, it is recommended to use numbers between 0 and 7.

marker.category = 5;

Set the weight

marker.weight = 4;

Filtering

marker.filtered = true|false;

Set the clustering size

You can specify a number indicating the area of the cluster. Higher number means more markers "merged". (Example)

pruneCluster.Cluster.Size = 87;

Apply the changes

Must be called when ANY changes are made.

pruneCluster.ProcessView();

Add custom data to marker object

Each marker has a data object where you can specify your data.

marker.data.name = 'Roger';
marker.data.ID = '76ez';

Setting up a Leaflet icon or a Leaflet popup

You can attach to the markers an icon object and a popup content

marker.data.icon = L.icon(...);  // See http://leafletjs.com/reference.html#icon
marker.data.popup = 'Popup content';

Faster leaflet icons

If you have a lot of markers, you can create the icons and popups on the fly in order to improve their performance.

function createIcon(data, category) {
    return L.icon(...);
}

...

marker.data.icon = createIcon;

You can also override the PreapareLeafletMarker method. You can apply listeners to the markers here.

pruneCluster.PrepareLeafletMarker = function(leafletMarker, data) {
    leafletMarker.setIcon(/*... */); // See http://leafletjs.com/reference.html#icon
    //listeners can be applied to markers in this function
    leafletMarker.on('click', function(){
    //do click event logic here
    });
    // A popup can already be attached to the marker
    // bindPopup can override it, but it's faster to update the content instead
    if (leafletMarker.getPopup()) {
        leafletMarker.setPopupContent(data.name);
    } else {
        leafletMarker.bindPopup(data.name);
    }
};

Setting up a custom cluster icon

pruneCluster.BuildLeafletClusterIcon = function(cluster) {
    var population = cluster.population, // the number of markers inside the cluster
        stats = cluster.stats; // if you have categories on your markers

    // If you want list of markers inside the cluster
    // (you must enable the option using PruneCluster.Cluster.ENABLE_MARKERS_LIST = true)
    var markers = cluster.GetClusterMarkers() 
        
    ...
    
    return icon; // L.Icon object (See http://leafletjs.com/reference.html#icon);
};

Listening to events on a cluster

To listen to events on the cluster, you will need to override the BuildLeafletCluster method. A click event is already specified on m, but you can add other events like mouseover, mouseout, etc. Any events that a Leaflet marker supports, the cluster also supports, since it is just a modified marker. A full list of events can be found here.

Below is an example of how to implement mouseover and mousedown for the cluster, but any events can be used in place of those.

pruneCluster.BuildLeafletCluster = function(cluster, position) {
      var m = new L.Marker(position, {
        icon: pruneCluster.BuildLeafletClusterIcon(cluster)
      });

      m.on('click', function() {
        // Compute the  cluster bounds (it's slow : O(n))
        var markersArea = pruneCluster.Cluster.FindMarkersInArea(cluster.bounds);
        var b = pruneCluster.Cluster.ComputeBounds(markersArea);

        if (b) {
          var bounds = new L.LatLngBounds(
            new L.LatLng(b.minLat, b.maxLng),
            new L.LatLng(b.maxLat, b.minLng));

          var zoomLevelBefore = pruneCluster._map.getZoom();
          var zoomLevelAfter = pruneCluster._map.getBoundsZoom(bounds, false, new L.Point(20, 20, null));

          // If the zoom level doesn't change
          if (zoomLevelAfter === zoomLevelBefore) {
            // Send an event for the LeafletSpiderfier
            pruneCluster._map.fire('overlappingmarkers', {
              cluster: pruneCluster,
              markers: markersArea,
              center: m.getLatLng(),
              marker: m
            });

            pruneCluster._map.setView(position, zoomLevelAfter);
          }
          else {
            pruneCluster._map.fitBounds(bounds);
          }
        }
      });
      m.on('mouseover', function() {
        //do mouseover stuff here
      });
      m.on('mouseout', function() {
        //do mouseout stuff here
      });

      return m;
    };
};

Redraw the icons

Marker icon redrawing with a flag:

marker.data.forceIconRedraw = true;

...

pruneCluster.ProcessView();

Redraw all the icons:

pruneCluster.RedrawIcons();

Acknowledgements

This library was developed in context of the BRIDGE project. It is now supported by the community and we thank the contributors.

Licence

The source code of this library is licensed under the MIT License.

prunecluster's People

Contributors

adimasci avatar brice-morin avatar brunolellis avatar cadrach avatar disarticulate avatar fungiboletus avatar hbwales avatar marcbanc avatar maxvonhippel avatar mordka avatar peergynt avatar rhynix avatar robbiethewagner avatar rolanddu avatar simison avatar undr avatar uniphil avatar valerio-bozzolan avatar vitalik74 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

prunecluster's Issues

'overlappingmarkers' event with multiple instances of PruneClusterForLeaflet

I have 2 instances of PruneClusterForLeaflet. When it comes time to spiderfy, one instance calls 'overlappingformarkers', however, both instances receive the event. The result is all the markers in the cluster are drawn twice (once for each instant).

Without breaking schema or backwards compatibility, this is the workaround I implement.

  1. Pass in the cluster that needs to be spiderfied when firing 'overlappingmarkers'.

                _this._map.fire('overlappingmarkers', {
                    cluster: _this,
                    markers: markersArea,
                    center: m.getLatLng(),
                    marker: m
                });
    
  2. Only Spiderfy the cluster that requires the spiderfication (is that a word?)

this._map.on('overlappingmarkers', function(data) {
    if (data.cluster === this._cluster) {
        this.Spiderfy(data);
    }
}, this);

Open a popup

I would like to call the layer.openPopup() method on a marker.

Beautiful API

The current API can be improved. The version 2 should have something closer to the Leaflet API.

  • Sanitize user inputs
  • GeoJSON support
  • Separate documentation examples and unit tests

Accessing markers inside a cluster

I'm trying to hover a document, and pulse the cluster that the points from that document are in, I know I can find the markers inside a cluster if I have the cluster already, but for each document I am just saving the markers. How can I look up the cluster if I know the markers?

Support for GeoJSON-Data

Hi everyone,
seems like a really nice project. I was just wondering if it is possible to use GeoJSON-Data as Input.

Thanks!

Bower complaining

FYI, getting this when declaring "PruneCluster": "~1.1.0" at bower.json:

bower PruneCluster#~1.1.0     mismatch Version declared in the json (0.10.1) is different than the resolved one (1.1.0)
bower PruneCluster#~1.1.0 invalid-meta PruneCluster is missing "main" entry in bower.json
bower PruneCluster#~1.1.0 invalid-meta PruneCluster is missing "ignore" entry in bower.json

Show all markers without clusters with custom zoom

In may application I want show all markers if zoom > 15. First, I think change leafletView.Cluster.Size = 1;. But I have many Lapping Markers and cluster show in this marker and marker show on map stand not well. Second, I think set this._map.fire('overlappingmarkers', ...) to show Lapping Markers. But it is not work.

Finally, I want get like that http://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld-maxzoom.388.html . They use option disableClusteringAtZoom.

GetClusterMarkers() length not match Cluster population

JSFiddle then check console

its little modifcation of example:

var leafletView = new PruneClusterForLeaflet();

leafletView.BuildLeafletClusterIcon = function(cluster) {
    var markers = cluster.GetClusterMarkers();
    console.log('blci', markers.length, cluster.population);
    console.assert( markers.length === cluster.population, 'Not match!');
    //console.log(markers);

    return PruneClusterForLeaflet.prototype.BuildLeafletClusterIcon.call(this, cluster);
};

How to disable clustering

I'd like to have a checkbox that allows users to disable clustering on the map if they would like. Is there a quick way to disable clustering, or do I need to make a whole new layer?

Force decluttering of markers at a certain zoom level

I'm coming to PruneCluster from Leaflet markerCluster, and the performance is much, much better. What I am building is a simple mobile app with about 1000 markers, and the difference in performance is very noticeable on phones/tablets.

But there is one feature of markerCluster that I can't yet find a solution to in PruneCluster: the disableClusteringAtZoom option. That is, I would like to be able to have the map disable clustering after a certain zoom level.

How would I go about doing this?

Using SVG paths as marker icon

Hi there,

Do you have any sample code for PruneCluster I can see that touches using something like below?

var icon = L.marker(latlng, {
icon: L.divIcon({
className: 'site-marker markers-'+id+'-'+selected,
iconSize: new L.Point(marker_width, marker_height),
html: svg })
.......

Documentation unclear on several points

Hi all,
This is an interesting project, and looks to more versatile than the more popular markercluster plugin! However, there's a thing I can't quite figure out reading the project description and code. I'm trying to edit the 10000 random categories example:

http://sintef-9012.github.io/PruneCluster/examples/random.10000-categories-2.html

I want the cluster icon to be changed based on data stored in the markers. In the code of the above page, I add the following code to the for loop that creates the markers:

marker.data.quantity= Math.floor(Math.random() * 20) + -10;

This adds a data attribute that holds a random value of -10 to 10 in it. I want to edit the cluster icon itself to show a total of all marker's quantity attribute. For example, if there are 10 markers in a cluster, with 8 having a quantity of 10, and 2 having a quantity of -10, the cluster containing these markers should have "60" written on it.

The first problem I get is this: in order to get the value out of the markers again, I have to loop through all the markers in the cluster. I could do this by adding this code to the BuildLeafletClusterIcon function:

var markers = cluster.getClusterMarkers();

However, in order to use this function, I have to do this:

"(you must enable the option using PruneCluster.Cluster.ENABLE_MARKERS_LIST = true)"

But I can't figure out where to put this line of code. I have pasted this line to several places in my code, but I keep getting the error that cluster.getClusterMarkers() is not a function.

Then the second problem: if I got the above code working, and the had a variable that contained the sum of the marker quantity data (60 in my example), I don't see how to pass this variable to the draw function from the BuildLeafletClusterIcon function.

Can someone please explain how to do this?

Don't restore _removeFlag

If I add two or more arrays of markers to the cluster, when I remove an array their markers are marked with the _removeFlag = true.

If I go back to add this array their markers continue marked with _removeFlag = true and then if I remove other array of markers this array is also removed (their points).

I tried to solve it temporarily with:

        for (i = 0, l = this._markers.length; i < l; ++i) {
            this._markers[i]._removeFlag = false;
        }

before

        for (var i = 0, l = markers.length; i < l; ++i) {
            markers[i]._removeFlag = true;
        }

        var newMarkersList = [];
        for (i = 0, l = this._markers.length; i < l; ++i) {
            if (!this._markers[i]._removeFlag) {
                newMarkersList.push(this._markers[i]);
            }
        }

        this._markers = newMarkersList;

It solves the problem but sure there's a better way.

why dont extends L.Marker !?

we loose all events on markers ('on'...) , aslo all existing methods such as bindPopup
why not ClusterObject.prototype = new L.Marker() ??
it will be much better like that ! map.markers.RegisterMarker(new L.Marker(position, opts));

Implement a filtering feature

In the current implementation, the plugin doesn't support filtering and the application must delete and add a lot of markers a lot of times. It's not beautiful and it's slow.

Minimizing Clicks and getting bounds for filtered markers

Please see: http://www.exploringspatial.com/#demo/6

This is roughly how I'm doing interactive filtering. Is it necessary to remove the markers first?

var markers = layer.GetMarkers();
layer.RemoveMarkers();
var marker;
for (var i =0; i<markers.length,i++){
    marker = marker[i];
    marker.filter = this.search.filterMarker(marker.data);
    layer.RegisterMarker(marker);
}
layer.ProcessView();
layer.FitBounds();

The problem with my approach is that FitBounds() includes filtered markers. I really want to zoom in on the markers that are visible. What is the best way to do this? If I eliminate the RemoveMarkers() and RegisterMarker(), and just toggle the filter attribute and run ProcessView(), nothing changes.

The other issue, especially when filtering, is that some clusters must be clicked three or four clicks that only change the zoom before the cluster expands, even though no other markers or clusters are visible on the map. My expectation was that when I click the cluster it should expand. I should have to click it 4 times.

Thanks!

Slow drag

Using PruneCluster, if I create a single marker (not part of a cluster), dragging it is very slow. If I remove PruneCluster include or if I use MarkerCluster, the drag speed is ok.

I create a test page (it's your example with a draggable marker added) at http://jsfiddle.net/neup69fo/

Weight example

Very efficient library, congratulations.

Just one point :
We don't know how to weight the markers, documentation is not very clear on that point.
There is no Weight example in the .zip file ?

Your lights please ?

Many thanks

Add ability to force redraw of cluster icon even if no markers changed

I would like the ability force the BuildLeafletClusterIcon function to be called by ProcessView even if no underlying markers have been added/removed/changed.

My use case involves showing a different cluster icon based on some of the .data fields on the individual markers in the cluster. If any of those .data fields change in a way that would cause a change to the icon, I want to be able to call ProcessView to redraw the cluster, thus displaying the correct icon.

Currently the ProcessView function is optimized so that if there is no structural change to the underlying markers it does not redraw the icon. Obviously this is there for performance reasons, and should not be changed.

I propose the ability to set a cluster.data.forceRedraw flag on the cluster prior to calling ProcessView. ProcessView would check for this flag and then redraw the cluster, regardless of whether or not the underlying marker structure has changed.

PruneCluster with ContextMenu

Hi there,

I have been able to use MarkerCluster with contextmenu but my similar implementation with PruneCluster is not working. Here is my code:

var marker = new PruneCluster.Marker(coordinates[1],coordinates[0], {
                icon: L.divIcon({ 
                        className: 'class-name',
                        iconSize: new L.Point(width, height), 
                        html: svg
                        }),
                        contextmenu: true,                              
                        contextmenuItems: [
                            {
                                text: 'Show Information',
                                index: 0,
                                value:"name",
                                callback:function(key,options){
                                    }},
                            {
                                separator: true,
                                index: 1 }
                        ]
            });
            pruneCluster.RegisterMarker(marker);

Any help would put me one step closer to demoing this to my manager.

Thanks,
Brian

more detailed bounds/hull

A feature in markercluster, that I miss here is the ability to show detailed bounds/hull (area with the inlcuded markers) on mouseover.
cluster.bounds only includes max/min lat and lon which will give me a rectangle.

It would be nice to add a builtin "showBoundsOnMouseover" or at least give access to detailed bounds.

As an alternative: is it possible to get a list of all included Markers from a cluster, to calculate the confex hull?

Spiderfy based on cluster size

I want to change the cluster click behaviour in this way: when cluster size is bigger than 20 zoom to bounds else spiderfy cluster. At max zoom level I want to spiderfy without checking cluster size.
I done this with MarkerCluster but I don't know how to do this with PruneCluster.

I tried to override BuildLeafletCluster in this way:

    leafletView.BuildLeafletCluster=function(cluster,position) {
        var _this=this;
        var m=new L.Marker(position,{
            icon: this.BuildLeafletClusterIcon(cluster)
        });

        m.on('click',function() {
          var markersArea=_this.Cluster.FindMarkersInArea(cluster.bounds),
              b, bounds, zoomLevelBefore, zoomLevelAfter;
          console.log("CLICK",markersArea.length);
          if (markersArea.length>20) {
            b=_this.Cluster.ComputeBounds(markersArea);
            if (b) {
                bounds=new L.LatLngBounds(new L.LatLng(b.minLat,b.maxLng),new L.LatLng(b.maxLat,b.minLng));
                zoomLevelBefore=_this._map.getZoom();
                zoomLevelAfter=_this._map.getBoundsZoom(bounds,false,new L.Point(20,20));
                if (zoomLevelAfter===zoomLevelBefore) {
                    _this._map.fire('overlappingmarkers',{
                        cluster: _this,
                        markers: markersArea,
                        center: m.getLatLng(),
                        marker: m
                    });
                    _this._map.setView(position,zoomLevelAfter);
                } else {
                    _this._map.fitBounds(bounds);
                }
            }
          } else {
            /*  ----- AND NOW?!? ----- */
          }
        });

        return m;
    };

In the else clause what I have to do?
And then, is it possible to avoid standard code duplication?

Thanks.

Group by categories

Hi
Is there a way to goup markers only by categories (i.e. each cluster contains only a certain category) ?
Nice work. Thanks.

Remove Prune layer

Good morning,
First of all congratulations for your nice plugin. I am dealing with thousands of markers and your solution is the only one which works fast enough.
I have an interface with several dropdownlists. It appears that when i do a second selection, the cluster from the first selction are kept in the map.

I tried the clearLayers() and got an error, i also tried to use the RemoveMarkers, the ProcessView but the different selections are adding to each other to create cluster with unrealistic numbers. This is the code for the PruneLayer when the selection of a dropdownlist is changed:

var z = 0;
var PruneMarkers = [];

PruneLayer.RemoveMarkers(PruneMarkers);
LeafletMap.removeLayer(PruneLayer);

for (var i in jsonData.sample) {
    for (var j in jsonData.sample[i].data) {

        var counter = jsonData.sample[i].data[j]
        var marker = new PruneCluster.Marker(counter.lat, counter.lon, {
            desc: jsonData.sample[i].decription 
        });
        PruneMarkers.push(marker);
        PruneLayer.RegisterMarker(marker);
        z++;
        //updateProgressBar(z, 10000);
    }
}

PruneLayer.PrepareLeafletMarker = function (marker, data) {
    var iconUrl = 'Scripts/images/marker-icon.png'
    marker.setIcon(L.icon({
        iconUrl: iconUrl,       
        shadowUrl: 'Scripts/images/marker-shadow.png',  
    }));
    if (marker.getPopup()) {
        marker.setPopupContent(data.desc, { minWidth: 320 });
    } else {
        marker.bindPopup(data.desc, { minWidth: 320 });
    }
};

LeafletMap.addLayer(PruneLayer);

Thanks for your help on that.
1 last things: do you plan to have a showCoverageOnHover feature like in the MarkerClusterer plugin? it is quite useful sometimes.

Thanks again

Sylvain

CircleMarker support

Thanks for a great library, works like a charm so far.
Would be nice if you could also use CircleMarker (the workaround is to specify a circle icon of course).

Edit: or support for the Awesome Markers plugin

Setting spiderfier options

I would like to change spiderfyDistanceMultiplier parameter because my icons are a little wide (about 120px).

What is the best option?

I thought about changing PruneClusterForLeaflet's initialize function to something like:

function(size: number = 120, clusterMargin: number = 20, spiderfyDistanceMultiplier: number = 1)

but then I must create an instance of PruneClusterForLeaflet passing size, clusterMargin and the new one.

Do you have any better suggestion?

I've created a plunker showing it: http://plnkr.co/edit/WmtpkEqSDJFuFeuiYP54?p=preview

bindPopup is not working

Thanks for alternative clustering plugin. It's works really fast. I can't wait to add it to our project :) The only one missing feature, is that bindPopup is not working with marker.

Hope you will implement it soon.

Mouseover function when hovering a cluster

I am trying to apply mouseover and mouseout events in the pruneCluster.BuildLeafletClusterIcon function, but I haven't been having much luck. I was trying something like:

pruneCluster.BuildLeafletClusterIcon = function(cluster) {
cluster.on('mouseover', function() {
//do mouseover stuff
}
}

This approach seemed to work for clusters greater than 2 in size or perhaps just random clusters, not sure. Any ideas how to do this correctly?

Dealing with multiple categories

Hi,
is there a way to dea with multiple categories like 1,2 instead of just 1 ? So we could have only one marker in the main view and at least one marker in each category layer ?
thanks and congratulations for your work

Set an icon for each marker

Hi, thanks for this library, it's really wonderful!
I am wondering if it's easy to set a special icon for each icon, not for all?

For example,

var markers = new L.MarkerClusterGroup();
for (var i = 0; i < Dat.length; i++) {
  var latlng = new L.LatLng(Dat[i].lat, Dat[i].lon);
  var popup = L.popup({"keepInView": true, 'maxWidth': 800}).setContent("<img src='img/Tibetan antelope.jpg'>");
  var myIcon = new LeafIcon({iconUrl: Dat[i].icon});
  var marker = L.marker(latlng, {icon: myIcon}).bindPopup(popup);
  markers.addLayer(marker);
}

PrepareView moves marker after toggling filtered properties on two markers in same cluster

Steps to reproduce:

  1. Create two markers close enough so that they are clustered together at a particular zoom level.
  2. Set the 'filtered' property on one of them to true
  3. call ProcessView()
  4. Toggle the filtered properties on both markers
  5. call ProcessView() again

The visible marker will slide over to where the hidden marker was.

The expected behavior should be that the visible marker becomes hidden and the hidden marker becomes visible.

This becomes a significant problem in scenarios where the two markers have different leaflet icons.

Fiddle: http://jsfiddle.net/johnmcase/y08v84mc/

Issues adding markers a second time

When I first load my page, I can add markers and geoJson and all my custom stuff and remove markers and everything seems to work. However, if I change routes, I get issues. When only using markers, and no geoJson, anytime I try to switch routes I get:

Uncaught Error: Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.

This is usually a problem with too many outlets or malformed html, when using Ember, but without using PruneCluster, I do not have this issue.

If I enable my custom geoJson stuff, for trying to add and remove shapes, I get a different error, mentioned here: Leaflet/Leaflet#2947

categories

hey! do you have an example for clustering with categories with a reallife example? is it possible to calculate not the markes count, but the sum of the categorie (-3 to 3)? thanks a lot in advance

ReferenceError

I am just starting to explore using PruneCluster. When I attempt to download and run a PruneCluster example locally I receive the following console error:

ReferenceError: L is not defined on line 352 of PruneCluster.js

Also: the same reference error on line 19 of random.100.html

I am running random.100.html locally. Any guidance would be appreciated.

Thanks,
Roland

Sometimes a marker gets stuck and does not disappear

I have a slider with a date range that the user can drag to change visible markers/clusters. I use the filtered property to show/hide markers/clusters.

Sometimes when the user changes the date interval one or more markers (never a cluster) get stuck.

I simulated the behaviour in this jsfiddle: http://jsfiddle.net/enNVz/132/

The fiddle simulates a number of user interval changes and as you can see one or two markers almost always get stuck and won't disappear.

You can click on a marker to show it's date. If you drag the slider and change the date interval manually you can see that the marker won't go away.

Many thanks for a great plugin!

Redrawing icons doesn't work for spiderfied markers

In my application, I override the PrepareLeafletMarker() call to change the color of the marker icon on click. This works well for regular markers, using the forceIconRedraw parameter and pruneCluster.ProcessView().

But it doesn't work on spiderfied markers. The click event I registered in PrepareLeafletMarker() gets called, but the icons in the map don't get redrawn.

remove prune cluster instance

when i have

pruneCluster = new PruneClusterForLeaflet()

is it possible to destroy it? like pruneCluster.remove() ?

Improved clusters animations

Hi !
I'am trying to tune a bit your project to set an animation between each zoom event. (when a zoomIn, the old cluster go slowly to the new one .. )
But i'm getting some issues to do that :/
I don't understand how to save for example the old clusters, for after check if a new clusters is inside a old one.
(i'm lost with the references between all objects ^^)
Thank's in advance

Debounce ProcessView

@brice-morin has a disengageable mouse-wheel and he suggested to wait few ms before updating the view.

Leaflet already debounces a bit the zoom events, but it's not enough for this kind of user.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.