Giter Club home page Giter Club logo

leaflet.markercluster.layersupport's Introduction

Leaflet.MarkerCluster.LayerSupport

Sub-plugin for Leaflet.markercluster plugin (MCG in short); brings compatibility with L.Control.Layers and other Leaflet plugins. I.e. everything that uses direct calls to map.addLayer and map.removeLayer.

Leaflet.markercluster plugin provides beautiful animated Marker Clustering functionality.

Leaflet is the leading open-source JavaScript library for mobile-friendly interactive maps.

GitHub releases npm

Size: 6 kB minified, < 2 kB gzipped.

NOTE: if your usage requires only compatibility of MCG with L.Control.Layers, you might be interested in this more simple plugin: Leaflet.FeatureGroup.SubGroup.

Requirements

Demos

Usage instructions

Quick Guide

HTML:

<!-- After Leaflet and Leaflet.markercluster scripts -->
<script src="leaflet.markercluster.layersupport.js"></script>

JavaScript:

var map = L.map("map"),
    mcgLayerSupportGroup = L.markerClusterGroup.layerSupport(options),
    myLayerGroup = L.layerGroup(arrayOfMarkers);
    
mcgLayerSupportGroup.addTo(map);
mcgLayerSupportGroup.checkIn(myLayerGroup); // <= this is where the magic happens!

myLayerGroup.addTo(map);

Now adding the Layer Group to the map adds clustered markers!

Works also with individual markers, so this means it should virtually be compatible with any plugin that adds to / removes markers from map (e.g. LeafletSlider).

Installing the sub-plugin

Local copy

  1. Download the "leaflet.markercluster.layersupport.js" file from the v2.0.1 release.
  2. Place the file alongside your page.
  3. Add the script tag (see Quick Guide > HTML) to your page after Leaflet and Leaflet.markercluster scripts.

CDN

You can alternatively use the free unpkg CDN service, but keep in mind that it "is a free, best-effort service and cannot provide any uptime or support guarantees".

<!-- After Leaflet and Leaflet.markercluster scripts -->
<script src="https://unpkg.com/[email protected]/dist/leaflet.markercluster.layersupport.js"></script>

npm

  1. Add this package to your project:

    $ npm install leaflet.markercluster.layersupport --save
  2. If you are using a bundling tool, import in your JavaScript. It only performs the side effect of attaching to the global L namespace, so you do not need to store it into a local variable or import a namespace.

    require('leaflet.markercluster.layersupport');
    // Or with ES6:
    import 'leaflet.markercluster.layersupport';

Creation

Simply use the L.markerClusterGroup.layerSupport factory instead of your regular L.markerClusterGroup:

var mcgLayerSupportGroup = L.markerClusterGroup.layerSupport(options);

mcgLayerSupportGroup.addTo(map);

Do not forget to add it to your map.

Adding and removing Markers / Layer Groups

Use the regular MCG methods (like addLayer, addLayers, etc.) to add Markers and/or Layer Groups to the MCG Layer Support group and to show them on to the map at the same time.

Layer Support provides 2 new methods checkIn and checkOut that do the same but do not show right away the passed Markers and/or Layer Groups on to the map. They accept a single layer or an array of layers.

Adding will automatically check in.

Check out will automatically remove from map.

Dynamically add to and remove from map while clustering

Once Markers and/or Layer Groups are added (or checked in) to the MCG Layer Support group, you can then directly add and remove them from the map; all child Markers will be added to or removed from the group, as if you had called group.addLayer (or group.removeLayer) instead.

This means that other Leaflet plugins (including standard Layers Control) that dynamically add to or remove markers from the map are now compatible with the clustering functionality!

For example, you can now gather Markers into several Layer Groups and use them as Overlays in L.Control.Layers: when ticking / un-ticking the Overlay name in the Control, markers will automatically cluster / be removed.

API Reference

Options

