Leaflet: Map is moving by itself when zooming in/out using mouse wheel and after reaching maxZoom

Created on 21 Apr 2016  Â·  16Comments  Â·  Source: Leaflet/Leaflet

The problem appears when I'm using a custom projection EPSG:25833 (UTM33 for working in an area of Norway) and going through these steps:

  1. Go to a really far point in the west of Norway (for example, Utsira island - use the button in the example under the map)
  2. Zoom in to the maxZoom level using mouse wheel (few levels before maxZoom also shows the same issue)
  3. Try zooming in/out without moving the mouse around and you will see the map slowly drifting away from the point where your mouse is located - moving to the right side of the cursor (if we move to a point of east Norway, then the map will be drifting the other way)
  4. Then while on the maxZoom level you can drag the map a little bit (even the smallest drag "helps") and you will be able to make the map move right again by clicking the disabled zoom in button on the zoomControl and clicking it intensively will just keep the map moving

Example of this behaviour:
Leaflet 0.7.7 + Proj4js 2.0.0 + Proj4Leaflet 0.7.2
http://playground-leaflet.rhcloud.com/quj/edit?html,output
Leaflet 1.0.0 (master) + Proj4js 2.3.14 + Proj4Leaflet (Leaflet 1.0.0 branch)
http://playground-leaflet.rhcloud.com/vod/edit?html,output

Reference of the MapServer used in the example for the tiles with the resolutions of the zoom levels and the origin:
http://services.geodataonline.no/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBasis/MapServer/

So I am able to reproduce this behavior in both Leaflet 0.7.7 and Leaflet 1.0.0 (master), but I am not sure if this is an issue with Leaflet, Proj4js or Proj4Leaflet. The issue is there on Windows in Chrome, Firefox and IE11.

I am not sure if I have found anything useful, but I was able to understand that when the Step 4 is happening L.Map.containerPointToLayerPoint() function is receiving slightly moved position of the map pane (10px on the x coordinate, 1px on the y coordinate) which is returned by this function L.Map._getMapPanePos(). Hope this helps somehow.

Also I would like to say that this is an absolutely beautiful library that just keeps on getting better.
Great job and keep up the good work, guys.

bug projections

All 16 comments

Hhhhmmmm. The only thing I can see is that the tiles flicker for a tenth of a second when the zoom animation ends and the new zoom level snaps in, and that it happens when the zoom level is high.

I think this is just an issue of the Kartverket tiles being out of alignment, I'll double-check.

The effect is much more noticeable when using a debugging GridLayer and going to a place much further apart (like Vardø): http://playground-leaflet.rhcloud.com/rube/1/edit?html,output

I do think this is a proj4-related issue. @perliedman should have a look.

@IvanSanchez Thanks for looking into this so fast.
Yep, the issue looks brutal in your example. I was first convinced that it was an issue with Proj4Leaflet, but then I started to doubt myself because of the zoom in button issue at the maxZoom level.

Zoom working fine in Oslo: https://drive.google.com/open?id=0B8DaJcGLql99bzV0OUpLUTdtOEk
Zoom working not so fine in Utsira: https://drive.google.com/open?id=0B8DaJcGLql99TWdvclhWSGQ3WkU
Zoom in button misbehaving at maxZoom level: https://drive.google.com/open?id=0B8DaJcGLql99Sm1Bcm5XZVRBMUE

Very weired. Also note that the problem doesn't happen until you have dragged the map - as long as you _just_ use the zoom controls, everything is fine. If you drag or zoom with the mouse wheel, things start to go crazy (also when using the zoom controls).

I _think_ this is because the projection seems to be highly unstable, for some reason, meaning that if you simply project a lat/lng and then unproject it, you get a significantly different result back.

I did the following test, which does the project/unproject cycle ten times:

zoom=18;
point=map.options.crs.latLngToPoint(map.getCenter(),zoom);
ll=map.options.crs.pointToLatLng(L.point(point), zoom);
for (var i = 0; i < 10; i++) {
    p = map.options.crs.latLngToPoint(ll, zoom);
    ll=map.options.crs.pointToLatLng(L.point(p), zoom);
}
p.distanceTo(point);

For spherical mercator (EPSG:3857), Leaflet's default, this gives a distance of 2.23e-8 - a _very_ small difference, the projection is very stable.

In comparison, the same code for EPSG:25833 gives a _huge_ difference of 420!

From some tracing, I think this is the problem: when zooming, Leaflet projects/unprojects the center, which moves a couple of pixels every time because of the unstable calculation.

I think the next step is to see if this unstable behaviour also occurs with just Proj4. I'm running late here, so I will have to pick this up later.

Huh.

This begs the question: Should we be storing the map center as a LatLng, or should we change everything and use a Point in CRS units instead?

It's kinda a huge change but the only way I see of fixing this.

