Spreading markers out as necessary in Google Maps - javascript

I'm displaying many (hundreds) of markers at a time in a given viewport in Google Maps. Often, this leads to markers being drawn over each other.
Since the exact positions aren't as important at zoom levels where so many markers are drawn, is there a library or piece of code that allows markers to dynamically update their position based on whether they are overlapping with other markers or not? As the user zooms in (and markers becomes more sparse), the markers will then move closer to their real positions.
And yes, I know about groupings, marker clusterings, etc. Those solutions aren't appropriate in my situation, since it is important that all markers be displayed at all times. And in actuality, I am already using those techniques as well, where appropriate. I'm using the Javascript V3 API.

You probably need to implement your own clustering algorithm - I think Google Maps let's you implement your own strategy (I know Bing Maps does, and typical they copy each other within 6 months or so of a new feature being implemented).
Note that for lots of dense pushpins, your constrains of separation but displaying all pins, are in conflict.
as for a strategy, my first thought is an annealing type of algorithm, although it probably isn't very fast. Basically each pushpin would exert a force on surrounding pushpins within a certain distance. iterate until sufficiently stable.

Related

BingMaps Is it possible to disable clustering below certain zoom level?

My map pushpins are relatively close to each other and even on a big zoom I still see them clustered.
I solved this issue by spreading the clustered pushpins by some random distance 5-10 meters.
I need more accurate solution so my idea is to disable the clustering below the certain zoom level, but I didn't find any way how to do it.
There is no option to disable clustering in the clustering layer in Bing Maps, but what you can do is monitor the zoom level of the map, and when it gets to a certain point, hide the cluster layer and load a new layer that isn't clustered. Unfortunately this means having two copies of your data in memory.
If you haven't fully committed to using the Bing Maps platform, you may also want to take a look at Azure Maps. The Azure Maps web SDK does things a bit differently where you would keep your data in a single data source and attach rendering layers to it. Clustering is turned on in the data source and has a max zoom level option for clustering.
Here is some examples: https://azuremapscodesamples.azurewebsites.net/index.html?search=cluster
Here is documentation: https://learn.microsoft.com/en-us/azure/azure-maps/clustering-point-data-web-sdk
There is an option clusteringEnabled now on ClusterLayerOptions which will disable clustering without losing the whole layer.
eg:
Microsoft.Maps.Events.addHandler(this.map, 'viewchangeend', () => {
// de-cluster at highest zoom level
this.clusterLayer?.setOptions({
clusteringEnabled:
this.map.getZoom() < this.map.getZoomRange().max
});
});

Best practice for handling thousands of circle markers with leaflet

I'm drawing a large number of markers (~3,000), and for performance reasons, would like to have the ability to only draw the markers which are in the visible area.
Any advice would be much appreciated.
Thanks
You can put your points into a spatial index, and query that index each time the map's bounds changes, adding and removing markers as you move.
One such spatial index is RBush by Vladimir Agafonkin / mourner, the author of Leaflet.
Having said that, it might not be worth it for 3000 markers, which most clients should be able to handle.
You might also want to look at Leaflet.markercluster if you haven't already. It can handle very large amounts of markers.

How to deal with multiple Google Maps markers on the exact same position

What I'm trying to do is finding an elegant way of dealing with multiple markers on the exact same spot on a google map. Possible scenarios are when your geo data just isn't accurate enough to distinguish two markers from one another (say 3 people live in the same house and all you have is an address) or you only have city information of a couple of shops.
Now there is the Clusterer of course, everybody is saying that, but that won't help here as the markers have the exact same location. They will stay clustered regardless of zoom level.
I like the way Google Earth does it. Here is an example. But so far I have not discovered a way to have this behavior in Google Maps. I would be pleased if someone can show me how to do this.
So perhaps as you are looping through your coordinates adding all the markers, you could check if any previous marker has the same latlng. If it has you could use a different marker, e.g one numbered '2'. Or to do the Google Earth thing, offset each marker slightly, and draw a polyline from the markers to the original location.

