Giter VIP home page Giter VIP logo

js-markerclusterer's People

Contributors

amuramoto avatar btelles avatar conmute avatar dependabot[bot] avatar emilengelin avatar googlemaps-bot avatar jpoehnelt avatar mbv avatar mwaddell avatar nora-soderlund avatar sandeepk-e avatar semantic-release-bot avatar usefulthink avatar vicb avatar yuethomas 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

js-markerclusterer's Issues

Migration Feedback

[Sorry for multiple points in the same issue]
Migrating from (depreciated) https://github.com/mahnunchik/markerclustererplus to v2.0.4

  1. More documentation in README please, with examples of calling each cluster algorithm & each render algorithm,
  • explain differences between them
  • give calling options for them.
  1. Slower... seemed to be lots of re-rendering. (12,000 markers). Maybe load markers into memory, do the clustering once at each zoom level, then just render on the map as you pan close.
  2. After showing/hiding markers with [marker].setVisible(), I called .render() to redraw - it just didn't work, cluster-total's were wrong, saw a cluster-total of 1 one time. Thinking about it, I needed to re-cluster, then re-render. Maybe add an example of this to the documentation as a migration point.
  3. Use cdnjs (or a google version of it)
    Hope this helps.

The automated release is failing 🚨

🚨 The automated release from the main branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you can benefit from your bug fixes and new features again.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can fix this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the main branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here are some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


No npm token specified.

An npm token must be created and set in the NPM_TOKEN environment variable on your CI environment.

Please make sure to create an npm token and to set it in the NPM_TOKEN environment variable on your CI environment. The token must allow to publish to the registry https://wombat-dressing-room.appspot.com.


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

Extending events

Is it possible to have marker events on a clustered marker? I.e "mouseover", "mouseout", etc. Currently only a click event is supported.

Not sure what it would take to port, but markerclustererplus had this functionality.

Thanks.

Performance issues while zooming in

Heyy @jpoehnelt,

I have been experiencing performance issues with the new version of the marker clusterer (1.0.17). I have a map with about 3500 markers and before we've been using an old version of markerclustererplus. I don't know the version as the version used is a .js file. The old clusterer was configured with the following settings:

const markerCluster = new MarkerClusterer(map, [], { maxZoom: 15, minimumClusterSize: 5, });

This gives a fairly smooth experience. Now we upgraded to the new clusterer and any algorithm has a pretty big performance impact. We're using the following settings:

const markerClusterer = new MarkerClusterer({ map: experienceMap, algorithm: new SuperClusterAlgorithm({ maxZoom: 15, minPoints: 5, radius: 60 }), });

There are no other event listeners on the map or on the markers. No custom icons or anything. Just a marker with a position and they're added to the map. Loading the initial makers is no problem and only takes about 15ms on an AMD 5900x with RTX 3070ti and 64gb ram. The problem begins when zooming in. It seems there is something blocking the main thread and as a result it all slows down and basically freezes. We've noticed this problem happening on Chrome, Edge and Firefox. We also tried the demo site and we experience the same performance problems to a lesser extent. After debugging we found out it causes in the reset() function of the MarkerClusterer class on the line with this.clusters.forEach((cluster) => cluster.delete()). The algorithm takes 8ms with 3500 markers but that line takes over 1700ms. It seems the clusters are getting rendered while the animation of the map zooming in is happening.

Thanks.

Update:
After testing it seems to be caused by the label tag of the marker. If all labels are removed, the lag is gone.

Help converting old version to the new one please

First issue is I'm not sure how I can set the zoomOnClick, gridSize, etc in the new version. I am able to get my markers to show though on the map.

/*//set marker clusterer
markerCluster = MarkerClusterer(map, markers,
    {
        zoomOnClick: false,
        gridSize: 50,
        imagePath: '/assets/img/gmaps/clusterplus/m',
        title: 'Multiple Entries'
    }
);
*/

//edited 02-19-22 to markerClusterer.MarkerClusterer from markerClusterer (see notes about using the npm downloaded version at https://www.npmjs.com/package/@googlemaps/markerclusterer)
markerCluster = new markerClusterer.MarkerClusterer({ map, markers });

Second issue is I don't understand how to use the new 'onClusterClick' way. I was previously using a listener for this which no longer works with the new version. https://googlemaps.github.io/js-markerclusterer/interfaces/MarkerClustererOptions.html goes into the options of the new version and mentions a 'onClusterClick', but I haven't been able to get it to do anything.