Option Type Default Description
singleAddRemoveBufferDuration Number 0 Gathers all calls to addLayer and removeLayer single operations (on this MCG) that happen during the specified duration (in ms) for batch processing. Similar to throttling with execution on trailing edge only. Use 0 to disable throttling. Disabled by default (see #11)

Methods

Method Returns Description
checkIn( <ILayer> or <ILayer[]> layers ) this Stamps the given Marker(s) or Layer Group(s) so that whenever they are added to or removed from the map later on, they are added to or removed from this group instead. If they are already on a map when checkIn is called, but they do not belong to this group yet, they are removed from that map.
checkOut( <ILayer> or <ILayer[]> layers ) this Un-Stamps the given Marker(s) or Layer Group(s) so that they retrieve their normal behaviour. Also removes the layers from the map.

MCG Layer Support does not provide any extra event.

Regular MCG options, events and methods

All regular MCG options, events and methods are available within MCG Layer Support. Refer to Leaflet.markercluster documentation.

Method Returns Description
addLayer and addLayers this Check in all passed layers, besides the normal behaviour.
removeLayer and removeLayers this Normal behaviour only. They do not check out layers.

Limitations

No clustering before at least one MCG Layer Support group has been added to map

As long as no MCG Layer Support group has been added to a given map, the latter will not be able to redirect calls to addLayer to the appropriate Layer Support group, even if you have properly checked in all Markers and Layer Groups. They will appear on the map without clustering. Once you add an MCG Layer Support group, it will collect its layers and re-add them properly clustered.

After that, markers already added on map will be collected by their respective Layer Support group once the latter are added to the map.

Later additions of checked in markers to the map will not show anything as long as the Layer Support group they belong to is not on map. If it is on map, then they show up normally (clustered).

Checked in Layer Group with child checked out marker

Refrain from doing the following: check in a Layer Group into an MCG Layer Support group (this checks in all child markers of that group) then check out one or several of the child markers individually.

The result is simple: when adding the Layer Group to the map, all child markers but the checked out ones will cluster. Checked out ones will be directly added to the map, without clustering. What did you expect? :-)

License

license

Leaflet.MarkerCluster.LayerSupport is distributed under the MIT License (Expat type), like Leaflet.markercluster.

leaflet.markercluster.layersupport's People

Contributors

asamk avatar ghybs avatar rey-awesense 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

Watchers

 avatar  avatar  avatar

leaflet.markercluster.layersupport's Issues

Slider cluster with dynamic php data

Hey,

I am using drupal and want to use this slider plugin.

I am not using geojson data instead i am using dynamic php data array and using it as
layerGroup = L.layerGroup([marker1, marker2, marker3, polyline]);

i have all the markers based on slider but not able to cluster it right now.
Will be glad if you can help me out in this.

Thanks,
Jay

Change in element leaflet-control-layers-overlays

Hi,

First of all, thank you very much for the plugin. It allowed me to use LeafletSlider. Since the implementation of the plugin, my labels positioned above a group of overlays disappeared (Before I used Leaflet.FeatureGroup.SubGroup).
e.g.
Mobility (in different languages)

  • overlay 1
  • overlay 2

Territories (in different languages)
-overlay 3
-overlay 4
-overlay 5

I used to add them via the following script:

$('<p style="color:#036;padding-top:5px;padding-bottom:1px;border-bottom:1px solid #036";">'+ text +'

' ).prependTo( $(".leaflet-control-layers-overlays").children()[1]);

I can partially solve my issue using dynamic css content:
div.leaflet-control-layers-overlays label:first-child:before {
content:'text';
color:#036;padding-top:5px;padding-bottom:1px;border-bottom:1px solid #036;
}

But then I loose the translation of the labels.

Can you help me?

Thanks in advance

Working with JSON data and Pie Chart

It is really a great plugin. I have 2 questions about the plugin I was curious about

  1. How can we work with JSON data and make sliders
  2. The pie chart that I mean by grouping the colors according to the defined colors in the groupings.

help with layersupport/leaflet slider

Hi,

I know this is more for development/issue requests but I was wondering if you could help me.

I'm developing a map here: https://demo-maps.s3-ap-southeast-2.amazonaws.com/mcls/examples/index.html

But I'm not a developer. I hack things together and they mostly work. Can you help me understand why I'm getting a 'TypeError: undefined is not an object (evaluating 't._leaflet_id')' error in my browser? The slider isn't working and I suspect it's how:
var sliderControl = L.control.sliderControl({
position: "topright",
layer: tx_old,
timeAttribute: 'hour',
range: true
});
is accessing the data. But I don't have the js skills to figure it out.

Please help! would be forever grateful as I love what your layer add-on's do.

Cheers

jmenz

getBounds() doesn't return valid object

When calling getBounds() on a L.markerClusterGroup.layerSupport object, it returns an invalid object (missing the required properties).

cluster = L.markerClusterGroup.layerSupport(); cluster.addTo(map); map.fitBounds(cluster.getBounds());

Above code works in the base plugin, if you take out the layerSupport part.

Red circle? (combination with Leaflet.search plugin)

Hi,

I'm working with clusters and I'm implementing search on map. When I enter a title of the marker, I get send to the location of the marker, but there is no red circle indicating where exactly marker is located, like when I work without clusters.

If there any way to get that red circle?
Thanks in advance!

Uncluster markers when there is layers control on the map

Hello,
Thank you for the great plugin.
I'm building a website where I'm implementing a checkbox to enable/disable clustering of the map.

The code works when there is no Layers Control attached to the map.

    $('input:checkbox[name=clustering]').click(function() {
        if($(this).is(':checked')) { //Show markers as a cluster.
                 // Remove the markers.
                 map.removeLayer(geojson_markers);
                 // Add the markers to the cluster group.
                 geojson_markers.addTo(markercluster);
                 // Add the cluster group to the map.
                 map.addLayer(window.markercluster); 
        } else { //Show markers as a indiviuals.
                 markercluster.clearLayers(); // Remove the layers of the cluster
                 geojson_markers.addTo(map); // Add the individual markers group to the map
        }
    });

The problem is that line geojson_markers.addTo(map); has no effect on the map. Even though the clustering part is working.

checkOut throws error

Since version 1.0.4, checkOut of a Layer Group throws an error:

Chromium:

Cannot read property 'removeLayers' of undefined

Firefox:

this._proxyMcgLayerSupportGroup is undefined

It seems that 8a7bb5a introduced that bug, because now Layer Groups that are "recruited" as "proxy" have 2 new methods (onAdd and onRemove) that are not handled when the Layer Group is checked out from the Layer Support, as is done for other methods in _dismissProxyLayerGroup:

// Restore the normal LayerGroup behaviour.
// Removal and check out of contained markers must be taken care of externally.
_dismissProxyLayerGroup: function (layerGroup) {
if (layerGroup._proxyMcgLayerSupportGroup === undefined ||
layerGroup._proxyMcgLayerSupportGroup !== this) {
return;
}
delete layerGroup._proxyMcgLayerSupportGroup;
layerGroup.addLayer = layerGroup._originalAddLayer;
layerGroup.removeLayer = layerGroup._originalRemoveLayer;
var id = L.stamp(layerGroup);
delete this._proxyLayerGroups[id];
delete this._proxyLayerGroupsNeedRemoving[id];
this._removeFromOwnMap(layerGroup);
},

Best way to incorporate SliderControl and Popups

Hello,

I'm working on a map using this script, and I'm having a bit of trouble both adding popups to the markers and styling the markers. With the AJAX json call, I'm not sure where to do these things. Thank you for your time.

var sliderControl = null;
var map = L.map('map').setView([38.912753,-77.032194], 9);

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

//Fetch some data from a GeoJSON file
$.getJSON(".//assets/data/borderstan.geojson", function(json) {

    var testlayer = L.geoJson(json);

    // Check into MCG Layer Support!
    // Add to map first before checking in.
    L.markerClusterGroup.layerSupport().addTo(map).checkIn(testlayer);

    var sliderControl = L.control.sliderControl({
        position: "topright",
        layer: testlayer,
        range: true
    });

    //Make sure to add the slider to the map ;-)
    map.addControl(sliderControl);
    //And initialize the slider
    sliderControl.startSlider();
});

Improve example.html files

Example.html files are terrible, impossible to reproduce with own configuration. Where is configuration code (map definition, for example)? There is no plain code in source.

mcgLayerSupport-controlLayers-realworld.100k.html
mcgLayerSupport-controlLayers-realworld.388.html
etc..

I'm forced to reverse-engineering the code (removing line after the line). It reminds me times of Internet explorer (Yes, so bad examples are).

layersupport + freezable

Thanks so much for all your work on this. Is there any way to use layersupport and freezable together/simultaneously?

Moving a marker throws an error and marker disappears

Moving a marker inside a MarkerCluster.LayerSupport layer with marker.setLatLng() produces an error:

error TypeError: Cannot read property 'x' of undefined
    at L.DistanceGrid._sqDist (https://unpkg.com/[email protected]/dist/leaflet.markercluster-src.js:1917:20)
    at L.DistanceGrid.getNearObject (https://unpkg.com/[email protected]/dist/leaflet.markercluster-src.js:1899:20)
    at NewClass._addLayer (https://unpkg.com/[email protected]/dist/leaflet.markercluster-src.js:984:36)
    at NewClass.<anonymous> (https://unpkg.com/[email protected]/dist/leaflet.markercluster-src.js:253:11)
    at NewClass.addLayers (https://unpkg.com/[email protected]/dist/leaflet.markercluster-src.js:287:4)
    at NewClass.addLayers (https://unpkg.com/[email protected]/dist/leaflet.markercluster.layersupport-src.js:115:8)
    at NewClass._processSingleAddRemoveBuffer (https://unpkg.com/[email protected]/dist/leaflet.markercluster.layersupport-src.js:267:29)

See: https://playground-leaflet.rhcloud.com/cave/edit?html,output

The problem is that LayerSupport buffers the add/remove operations and MarkerCluster implements moving a marker via removing and readding the marker. MarkerCluster expects the remove/add calls to be synchronous:

	_moveChild: function (layer, from, to) {
		layer._latlng = from;
		this.removeLayer(layer);

		layer._latlng = to;
		this.addLayer(layer);
	},

The issue can be worked around by disabling buffering in LayerSupport (by setting singleAddRemoveBufferDuration: 0).
See: https://playground-leaflet.rhcloud.com/yayab/edit?html,output

I'm not sure if this issue can be fixed in LayerSupport, or needs an improved move behaviour in MarkerCluster.

Leaflet Tag Filter Button and LayerSupport Plugins

I noticed that this plugin has the capability to be compatible with other plugins that add or remove markers on a map. I was hoping to use this feature with the Leaflet Tag Filter Button made by maydemirx. It filters markers by associated tags and generates a little button for users to interact it. I believe I succeeded in adding the layerSupported cluster to my map, but I am unsure, though, how to integrate the supported cluster with the tag filter buttons. The closest tutorial to combining two plugins is the Leaflet slider plugin, that has a demo here. I've tried to mimic the style of the implementation of the slider demo, adjusting for my own needs, but to no avail.

The Leaflet Tag Filter Button does support an update() method and an enablePruneCluster method, both of which sound like they could be used to achieve what I'm looking for. Yet, when I apply them individually to the filter buttons, they don't work. I'm either applying the filter button methods incorrectly or creating the layerSupported cluster inaccurately.

Here is my code for generating the layer supported marker cluster group:

var clusters = L.markerClusterGroup.layerSupport({maxClusterRadius:75}),
    group1 = L.layerGroup();
var getjson = $.getJSON("map-v2.geojson",function(data){
  var bev = L.geoJson(data,{
    pointToLayer: function(feature,latlng){
      var marker = L.marker(latlng, { tags: feature.properties.Genres.concat(feature.properties.Creator)});
      marker.bindPopup('<p align=center>' + '<strong>Title: </strong>' + feature.properties.Title + '<br/><a href="' + feature.properties.Image_Bank_URL + '" target="_blank"><img src="' + feature.properties.Thumbnail_URL + '"/></a><br/>' + '<strong>Date: </strong>' + feature.properties.Date + '<br/>' + '<strong>Creator: </strong>' + feature.properties.Creator, {minWidth : 250});
      return marker;
    }
  });
  bev.addTo(group1);
  clusters.addLayer(group1);
  map.addLayer(clusters);
});

// Here is where I add the layer supported clusters to the map.
clusters.checkIn(group1);
clusters.addTo(map);

Here is the section where I generate the tag filter buttons:

// Here is the code block for the Tag Filter Button. I start by accessing a tags file that has the data that I use for filter options. I should note that the genres.addToRelated is not working (it is supposed to link the 2 buttons together to work in conjunction with each other).
$.getJSON('tags.json', function(data) {
var genres = L.control.tagFilterButton({
  data: data.genres,
  filterOnEveryClick: true,
  icon: '<i class="fas fa-tags"></i>',
}).addTo(map);
var creators = L.control.tagFilterButton({
  data: data.creators,
  filterOnEveryClick: true,
  icon: '<i class="fas fa-user-edit"></i>',
}).addTo(map);
jQuery('.easy-button-button').click(function() {
	target = jQuery('.easy-button-button').not(this);
	target.parent().find('.tag-filter-tags-container').css({
		'display' : 'none',
	});
});
genres.addToRelated(creators);
});

I added genres.update(clusters); and genres.enablePruneCluster(clusters); after the genres.addToRelated(creators);, but both of those didn't work to update the clusters.

If you'd like to see it all in action, here is a plunker of the code.

markersupport

hi there i have issue with competability L.markerClusterGroup with L.moveMarker. How can i fix this problem.
here is my code with markerCluster
without moveMarker

    var group2 = L.markerClusterGroup.layerSupport();
    group2.addTo(map);
    marker[1001] = L.moveMarker(
        [[41.3110, 69.2797], [41.4110, 69.1797]],
        {animate: true, color: "purple", weight: 1, hidePolylines: false, duration: 5000, removeFirstLines: true, maxLengthLines: 3},
        {animate: true, hideMarker: false, duration: 5000, speed: 0, followMarker: false, rotateMarker: true, rotateAngle: 0,
        icon: L.divIcon({
                    iconSize: [28, 28],        marker[1001] = L.moveMarker(
    [[41.3110, 69.2797], [41.4110, 69.1797]],
    {animate: true, color: "purple", weight: 1, hidePolylines: false, duration: 5000, removeFirstLines: true, maxLengthLines: 3},
    {animate: true, hideMarker: false, duration: 5000, speed: 0, followMarker: false, rotateMarker: true, rotateAngle: 0,
    icon: L.divIcon({
                iconSize: [28, 28],
                className: "position-absolute rotate--marker",
                html:
                    '<div><img style="height:28px" src="https://www.pngkit.com/png/full/54-544296_red-top-view-clip-art-at-clker-cartoon.png" /></div>'
            }),
        title: 'red'

    }).addTo(map);
                    className: "position-absolute rotate--marker",
                    html:
                        '<div><img style="height:28px" src="https://www.pngkit.com/png/full/54-544296_red-top-view-clip-art-at-clker-cartoon.png" /></div>'
                }),
            title: 'red'

        }).addTo(map);

Picture1

and with moveMarker but there is nothing

        marker[1001] = L.moveMarker(
            [[41.3110, 69.2797], [41.4110, 69.1797]],
            {animate: true, color: "purple", weight: 1, hidePolylines: false, duration: 5000, removeFirstLines: true, maxLengthLines: 3},
            {animate: true, hideMarker: false, duration: 5000, speed: 0, followMarker: false, rotateMarker: true, rotateAngle: 0,
            icon: L.divIcon({
                        iconSize: [28, 28],        marker[1001] = L.moveMarker(
        [[41.3110, 69.2797], [41.4110, 69.1797]],
        {animate: true, color: "purple", weight: 1, hidePolylines: false, duration: 5000, removeFirstLines: true, maxLengthLines: 3},
        {animate: true, hideMarker: false, duration: 5000, speed: 0, followMarker: false, rotateMarker: true, rotateAngle: 0,
        icon: L.divIcon({
                    iconSize: [28, 28],
                    className: "position-absolute rotate--marker",
                    html:
                        '<div><img style="height:28px" src="https://www.pngkit.com/png/full/54-544296_red-top-view-clip-art-at-clker-cartoon.png" /></div>'
                }),
            title: 'red'

        }).addTo(map);
                        className: "position-absolute rotate--marker",
                        html:
                            '<div><img style="height:28px" src="https://www.pngkit.com/png/full/54-544296_red-top-view-clip-art-at-clker-cartoon.png" /></div>'
                    }),
                title: 'red'

            }).addTo(group2);

Picture2

Overlapping MarkerCluster popups?

I use your application and it works very successfully.

  1. Pop-up popups overlap as shown in the picture. Is there a solution for this?
  2. I have one more question when clicking on a classification, the other clicked classifications are closed. Is it possible to open both by clicking?
    Thank you.

image

The first demo popup unable to open

maxzoom : Popup can be opened for the first time. But when I narrowed the map,then maxzoom once again, popup unable to open (My English is very poor, please forgive me)

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.