Google Maps Best Practices?

We started using Google Maps on our web application rather extensively. It worked fine at the beginning, but as we add more markers we find that the performance are not quite there. Although I'm quite sure we don't use it in the most efficient way.
I am looking for information about Google Maps best practices and tips'n tricks. Any suggestions?
You might find some good ideas in this article, which compares several methods of handling large amounts of markers.
Marker Manager has some limitations, depending on what you're trying to accomplish; for instance, it doesn't allow every marker to be available from every zoom level. I created a clustering function based on the principles discussed in this tutorial. It uses the Static Maps API in PHP, but the principles behind the clustering can be used however you want.
Update: This clustering utility was just released: MarkerClusterer
Use Marker Manager.
Limit markers to what's visible (ie, understand the window boundaries, and only show markers that fall inside the window)
Learn to listen for various map activities and react - such as viewpoint moves, zooming, etc - to update the markers
Don't show markers that overlap significantly - show only one marker (perhaps a different shade or color to denote there are several points at this marker) and let the user zoom in if they want to see the individual markers. Use the tooltip to show a zoomed in window if you want to get fancy.

Hybrid static/dynamic Google Map

Ever noticed that when you go to maps.google.com and do a search (say, car wash), it renders a lot of results (represented by small circles) and a few prominent ones (seen as regular-size pins)?
Notice how quickly it does this?
From what I can tell from analyzing this in Firebug, much of this is generated on the server and sent to the client as a static image.
However, it's still dynamic. You can still zoom in and out, or click on a result and see a dynamic InfoWindow rendered.
Google have made the map quick and smooth using static images, while still making it flexible.
Is there a way to do this kind of 'pre-loading' with my own Google Map (implemented with the Google Maps API)?
The technology that maps.google.com uses is similar to that used in a GLayer. The server dynamically builds tiles and "hotspot" info. The GLayer tiles are also constructed dynamically (and possibly cached) even though the underlying data is fairly static. From the client side, the searched dots technology is identical to the Wikipedia or Panoramio GLayer. The only new trick is that the dot information is generated dynamically on Google's big fast servers.
The API does not (yet) provide any tools for creating custom GLayers. If you want to do the same sort of thing yourself, using your own database of locations, there are three steps that you need to code:
Create your own custom tileserver
which searches your database for
items in the tile area and uses a
graphics library like gd or
imagemagic to place dots on the
tile. Use those tiles to create a
GTileLayerOverlay on the client.
When the user clicks on the map,
send the location of that click to a
second server. That server should
check your database and return the
infowindow text for the dot at that
location, if any. Returning all the infowindow contents from all the dots imaged by the tileserver would be unacceptably slow, so you have to fetch them one by one, as needed.
Changing the cursor when the mouse
is over a dot is more tricky. What Google
do is return a list of hotspot
coordinates for all the dots on each
tile. Whenever the mouse moves, the
API determines which tile the
pointer is over and uses a quadtree
algorithm to see if the pointer is
over a hotspot, and change the
cursor if necessary. If you only
have a modest number of hotspots per
tile, then a linear search would
probably be acceptably fast. If you might have thousands of dots per tile, then you'll probably need to write your own quadtree algorithm. The Google quadtree code is not exposed, so you can't use it.
Here's a page where somebody has done all that. In this case the hotspots are calculated as circles, by comparing the distance from the centre point, even though the dots are square. On maps.google.com the hotspots are calculated as rectangles, by using GBounds.containsPoint(), even though the dots are round.
I'm doing something similar - but instead using a tile layer, I just send server-clustered markers to the browser whenever the view changes. If your data is static, you can pre-cluster your markers and it would be incredibly fast with tens of thousands of markers.
Our site can't use pre-clustering because the markers can be searched and filtered, but it's still pretty fast up to about 20,000 markers. Still working on it...

Categories