/*
//no longer works with new version
//marker clusterer click
google.maps.event.addListener(markerCluster, 'clusterclick', function(cluster) {
    //close any open windows
    infowindow.close();
    
    //if zoom is less than max show just zoom in
    if(map.getZoom() < map.maxZoom ){
        map.setCenter(cluster.center_);
        map.setZoom(map.getZoom() + 2);
    }
    //show custom window with multiple ip address details
    else {
        //get markers length
        var markersLength = cluster.getMarkers().length;
        
        var detailContent = '<b class="fw6 text-primary">' + cluster.getMarkers().length + ' IP Addresses :</b><br/><br/>'+                         
            '<div>'+
                '<ul class="list-unstyled m-0">'+
                    //'<li><b class="fw6">City :</b> '+cluster.getMarkers()[0].entry_city+'</li>'+
                    //'<li><b class="fw6">Location :</b> '+cluster.getMarkers()[0].entry_location+'</li>'+
                    '<li><b class="fw6">City, Location :</b> '+(cluster.getMarkers()[0].entry_city ? cluster.getMarkers()[0].entry_city : 'n/a')+', '+(cluster.getMarkers()[0].entry_location ? cluster.getMarkers()[0].entry_location : 'n/a')+'</li>'+
                    '<li><b class="fw6">Postal Code :</b> '+cluster.getMarkers()[0].entry_postal+'</li>'+
                    '<li><b class="fw6">Country :</b> '+cluster.getMarkers()[0].entry_country+'</li>'+
                '</ul>'+
            '</div>'+
            '<hr/>';
        
        for (var i=0; i < markersLength; i++)
        {
            detailContent += ''+
                '<div>'+
                    '<ul class="list-unstyled">'+
                        '<li><b class="fw6">IP Address :</b> '+cluster.getMarkers()[i].entry_ip+'</li>'+
                        '<li class="mb-10"><b class="fw6">Number of entries :</b> '+cluster.getMarkers()[i].entry_total+'</li>'+
                    '</ul>'+
                '</div>';
        }
        
        var info = new google.maps.MVCObject;
        info.set('position', cluster.center_);
        infowindow.setContent(detailContent);
        infowindow.open(map, info);
    }
});
*/

Any help or clarification would be appreciated.

Delete markers is not working

I want to create a dynamic map, and remove markers or clusters. Unfortunately, removing the markers with the corresponding functions removeMarkers(...) and clearMarkers() does not work. Please check my sandbox.

By the way, deleting markers works fine through the deprecated implementation of @googlemaps/markerclustererplus.

Installing with npm loads incorrect paths for imports

when installing via npm instead of downloading source under releases results in the following

  • WARNING in ./node_modules/@googlemaps/markerclusterer/dist/index.esm.js
  • Error: ENOENT: no such file or directory, open 'C:/.../node_modules/@googlemaps/markerclusterer/src/algorithms/kmeans.ts'

npm is looking for src directory but it does no exist all files are located in dist.

this occurs on multiple imports

GridAlgorithm - zooming to marker at or above maxZoom level doesn't display marker

Zooming to marker at or above maxZoom level doesn't display marker when using GridAlgorithm. It works as expected when using SuperClusterAlgorithm.

Problem can be seen at this example. Note I have used default parameters for GridAlgorithm so maxZoom is 16.
There are 3 buttons to pan and zoom at 3 markers. Zoom level for these markers can be set using Set Zoom buttons.

Steps to replicate the issue:

  1. Load the example
  2. Click on Marker 3
  3. All 3 maps will zoom to the marker. However, there is no marker image displayed at map 2
    Note: the map's zoom is at level 16 and maxZoom for GridAlgorithm is 16
    image
  4. Zoom out on any map. The marker will now appear on map 2.

If the marker is zoomed at level 15 then map 2 will display the marker correctly.
Steps to replicate:

  1. Load the example
  2. Click on "Set Zoom at 15" button. This will set zoom to level 15 when marker buttons are clicked.
  3. Click on Marker 3
  4. All 3 maps will zoom to the marker and map 2 will display the marker correctly
    Note: the map's zoom is at level 15 and maxZoom for GridAlgorithm is 16
    image

library mutates its data (Markers)

Using the latest version of this library i noticed the library mutates the markers provided. Thats fine inside a React Class component, but when i want to have a Functional component i noticed i will endup with both markers being painted since the library will mutate the collection of markers.

Is it possible the library, when initiating a new Clusterer, will return its (mutated) markers? So i can update state?

Upgrade from @google/markerclustererplus

Hello,