Looking a bit more at this, it is apparent that the problem gets worse the further north you go. I can't reproduce it in Oslo or Trondheim, but it starts showing if you go to the northern parts of Norway. Running a test with just Proj4 shows the same - the projection starts becoming unstable if you go to high latitudes.

I've tried to find info on the bounds for UTM zone 33N, but have not found much more than it should start showing deformation in high latitudes.

@IvanSanchez what you're saying makes sense: internally we very rarely care about latitudes and longitudes, but very much about projected coordinates or pixel coordinates, latlngs are the API for the user.

I guess we should be able to work around some of the weirdness in situations like this if we more consistently used projected coordinates throughout the code.

Having said that, the refactor would be enormous, as you say, and the gain is mostly in corner cases like this (except for, maybe your WebGL plans :wink:), and might have some unexpected new behaviours in corner cases.

Also, things like #2553, which is mostly possible today, would also be a lot harder if we used projected coordinates more internally.

That is the one thing that we in our team also noticed when we needed to just project/unproject a point to draw a rectangle on the map by dragging one of the vertexes (we us Leaflet.Editable plugin for this and LatLng does not work with this since the map projection is UTM 33 and drawing it on LatLng just shows up in slight rotation) and on the west side of Norway it just started to drift apart. Everything was drawing just fine in the bounds of the actual UTM zone 33N, but when you go out of it it just drifts apart and further you go from the actual bounds of the zone, the more mess it causes.

Rotated rectangle on LatLng https://drive.google.com/open?id=0B8DaJcGLql99NkRDNmhDTG1wR3M
Rectangle draw in Oslo https://drive.google.com/open?id=0B8DaJcGLql99OGN5aTY2VTY5UWM
Rectangle draw in Utsira https://drive.google.com/open?id=0B8DaJcGLql99eWxhZFNqZ0s0TFk
Polygon draw in Vardø https://drive.google.com/open?id=0B8DaJcGLql99SHc3U1dpMWlFd0U

Norway is covered by the UTM zones from 32 to 36 and when we switch the map projection to UTM 32 and do the same drawing of rectangle in Utsira, it does not drift apart there, but does in parts near Oslo then which it did not on the UTM 33. So probably changing to UTM 36 for Vardø would make it smooth there.

Right now we are considering of trying to use container points for the drawing of the rectangle and not involving the projection in this, but we haven't tried it yet.

Looks like the problem does not show up for Oslo and Trondheim, because the UTM 33N is the correct zone for Oslo and UTM 32V is the one for Trondheim, which is pretty close to UTM 33N, probably.

I have also thought about the need for our solution to switch the CRS of the map on the go so we can basically try to see where the user is located on the map and then use the correct CRS for that location, but there would also be some edge cases where the view of the map is on the edge of two UTM zones.

Thanks for your input @perliedman

I also filed an issue on Proj4js with this: https://github.com/proj4js/proj4js/issues/187

Using the C version of Proj.4 (cs2cs), I get much, much smaller differences (but still differences), so there might be a possibility to fix this in Proj4js.

Thanks for that. I hope there is a possibility to fix this, because I have spent a lot of time fighting this before posting it here and it would be pretty sad if there would be no hope.

Also do you think the "Zoom in" button of ZoomControl should act like that when the maxZoom level is reached? Should it keep trying to zoom in more even though we are at the maxZoom level? Shouldn't there be a check for maxZoom level somewhere in this function or in the this._map.zoomIn() function?

_zoomIn: function (e) {
    if (!this._disabled) {
        this._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
    }
}

@perliedman @IvanSanchez Any thoughts?

Edit: The issue with "Zoom In" button and maxZoom level has been fixed here https://github.com/Leaflet/Leaflet/pull/4791

Hi, all,
the issue https://github.com/proj4js/proj4js/issues/187 has been fixed and was the main reason this issue here was popping up.

There is a new version 2.3.18-alpha of proj4js out which uses etmerc for doing projections using the utm projection and the more numerically stable projection of etmerc has helped to solve the issue of the utm projection being unstable.

Here are the updated examples, using the latest version of proj4js and without the weird movements of the map by itself as described in this issue:
http://playground-leaflet.rhcloud.com/hib/edit?html,output
http://playground-leaflet.rhcloud.com/kuz/edit?html,output (this one is using a debugging GridLayer)

So I would say that this is finally fixed and can be closed. ✨

So I would say that this is finally fixed and can be closed. :sparkles:

Roger that.

@theashyster great addition to Proj4js, and great job hanging in there and actually solving this pretty tricky issue!

@perliedman Yes, thanks for the help and praise. :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jcarenza picture jcarenza  Â·  3Comments

JonnyBGod picture JonnyBGod  Â·  4Comments

timwis picture timwis  Â·  3Comments

prbaron picture prbaron  Â·  3Comments

arminghm picture arminghm  Â·  3Comments