googlemaps / js-markerclusterer Goto Github PK
View Code? Open in Web Editor NEWCreate and manage clusters for large amounts of markers
Home Page: https://googlemaps.github.io/js-markerclusterer/
License: Apache License 2.0
Create and manage clusters for large amounts of markers
Home Page: https://googlemaps.github.io/js-markerclusterer/
License: Apache License 2.0
[Sorry for multiple points in the same issue]
Migrating from (depreciated) https://github.com/mahnunchik/markerclustererplus to v2.0.4
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.
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 π¦π
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.
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.
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.
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.
In the previous js-markerclustererplus
there is an option minimumClusterSize
that sets
The minimum number of markers needed in a cluster before the markers are hidden and a cluster marker appears.
https://googlemaps.github.io/js-markerclustererplus/interfaces/MarkerClustererOptions.html#minimumClusterSize
How to set that minimumClusterSize
option in this new library?
when installing via npm instead of downloading source under releases results in the following
npm is looking for src directory but it does no exist all files are located in dist.
this occurs on multiple imports
I gave been trying to add custom icons for Marker Clusters and am not able to find the feature.
The official documentation mentions the below (https://developers.google.com/maps/documentation/javascript/marker-clustering#npm_1)
Customize the cluster icon through the renderer interface.
But the option is not visible in the API.
Any help is much appreciated.
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:
If the marker is zoomed at level 15 then map 2 will display the marker correctly.
Steps to replicate:
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?
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 !
Please tell me how to change the icon picture for a cluster?
Hi, me again !
Do you think it is possible to add a radius
parameter in the Super Cluster Algorithm Options ? I saw it is fixed to 60 in the supercluster.ts file on line 41. If I could have set my own value, I would have go with that algorithm instead of the Grid Algorithm. With the grid one, I can set a grid size.
Thanks π !
https://codesandbox.io/s/competent-newton-v1mpo
50,000 markers
out of memory browser crash
click on two clusters
click drag right
page becomes unresponsive
in both chrome & firefox
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.
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()
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.
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
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!
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.
I think it could be interesting to have a mechanism that detects duplicate markers when using the function addMarker
of a MarkerClusterer instance.
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?
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
To support the spiderify use case, it may be beneficial for the render signature to be widened to anything that implements setMap
.
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.
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.
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.
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.
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?
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
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)
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.
1.Using script api <script src="https://unpkg.com/@googlemaps/markerclusterer/dist/index.min.js"></script>
2. Inside a vuejs app
You should see like me clusters of size 0
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 ;)
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));
β¨ }
β¨});
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?
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 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:
Hi,
Very simple thing : in the documentation for the MarkerClustererOptions, it says the default algorithm is GridAlgorithm but on line 81 of the markerclusterer.ts file, the SuperClusterAlgorithm is default. It took me some time to figure this out since my implementation wasn't working as expected.
Thanks !
Just a few tips for Angular users & a bug (I think).
Please be sure to include as much information as possible:
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]
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,
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!
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
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.
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();
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.
Just another option for those looking to manage a large number of data points with Google maps:
https://github.com/bdcoder2/grid_clusterer
If interested, I would be more than happy to send you the source code (Typescript) for inclusion as an option for Google maps.
I cannot use this library with angular without installing the markerclustererplus library.
"@types/google.maps": "3.47.4"
and "@googlemaps/markerclusterer": "1.0.24"v13.2.3
npm i @googlemaps/markerclusterer
npm i @types/google.maps --save-dev
GoogleMapsModule
in the import<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>
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)
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
β});
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.