actually, i'm using @google/markerclustererplus to display cluster on the map (with the import <script src="https://unpkg.com/@googlemaps/markerclustererplus/dist/index.min.js"></script>) by using "".

I was wondering if it exists the same tag (or something else) in your package. I haven't found it for the moment so i'm asking here...

Thanks in advance !

Trigger click event on marker which inside a cluster

I want to open a info window of a marker which is inside a map cluster. For other marker which are not inside any cluster google.maps.event.trigger(ourMarker, 'click'); is working as expected, but if marker is inside cluster then it is not working.

Here is a sample example code: https://codesandbox.io/s/new-bird-8fp0q?file=/src/index.ts

On line 58, I triggered event for marker[0] which is not inside any marker cluster. That is why it is working as expected.

Please change line number 58 to google.maps.event.trigger(markers[1], "click"); . That will not work because it is inside marker cluster.

Could you please help me with this?

Thanks in advance.

Expose idleListener as a method or property for toggling automatic render

Currently idleListener is a protected property, so markerclusterer instances always call render() on map idle events whenever attached to a map. However sometimes this behavior isn't desirable. With large datasets rendering can take significant resources so users may wish to debounce this event or otherwise only call render() at their convenience. Rendering may also be pointless if the application is always going to change the marker data based on the new map location anyway, which is my current use case.

Describe the solution you'd like
Export a method to toggle automatic calls to render() by remove()ing or reinstating the MapEventListener at idleListener, or export a property which the body of idleListener uses to determine whether to abort before calling render().

I'm willing to make a pull request for this. see: (TheAtomicOption@7e1a907) as a first draft.

**Describe alternatives you've considered
Additionally/alternatively add a MarkerClustererOptions value to configure whether idleListener is assigned. This would at least allow it to be set on initialization, but users would have to write and manage their own listeners for calling render() rather than just calling a method to swap behavior.

Additional Context
My particular use case involves retrieving a new marker list whenever the map pans or zooms. I'm using this module along with the rest of google maps through a wrapper for Blazor, called BlazorGoogleMaps (https://github.com/rungwiroon/BlazorGoogleMaps). Unfortunately this means that there is some lag between the between the business logic and JS. Because of that, alternatives like destroying the current instance of markerclusterer on map events before idle and instantiating a new one with the new data afterwards is difficult to work around. They can easily result in race conditions when things like calls to render from the idleListener can happen before my business logic has had time to respond.

The mediocre workaround I am currently using is to set a listener on the bounds_changed map event to call clusterer.clearMarkers(true) which at least avoids rendering the current set of markers until the next set of markers are added. But it's not optimal since I have to pass the entire marker set back into markerclusterer rather than being able to update it addMarkers()/removeMarkers()

Proposal: Prevent unnecessary re-renders

On maps with only a small amount of clusters, it often happens that all clusters are redrawn upon zoom, even though nothing has changed. The resulting flickering looks very buggy and distracting. As a workaround, we use an algorithm that compares the actual markers:

import {
  AlgorithmInput,
  Cluster,
  SuperClusterAlgorithm,
  SuperClusterOptions,
} from "@googlemaps/markerclusterer";
import { shallowEqual } from "fast-equals";

const summarize = (c: Cluster) => `${c.position} ${c.count}`;

export class CachedSuperClusterAlgorithm extends SuperClusterAlgorithm {
  constructor(opts: SuperClusterOptions = {}) {
    super(opts);
  }
  calculate(input: AlgorithmInput) {
    const prevClusters = this.clusters;
    const output = super.calculate(input);
    const { changed, clusters } = output;
    if (changed && prevClusters) {
      if (shallowEqual(prevClusters.map(summarize), clusters.map(summarize))) {
        return { changed: false, clusters };
      }
    }
    return output;
  }
}

I was wondering if it made sense to incorporate such a check into the library, and would be happy to contribute a PR if you think this would be a good idea.

angular library using markerclusterer causes failing jest tests

Hello,

We have created an angular 13 ui components library which is using the @googlemaps/markerclusterer package. This components library was created inside a nx repo and published via private npm. After installing this components library inside an angular 13 application which is using jest for testing, all our unit tests are failing with the same error =>

Test suite failed to run
SyntaxError: The requested module '@googlemaps/markerclusterer' does not provide an export named 'MarkerClusterer'
at Runtime.linkAndEvaluateModule (node_modules/jest-runtime/build/index.js:826:5)

Does this mean that the @googlemaps/markerclusterer package is not really compatible to be used with angular 13 and jest?

Kind regards,

Gerry

Library not working with Angular Google Maps component

