shramov/leaflet-plugins

Google : laggy panning

SeBsZ opened this issue · 30 comments

I'm adding markers in real-time every few seconds to leaflet. When viewing using OpenStreetMap tiles, it pans nicely to the new marker. When using Shramov's Google plugin there is a strange lag/flicker when the map pans to the new marker.

It's hard to explain. The markers are close together, only a few 100meters apart. This "bug" is observed in IE11 and Chrome.

This image shows the moment of panning. The fact that tiles are missing is not a huge problem for me, but the panning animation is very laggy. Even existing markers and polylines move "stuttering".

mapbug

Hopefully I managed to be clear in explaining the issue. Thanks!

I can confirm that bug while using google maps layer, problem discovered with FF & Chrome on Mac, but Safari works fine. Looks like animation issue. Observed for vector features and raster overlays.

Hi and thanks for the bug report. I already know that google layer are bugy/lagy/etc but i don't want to spare time on it cause we still don't know if this kind of usage is compilant with google TOS as said in #48 ...

Anyway, feel free to provide a patch to handle this bug :)

It would be nice if @SeBsZ or @dobrych could provide a jsffidle showing the bug in order to allow anybody interested to work on this bug. Does anyone of you guys have found a patch or a workaround for this bug ?

I have this bug too, and have found a solution.

The problem is that you synchronize the layers using async events which is very bad :(

eg:
Layer 1, Markers = Leaflet
Layer 2, Google = OSM / Google

Layer 1 move -> update event -> async update Google layer position

The way to solve this, is to synchronize the layers upper in the chain, eg. tapping into the mouse move event or similar and in THIS position, move all layers simultaniously.

Maybe the Google.js plugin layer could inject callbacks into Leaflet, which is fired when Leaflet is moving around.

Nice, thanks for the hint @Montago :) Could you try to provide a patch for it ?

investigating further... it seems that Google API is built on being async.

try opening Google maps and drag around very fast, the map is moving in a delayed fashion.
Leaflet on the other hand, moves linearly and without delay.

So maybe the solution is to inject callbacks into the Google API engine (google.js plugin) ???

eg: Leaflet register mouse move event, but calls Google API first, then update the center/zoom position after Google has done its magic ...

its really messy 👎

its really messy

You got the point :p And we still don't know if this usage of google tiles is ok with their TOS, that's one the reason i don't want to give time on it :\

According to Leaflet:

..."The problem with Google is that its Terms of Use forbid any means of tile access other than through the Google Maps API.

You can add the Google Maps API as a Leaflet layer with a plugin. But note that the map experience will not be perfect, because Leaflet will just act as a proxy to the Google Maps JS engine, so you won't get all the performance and usability benefits of using Leaflet when the Google layer is on."...

So i guess that it's not OK to grab the tiles indivually and inject them into Leaflet - but its ok to relay the mouse inputs and display maps as a background... heck, this is being done in many places, so i guess they are OK with it.

I have a meeting with the Google Maps folks in a couple of days, maybe they will throw a few ressources onto this matter.. Our company is the biggest Google Maps costumer in our country afterall 👍

I know that, all this as been discussed in #48 ;)

I have a meeting with the Google Maps folks in a couple of days, maybe they will throw a few ressources onto this matter..

Nice, hope you'll have good news for us after that meeting :)

take a look at this:
http://stackoverflow.com/questions/22306130/how-to-limit-google-maps-api-lag-when-panning-the-map-with-lots-of-markers-and-p

http://jsfiddle.net/CX4gN/3/

according to the source, the problem with lag, is because Google API can't handle all the mouse move events, so by throttling the events, the movement of GMap is more linear.

try setting the period to 0 ms

investigating further

Google.js:

this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this);

removing / disabling this line, reduces the lag,

Internet Explorer 11 DO NOT LAG.. its only Chrome and Firefox that lags... (maybe more)

I've noticed that Leaflet also throttles the input.. and have tried replacing that with the suggested script above.. seems to help a lot.

Awesome research @Montago ! Indeed, disabling that line in Google.js helps to fix this issue in my case as well.

Although I must say it isn't really a 'fix' it's an improvement since the real issue (async events) is still here.

Did the discussion with the GMaps guys lead to anything?

Hi... I asked Google about a few things but haven't heard from them.

We decided the toss out Leaflet and go clean with Google API 3.xx - Its not as smooth and easy to use as Leaflet, but thats how it is and we can live with it. Our biggest reason to get Leaflet was Skobbler maps - but since they are 15 times more expensive than Google the choice was easy.

