Leaflet: drift of coordinates after zooming

Created on 10 Jan 2012  Â·  10Comments  Â·  Source: Leaflet/Leaflet

var mapCenter = new L.LatLng(10.000000, 10.000000);
map.setView(mapCenter, 1)
for (i=2;i<19;i++){
map.zoomIn(); }
map.getCenter() - returns (9.96885, 9.84375)
Second place is shifted ca. 20km
Whether it is a rounding error, or screen coordinates conversion?

bug projections

Most helpful comment

I don't agree, it's quite a minor issue. Actually it is only visible in a case where user calls panTo and setZoom in succession separately instead of calling setView with the needed center and zoom immediately, how it is supposed to.

This error happens because when you call panTo, the center is set within 0.5 pixels precision so that it displayed crisply on the screen (without subpixel antialiasing). Because subsequent setZoom is independent operation, it doesn't know about the exact location that was passed to the panTo call, it only knows about the map's current state. It's quite a reasonable behavior, so I consider this issue a minor feature instead of a bug. Just use setView when you need to set both center and zoom and you should be fine.

All 10 comments

The issue seems to be occurring only when width and/or height of the map's container element is odd. When the map is zoomed in, the new center coordinates are calculated using the center of the map which ends up being half a pixel off at the current level but is rounded up and causes it to be off by 2 pixels at the next zoom level. I think just flooring that pixel value may fix it, but not sure if it'll affect other calculations.

The issue seems to be occuring not only with odd container dimension. Tested with even/odd values - same results. It seems that fault inversely proportional to zoom. Simple setView / getCenter returns another coords.

That's because of internal rounding of coordinates. I'll try to come up with solution to this.

This should be classified as a bug, not a (minor) feature. The fact that the actual center that panTo() and setView() go to has a margin of error proportional to the current zoom level is a) undocumented and b) likely of significant interest to many developers.

I quantified the extent of this error using the following code:

var d = map.getBounds().getNorthEast().distanceTo(map.getBounds().getSouthWest()),
    b = map.getSize();
var err = Math.round((d / Math.sqrt(b.x*b.x + b.y*b.y)) / 2); // error in meters
console.log(err + ' @zoom=' + map.getZoom());

... and came up with the following:

"11277 zoom=0"
"4747 zoom=4"
"300 zoom=8"
"19 zoom=12"
"1 zoom=16"

To put this into context, note that HTML5's geolocation API often returns coordinates with an accuracy in the 20-60m range. Thus, if you "center" the map at a zoom level <= 12, the error of the center is as much or more than that of your data point. (I actually got bit by this because was doing map.panTo(); map.setZoom(16); on a map on which I have a center-crosshair displayed, and kept seeing wildly inaccurate view behavior depending on what the starting zoom level was.

I don't agree, it's quite a minor issue. Actually it is only visible in a case where user calls panTo and setZoom in succession separately instead of calling setView with the needed center and zoom immediately, how it is supposed to.

This error happens because when you call panTo, the center is set within 0.5 pixels precision so that it displayed crisply on the screen (without subpixel antialiasing). Because subsequent setZoom is independent operation, it doesn't know about the exact location that was passed to the panTo call, it only knows about the map's current state. It's quite a reasonable behavior, so I consider this issue a minor feature instead of a bug. Just use setView when you need to set both center and zoom and you should be fine.

I don't agree, it's quite a minor issue.

While I agree this isn't a showstopper problem, are you sure you've considered all the implications ...

Actually it is only visible in a case where user calls panTo and setZoom in succession separately instead of calling setView with the needed center and zoom immediately, how it is supposed to.

No, it happens anytime the zoom level is changed (by the developer _or user_) after the map has been centered on a coordinate. As a developer you don't necessarily want to assume you know what zoom level the user wants - (as a user, having to constantly zoom in or out to stay at a preferred zoom level is annoying!) - so sometimes it's better to just center the map and let the user deal with zoom setting.

This will be particularly noticeable if the user asks you to center the map at some marker location, and happens to be at a low zoom level at the time. For example:

  • Go to http://leaflet.cloudmade.com/
  • Zoom the map out to level 5, to where you can see most of Britain.
  • Center the map on the marker via map.panTo(marker.getLatLng())
  • Now start zooming in using the zoom control
  • _by zoom level 14, the marker is off-map(!)_

Basically, this'll be an issue anytime the user wants "big-picture" context, with the ability to drill in for low-level detail... which is kind of what's so cool about online maps. Anyhow, sorry if this comes across as whiny - 'not my intent. I just want to make sure this is problem is appropriately classified. Thanks!

Is it meant to work with custom Map Projection using proj4Leaflet? I am using custom Map projection, Leaflet-Leaflet-bd80381/dist/leaflet-src.js and I sadly still see this annoying behaviour :/
I just create the map with lowest zoom level possible. Than i just click Leaflet zoom buttons: zoom in to the max, zoom out to the min, zoom in to the max and the view is not the same...
Ahh and I noticed one little issue which might be related: sometimes after some zoom and pan actions, when you zoom out to the min level, zoom button visually disables, but you still can press the "zoom out" button, which pans a map a pixel or so sideways...

The center resets after the map is panned (even by one pixel) and becomes projected from the pixel position of the map pane, so it becomes off on a different zoom level... Can you make a minimal test case on JSFiddle that reproduces that one-pixel-shift problem and report as a new issue?

Sorry, I think it's quite hard to reproduce it programmatically, because it
occurs after some quick zoom-pan actions. That's not a big deal to have
such a little bug as only few people would press visually disabled button
anyways, but I wonder if it would be related with some view drift after
zoom, because this drift drives me crazy. I used to use ArcGIS JS API in
the past, I have tested OpenLayers samples and they don't seem to have
coordinates drift problem. Leaflet has :/

On Sat, Jun 8, 2013 at 11:31 AM, Vladimir Agafonkin <
[email protected]> wrote:

The center resets after the map is panned (even by one pixel) and becomes
projected from the pixel position of the map pane, so it becomes off on a
different zoom level... Can you make a minimal test case on JSFiddle that
reproduces that one-pixel-shift problem and report as a new issue?

—
Reply to this email directly or view it on GitHubhttps://github.com/Leaflet/Leaflet/issues/426#issuecomment-19145341
.

Well, I can't reproduce this bug, I can't see any drift of coordinates when zooming back and forth (at least with the default projection), so I have to close the issue. Will reopen after you're able to describe clear steps to reproduce.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

piehei picture piehei  Â·  3Comments

timwis picture timwis  Â·  3Comments

JonnyBGod picture JonnyBGod  Â·  4Comments

edmsgists picture edmsgists  Â·  3Comments

pgeyman picture pgeyman  Â·  3Comments