Hey,
I came here because of some bugs in old js-markerclustererplus library (this issue). However, when I tried to use this lib with Angular Google Maps component, it's throwing errors. I tried to "build a bridge" in ugly way to make the new lib working, but with no effects. This is my tries:
window.MarkerClusterer = window.markerClusterer.MarkerClusterer; window.MarkerClusterer.prototype.repaint = window.MarkerClusterer.prototype.render;
I know the chances to update Google Maps component are very low, so I'm asking you to adapt old methods.

Thanks a lot!

Fractional Zoom and SuperCluster

Hi Team,

Thanks for open sourcing / making your project public.

Not sure if this is a bug or if I am just having a Sunday Funday.

There appears to be an issue with the default cluster algorithm when applied to a map that is vector based instead of raster based when updating clusters on click.

I am not 100% sure if I am debugging the issue correctly but it appears to be caused by/when zoom is not an integer value when tilted etc. Overriding the SuperClusterAlgorithm cluster function to round map.getZoom() to an integer seems to solve the issue more or less but not sure of any other issues it may cause or if it would be better to open an issue with the Super Cluster library team as the error seems to occur in the getClusters function on const tree = this.trees[this._limitZoom(zoom)] line.

addMarker does not update cluster number

When adding new marker to the clusterer (at least when clusterer is not visible, map is zoomed in), then zooming out to show clusters, the marker seems not to be counted in the cluster.

// SuperClusterAlgorithm
clusterer.addMarker(marker);
clusterer.render(); // optional?

delete clusters

There some complete example for delete markers and clusters?

I can't use the delete() method correctly.

The response is delete is not a function

Thank you

getMarkers()?

Old version had a getMarkers() which would return marker information from the clicked on cluster. Is there no such ability in this version?

In my case I had clusters which could never be zoomed in enough to separate them into markers. For example, multiple people at the same lat/lng each with their own marker. When the maxzoom was reached on click of the cluster I would show an info window popup that broke down the information of the different markers in that cluster.

Remove dependency on fast-equals

fast-equals uses the following code which violates security performance check in some environments:

const hasOwnProperty = Function.prototype.bind.call(
  Function.prototype.call,
  Object.prototype.hasOwnProperty,
);

You can find it at https://github.com/planttheidea/fast-equals/blob/master/src/utils.ts#L234

It another variant of the library called fast-deep-equals passes this security check, is already included in js-markerclusterer dependencies, and has exactly the same effect. Removing the dependency fast-equals removes this violation.

Markers are blinking at any action

Hey! Thank you so much for this helpful library.
Despite all the good things, I have a big problem that prevents me from using it.
These are blinking markers. At any movement on the map or window size change, a complete redrawing occurs. This behavior is also observed in the example from the google documentation here in Safari/Firefox/Chrome, so I will not give an example of my code. It's basically the same.

Version: 1.0.5
Included to the page via unpkg.

Is there any way to overcome this problem, or do I have to wait for a solution for now?
With respect, Roman.

Map tiles do not show up unless I resize

I am using https://unpkg.com/@googlemaps/markerclusterer/dist/index.min.js CDN approach

When my map displays sometimes it will show the background tiles, and sometimes it doesn't. You have to manually resize the browser for it to render the tiles. If you click on any cluster markers, it doesn't show tiles anymore and you have to resize again.

You can view at https://s3.amazonaws.com/pramadillo/screencast_2022-06-03_11-34-06.mp4

I have the following code for displaying the map

`(function ($) {
'use strict';

$(function () {
    var bounds = new google.maps.LatLngBounds()
    var markers = getMarkers();

    $(window).scroll(function () {
        var offset = 0;
        var sticky = false;
        var top = $(window).scrollTop();
        var bottom = $('.entry-content').scrollTop();

        if ($("#business-list-container").offset().top < top && $("#business-list-container").offset().top > bottom) {
            $(".business-list-map-container").addClass("sticky");
            sticky = true;
        } else {
            $(".business-list-map-container").removeClass("sticky");
        }
    });

    function getMarkers(){

        $.ajax({
            url: emoxie.ajax_url,
            type: 'post',
            dataType : "json",
            data: {
                action: 'emoxie_get_listings',
                nonce: emoxie.get_listings_nonce,
                post_id: emoxie.post_id,
                args: emoxie.args,
            },
            success: function(response) {
                initMap(response);
            }
        })

        return markers;
    }

    function initMap(markers) {

        const map = new google.maps.Map(document.getElementById('business-list-map'))
        var infoWindow = new google.maps.InfoWindow(), marker, i
        var marker_clusterer = new markerClusterer.MarkerClusterer({ map: map });

        /* Place each marker on the map  */
        for (i = 0; i < markers.length; i++) {
            if (null !== markers[i].lat) {
                var position = new google.maps.LatLng(markers[i].lat, markers[i].lng)
                bounds.extend(position)

                marker = new google.maps.Marker({
                    position: position,
                    map: map,
                    title: markers[i].title
                })
                marker_clusterer.addMarker( marker );

                /* Add info window to marker   */
                google.maps.event.addListener(marker, 'click', (function (marker, i) {
                    return function () {
                        infoWindow.setContent(markers[i].title)
                        infoWindow.open(map, marker)
                    }
                })(marker, i))

                /* Center the map to fit all markers on the screen */
                map.fitBounds(bounds)
            }
        }

        var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function (event) {
            // this.setZoom(10)
            google.maps.event.removeListener(boundsListener)
        })

        google.maps.event.trigger(map, 'resize');

    }


});

})(jQuery);`