Leaflet has (to some degree) better API and map movement and also better rendition of markers and custom layers... but mr and mrs Noob wouldn't notice in a million years...

Sorry i can't be of more help - but now you know whats up and down.

Thanks for the update. Clear story. I tend to go back to 'vanilla' Google Maps API as well since it has a much better performance.


This email was sent from my iPhone and therefore subject to typos and other inaccuracies.

On 1 dec. 2014, at 18:22, Montago notifications@github.com wrote:

Hi... I asked Google about a few things but haven't heard from them.

We decided the toss out Leaflet and go clean with Google API 3.xx - Its not as smooth and easy to use as Leaflet, but thats how it is and we can live with it. Our biggest reason to get Leaflet was Skobbler maps - but since they are 15 times more expensive than Google the choice was easy.

Leaflet has (to some degree) better API and map movement and also better rendition of markers and custom layers... but mr and mrs Noob wouldn't notice in a million years...

Sorry i can't be of more help - but now you know whats up and down.


Reply to this email directly or view it on GitHub.

Yeah well, in some cases... as soon as you start using RichMarker to show HTML on the map, Google Maps really starts to suck :(

just 50 markers with 10 div's and 1 image each, will slow it down
and don't even try adding SVG icons to Google maps o_O !!!

Apparently it's fine to use Leaflet if you have a Maps for Work license.

I can confirm that use with leaflet while under a Maps for Work license was allowed, after directly requesting confirmation of this use case from our account manager.

Thats nice and all but there are free alternatives that perform just as good without the need of fancy licenses.

I could just use the Google Maps API for a map implementation instead of using Leaflet + Maps for Work license, you know what I mean?

The issue is the implementation while building a paid product. All of the big providers except Bing explicitly disallow that use, including MapQuest.

So when I have for instance a paid app that uses Leaflet, that's not allowed? Even when I give full credit in lets say an 'about' page or so?

It's unfortunate that Leaflet doesn't really work that well with Google map tiles (panning and zooming lags and seems a little off).
The reason why I would prefer to use Leaflet is because the Google Maps V3 API is rather rigid and has but a handful of plugins to use. Leaflet on the other hand has a full community behind it, which means a much nicer library to use for development and many plugins that can really help speed up development.

Some examples: Google's MarkerClusterer plugin doesn't work as well as Leaflet.markerCluster. InfoWindows can't be styled without a DOM tree traversal hack and the InfoBubble plugin isn't great either.

Attribution guidelines are extremely specific. Most require attribution be displayed on map at a minimum. Furthermore, most attribution is secondary meaning Google is adhering to someone elses attribution requirements, and that is why they are so specific about how people use their maps.

As for using google maps, or any provider, without a formal licensing agreement behind any pay wall(lisence, purchse, subscription), that is very grey, and unless there are specifically allowed app based terms it is without a doubt violating TOS.

I dont know if you're using Angular @TheSisb but if you do you could give angular-google-maps a try. It's very extensive with loads of addons and features.

I hadn't seen that. It looks like a step in the right direction (for Google Maps) but we don't currently use Angular on our project. If the decision is made to use Google Maps over an alternative at this point, I may include Angular in our project just for the map. Seems like overkill though.

[Edit] After a more thorough inspection, it doesn't seem to offer much improvement at all. It just seems to be a wrapper over Google's existing API, which is lackluster.

As you confirmed yourself; that seems like an extremely unwise choice. Using a full framework just to use a plugin for that framework is indeed a huge overkill.

Don't know if you're familiar with PHP but it's like installing all of Symphony just to send an e-mail. Or including jQuery just to change the contents of a span once.

Like I said; overkill. Choose wisely which framework / library / plugin to use and why.

Edit: we're getting offtopic here and polluting the main issue.

Closing this old issue since nobody is working on it. Feel free to provide a pull req for that :)

rcknr commented

@brunob I've tried to get around this and used several techniques to make it smoother but the best it got is like this https://jsfiddle.net/rcknr/jqyjup8g/ i.e. just slightly less horrible than it is right now.
Do you want me to pull request this?

@rcknr yes a PR would be nice and more easy to see the diff :)

r1g0 commented

Changing this line

this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this);

to

this._limitedUpdate = L.Util.limitExecByInterval(this._update, 0, this);

really improved it for me.