Any help would be much appreciated. I tried triggering the map resize but that didn't seem to have any effect.

MarkerClustererOptions - minimumClusterSize

Is your feature request related to a problem? Please describe.
Apparently it is recommended to move from js-markerclustererplus to js-markerclusterer. The problem that I am running into is that minimumClusterSize seems to be missing as a cluster option.

js-markerclustererplus repository

Describe the solution you'd like
Could be possible to add to the MarkerClustererOptions the option to add an minimumClusterSize.

Additional context
If there is an alternative solution, I am also fine with that. Could you give me some recommendations?

Updating styles to new version.

HI,

I've switched to the new version of this and it does work, but I'm having difficulty styling the clusters whereas I managed easily with the old version.

In the old version I had it set up like:

                    let markerCluster = new MarkerClusterer({map, markers}, {
                        maxZoom: 14,
                        clusterClass: 'custom-clustericon',
                        styles: [
                            {
                                width: 30,
                                height: 30,
                                className: 'custom-clustericon-1'
                            },
                            {
                                width: 40,
                                height: 40,
                                className: 'custom-clustericon-2'
                            },
                            {
                                width: 50,
                                height: 50,
                                className: 'custom-clustericon-3'
                            }
                        ]
                    });

and styled as so:

.custom-clustericon {
    background: var(--cluster-color);
    color: #fff;
    border-radius: 100%;
    font-weight: bold;
    font-size: 15px;
    display: flex;
    align-items: center;
}

.custom-clustericon:before,
.custom-clustericon:after {
    content: "";
    display: block;
    position: absolute;
    width: 100%;
    height: 100%;
    transform: translate(-50%, -50%);
    top: 50%;
    left: 50%;
    background: var(--cluster-color);
    border-radius: 100%;
}

.custom-clustericon:before {
    width: calc(100% + 10px);
    height: calc(100% + 10px);
    opacity: 0.6;
}

.custom-clustericon:after {
    width: calc(100% + 20px);
    height: calc(100% + 20px);
    opacity: 0.3;
}

// The bigger the number, the more markers/groups are contained within.
.custom-clustericon-1 {
    --cluster-color: hsl(var(--color-highlight));
}

.custom-clustericon-2 {
    --cluster-color: hsl(var(--color-secondary));
}

.custom-clustericon-3 {
    --cluster-color: hsl(var(--color-primary));
}

How can I replicate the older styles using the new version? I;ve tried to inspect the new cluster markers, but all I see is a div with a single transparent pixel image within. Nothing to actually help me style. I just want to replicate the styles I have above. Custom cluster icon colours and three cluster sizes. I'm not sure what those sizes were specifically as I just used the ones that came as default with the old version.

Thanks,
Neil

Option for SuperClusterer algorithm bounding box

Hello @jpoehnelt,

Is there a reason why 2 months ago (#60, src/algorithms/supercluster.ts:96), you switched the bounding box for getClusterer() in the SuperClusterer algorithm from a dynamic [west, south, east, north] to a static [-180, -90, 180, 90]?

We were working on a project, and we had some huge performance issues (tested on Ubuntu 20.04 LTS and macOS 12.1 Monterey).

Running on 2.3k markers, going above 100 clusters on the entire map would literally crash the browser.

Digging through the SuperClusterer algorithm, we found the bounding box set on those previously mentioned static numbers. Changing back those values for the dynamic ones, fixed it.

Correct me if I'm wrong, but it seems relevant to only want the algorithm to operate on currently visible clusters (instead of the entire world).

Thank you,
Have a lovely day.

(Related pull request : !135)

Hiding markers is still displaying clusters with size 0

Hi,
I'm currently building an interactive map with markers. So my code is adding a map with various markers, then adding a clustering and everything is working fine. Issue is appearing when I'm starting to hide some markers, by using marker.setVisible(false) and then rendering again my clusterer, with markerClusterer.render(). I can see on my map some cluster with size 0 appearing where I've hidden some markers.

Environment details

1.Using script api <script src="https://unpkg.com/@googlemaps/markerclusterer/dist/index.min.js"></script>
2. Inside a vuejs app

Steps to reproduce

  1. Create a map
  2. Add various markers
  3. Add a clustrer
  4. Render it to see everything is fine
  5. Hide markers dynamically, with a button click for example
  6. Render again the clusterer

You should see like me clusters of size 0

Code example

Rapid fiddle here : https://jsfiddle.net/2vzayxc4/3/
Click on hide button under the map, and zoom out to see it happening.

Thanks for the help, it's driving me crazy ;)

mouseover/mouseout per cluster marker

Thanks for stopping by to let us know something could be better!

Is your feature request related to a problem? Please describe.
In the old marker clusterer, we could have add mouseover/mouseout listeners to the cluster markerer, and that would fire the corresponding events for each cluster marker.
The new implementation lacks this feature.

Describe the solution you'd like
MarkerClustererEvents.CLUSTER_MOUSE_OVER/MarkerClustererEvents.CLUSTER_MOUSE_OUT would be great.

Describe alternatives you've considered
Accessing the "protected" clusters property.

markerCluster.addListener(markerCluster, MarkerClustererEvents.CLUSTERING_END, () => {

    for (let cluster of markerCluster.clusters) {

        if (cluster.markers.length === 1) continue;
        cluster.marker.addListener('mouseover', () => onClusterMouseOver(cluster));
        cluster.marker.addListener('mouseout', () => onClusterMouseOut(cluster));

    }

});

reset method contains duplicate lines of code? why? ...

In: src/markerclusterer.ts, the reset() method contains the following:

  protected reset(): void {
    this.markers.forEach((marker) => marker.setMap(null));
    this.markers.forEach((marker) => marker.setMap(null));
    this.clusters.forEach((cluster) => cluster.delete());
    this.clusters = [];
  }

LInes 212 and 213 are identical, i.e.:

212    this.markers.forEach((marker) => marker.setMap(null));
213    this.markers.forEach((marker) => marker.setMap(null));

-- is there any reason why?

Create and export react component

It would be benefical to have a <MarkerClusterer map={map}> component. Need to consider if a prop of markers would be better or a child <Marker> components.

GridAlgorithm keeps displaying cluster at maximum zoom level

GridAlgorithm keeps displaying cluster and doesn't display markers at maximum zoom level. There is maxZoom which can be set, however it has no effect in GridAlgorithm. It works as expected when using SuperClusterAlgorithm.

Steps to replicate:

  1. Go to Algorithm Comparisons example page
  2. Keep clicking on any cluster and go to maximum zoom level.
  3. GridAlgorithm will keep displaying cluster

image

Documentation: package name in README.md Migration section is wrong.

Environment details

  1. Specify the API at the beginning of the title (for example, "Places: ...") [documentation, n/a]
  2. OS type and version [n/a]
  3. Library version and other environment information [n/a]

Steps to reproduce

  1. check https://github.com/googlemaps/js-markerclusterer/blob/main/README.md
  2. the first sentence refers to "@googlemaps.markerclustererplus" twice -- the first one should probably refer to the current package instead.

Angular usage & "allowSyntheticDefaultImports": true,

Just a few tips for Angular users & a bug (I think).


Please be sure to include as much information as possible:

Environment details

Running on Win10 Pro insider, Chrome browser (latest), VSCode (insiders), all packages are evergreen

PS D:\Projects\RangerTrak\rangertrak> npm list
[email protected] D:\Projects\RangerTrak\rangertrak
β”œβ”€β”€ @angular-devkit/[email protected]
β”œβ”€β”€ @angular-material-components/[email protected]
β”œβ”€β”€ @angular-material-components/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @angular/[email protected]
β”œβ”€β”€ @fortawesome/[email protected]
β”œβ”€β”€ @fortawesome/[email protected]
β”œβ”€β”€ @fortawesome/[email protected]
β”œβ”€β”€ @fortawesome/[email protected]
β”œβ”€β”€ @fortawesome/[email protected]
β”œβ”€β”€ @googlemaps/[email protected]
β”œβ”€β”€ @material/[email protected]
β”œβ”€β”€ @material/[email protected]
β”œβ”€β”€ @mdi/[email protected]
β”œβ”€β”€ @ngx-pwa/[email protected]
β”œβ”€β”€ @popperjs/[email protected]
β”œβ”€β”€ @types/[email protected]
β”œβ”€β”€ @types/[email protected]

β”œβ”€β”€ @types/[email protected]
β”œβ”€β”€ @types/[email protected]
β”œβ”€β”€ @types/[email protected]
β”œβ”€β”€ @types/[email protected]
β”œβ”€β”€ @types/[email protected] extraneous
β”œβ”€β”€ @what3words/[email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
β”œβ”€β”€ [email protected]
└── [email protected]

Steps to reproduce

code is pretty much the same as listed in : https://github.com/googlemaps/js-markerclusterer (i.e., pretty simple)
ng serve -o

Yields

`Warning: D:\Projects\RangerTrak\rangertrak\node_modules@turf\clusters-dbscan\dist\es\index.js depends on 'density-clustering'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies

Warning: D:\Projects\RangerTrak\rangertrak\node_modules@turf\clusters-kmeans\dist\es\index.js depends on 'skmeans'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies

Error: node_modules/@googlemaps/markerclusterer/dist/algorithms/supercluster.d.ts:18:8 - error TS1259: Module '"D:/Projects/RangerTrak/rangertrak/node_modules/@types/supercluster/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

18 import SuperCluster, { ClusterFeature } from "supercluster";
~~~~~~~~~~~~

node_modules/@types/supercluster/index.d.ts:175:1
175 export = Supercluster;
~~~~~~~~~~~~~~~~~~~~~~
This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.`

To fix this, one needs to comprehend https://www.typescriptlang.org/tsconfig#allowSyntheticDefaultImports
and then add the following line to your tsconfig.json file
"compilerOptions": {
"allowSyntheticDefaultImports": true,

Code example

So some tips for other Angular users:
import { MarkerClusterer } from "@googlemaps/markerclusterer"
fails, and I've had to go to:
import * as GMC from "@googlemaps/markerclusterer"

then in the Component:
gMap?: google.maps.Map
markers: google.maps.Marker[] = []
markerCluster!: GMC.MarkerClusterer
markerClustererImagePath ='https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'``

then in
onMapInitialized(theGodGivenReferenceToTheActualGoogleMap: google.maps.Map) {
this.map = theGodGivenReferenceToTheActualGoogleMap // Otherwise its near impossible for angular google map users to get the actual map reference & this is buried in git history, NOT well documented!

this.markerCluster = new GMC.MarkerClusterer({
map: this.map,
markers: this.markers,
// algorithm?: Algorithm,
// renderer?: Renderer,
// onClusterClick?: onClusterClickHandler,
})
...
}

WARNING: do NOT use the Angular wrapper around google.maps.Marker & google.maps.MarkerMarkerClusterer!

github.com/angular/components/tree/master/src/google-maps/map-marker
github.com/angular/components/tree/master/src/google-maps/map-marker-clusterer

For some reason these wrappers ONLY include lat/lng positions,
and do not support Marker options: i.e. all your markers and clusters will look like identical clones
and are pretty much mind-dead! (it is fine to use the rest of their wrappers, IF you are aware of the lightly documented onMapInitialized() event as shown above.)

Good luck & LOVE all the great work being done here!

Documentation spelling errors in core & markerclusterer

When comparing markerclustererplus to this version of markerclusterer I noticed a few typos in the documentation of the code. These obviously are not causing a problem however I wanted to bring them to attention. Looking forward to working with this package in the future!

src/algorithms/core.ts:

Line 22: makres -> markers
Line 76: prepocessing -> preprocessing

src/markerclusterer.ts:

Line 33: arry -> array

Markers disappears when zooming out in GridAlgorithm

When zooming out around when you can see two continents, the markers disapperas for the three algorithms GridAlgorithm, KmeansAlgorithm and DBScanAlgorithm. This can easily be seen in the algorithm demo.

Environment details

  1. Replicate-able in both Windows/Linux and Chrome/FireFox
  2. Version v1.0.16

Steps to reproduce

  1. Go to https://googlemaps.github.io/js-markerclusterer/public/algorithms/
  2. Zoom out until you see two continents
  3. The markers/clusters disappear in 3 of 5 algorithms.

Code example

The problem seem to be in this function, when extending the bounds, new bounds gets wrong.

filterMarkersToPaddedViewport(map, mapCanvasProjection, markers, viewportPadding)

var extendedMapBounds = extendBoundsToPaddedViewport(map.getBounds(), mapCanvasProjection, viewportPadding);

A quick and dirty workaround is to just not extend the bounds:

var extendedMapBounds = map.getBounds();

Possible to create a StackBlitz/Plunker example?

Thanks for stopping by to let us know something could be better!

Is your feature request related to a problem? Please describe.
I'm not sure how to "approach" (i.e., build and run) the examples in your examples directory. I'm sure its trivial, but where do I get started?!

For instance your ReadMe has:
sample.component.ts as:

import { MarkerClusterer } from "@googlemaps/markerclusterer";

// use default algorithm and renderer
const markerCluster = new MarkerClusterer({ map, markers });

Obviously there is a lot more to producing a simple map than this...

Describe the solution you'd like
It would be nice to have a StackBlitz (or other easy isolated dev environment, like Plunker or CodePen) examples to ensure I'm setting up my environment correctly, have the right versions of related packages, and haven't made any typos...

Describe alternatives you've considered
I'm just browsing for full code examples to insert into my project as a starting point...

Additional context
Add any other context or screenshots about the feature request here.

Cannot use the library in Angular without importing the markerclustererplus library

I cannot use this library with angular without installing the markerclustererplus library.

Environment details

  1. "@types/google.maps": "3.47.4" and "@googlemaps/markerclusterer": "1.0.24"
  2. Windows 11
  3. Angular v13.2.3

Steps to reproduce

  1. Download npm i @googlemaps/markerclusterer
  2. Download npm i @types/google.maps --save-dev
  3. Create a component and use it as bellow
  4. Do not forget to add the GoogleMapsModule in the import

Code example

<google-map #googleMap width="100%" height="100%" (idle)="initClusterer($event)">
  <map-marker-clusterer *ngIf="googleMap?.googleMap">
    <ng-container *ngFor="let i of items">
      <ng-container *ngIf="i.categories | haveCategory: targetCategory">
        <map-marker #markerElem [position]="i.position"> </map-marker>
      </ng-container>
    </ng-container>
  </map-marker-clusterer>
</google-map>
@ViewChild('googleMap', { static: true }) googleMap: GoogleMap
markerCluster?: MarkerClusterer

initClusterer(e) {
    console.log('initClusterer', e)
    if (!this.googleMap?.googleMap || this.markerCluster) return

    console.log(this.googleMap, this.googleMap.googleMap)
    this.markerCluster = new MarkerClusterer({
      map: this.googleMap.googleMap,
      markers: this.markerElem,
    })
}

Then works as soon as I do add the following in my index.html
<script src="https://unpkg.com/@googlemaps/markerclustererplus/dist/index.min.js"></script>

Stack trace

vendor.js:91237 ERROR Error: MarkerClusterer class not found, cannot construct a marker cluster. Please install the MarkerClustererPlus library: https://github.com/googlemaps/js-markerclustererplus
    at MapMarkerClusterer.ngOnInit (vendor.js:125746:15)

algorithm use with no-module oriented

Hello,

I not use the typescript and module to use this library, all work like a charm except for algorithm parameter.
How to ​use default algorithm ?

How to use specific algorithm like Super or Noop or create new with non-module programmation ?

Thanks

const interpolatedRenderer = {
                render: function ({ count, position }, stats) {
                    // use d3-interpolateRgb to interpolate between red and blue
                    // create svg url with fill color
                    const svg = window.btoa(`
                      <svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240">
                        <circle cx="120" cy="120" opacity=".8" r="70" />
                      </svg>
                    `);
                    // create marker using svg icon
                    return new google.maps.Marker({
                        position,
                        icon: {
                            url: `data:image/svg+xml;base64,${svg}`,
                            scaledSize: new google.maps.Size(60, 60),
                        },
                        label: {
                            text: String(count),
                            color: "rgba(255,255,255,0.9)",
                            fontSize: "12px",
                        },
                        // adjust zIndex to be above other markers
                        zIndex: Number(google.maps.Marker.MAX_ZINDEX) + count,
                    });
                },
            };
new markerClusterer.MarkerClusterer({
               ​markers: markers,
               ​map: map,
               ​renderer: interpolatedRenderer,
               ​algorithm: markerClusterer.MarkerClusterer.algorithm.NoopAlgorithm
           ​});

Typo in README.md

Hi, there is an issue in the casing with this line:

When adding via unpkg, the MarkerClusterer can be accessed at markerclusterer.MarkerClusterer.

markercluster should be camel case.

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.