Leaflet / Leaflet

🍃 JavaScript library for mobile-friendly interactive maps 🇺🇦
https://leafletjs.com
BSD 2-Clause "Simplified" License
40.28k stars 5.76k forks source link

Latest Chrome introduced 1px tile borders to integer zooms #6101

Closed hyperknot closed 2 years ago

hyperknot commented 6 years ago
half dome via mist trail by hyperknot maphub 2018-03-22 03-08-01

How to reproduce

  1. Use a map with a darker background colors, like Dark Matter.
  2. Pan around and you'll see the 1px grey tile borders.
  3. This was the biggest issue with fractional zooms in Chrome, now it's happening with integer zooms as well!

Safari and Firefox is still fine.

@IvanSanchez any chance of getting back the examples from: https://github.com/Leaflet/Leaflet/issues/3575

cc: @perliedman @yohanboniface @mourner

What should we do now? Open issues in Chromium and just hope for the best?

hyperknot commented 6 years ago

Created a CodeSandbox and a screen capture GIF: Edit ql1ymyr0n6

leaflet

It happens in non-Retina resolutions as well.

perliedman commented 6 years ago

😭

Can just confirm that I can reproduce this on Windows with Chrome 65.0.3325.181.

I seem to remember setting L_DISABLE_3D fixed the old issue with tile borders, but this does not appear to make any difference in the example you linked above.

IvanSanchez commented 6 years ago

I can reproduce on Chromium 65.0.3325.146 on linux.

At first sight this seems to be due to non-integer offsets when doing inertia panning.

perliedman commented 6 years ago

On a further update, I'm still seeing a lot of translate3d when I inspect the map in the DOM, even after setting window.L_DISABLE_3D = true, so maybe something else going on there.

Anyway, I'd say we should report this as an issue to the Chrome team. IIRC, they were at least sort of helpful last time we did that, even though it didn't fix the issue in the end.

IvanSanchez commented 6 years ago

https://github.com/Leaflet/Leaflet/blob/8a009fa662fd42efc3d720ab60d878c245f6e681/src/map/handler/Map.Drag.js#L212

Wait, the inertia offset is already rounded up. WTF?! :confused:

IvanSanchez commented 6 years ago

image

If the inertia offset is rounded up, why are the translate3d transforms fractional?! :confused:

perliedman commented 6 years ago

@IvanSanchez weird, but at least that look like something we can work on!

IvanSanchez commented 6 years ago

The rounded-up calls are called just once. I've traced the problem down to

https://github.com/Leaflet/Leaflet/blob/8a009fa662fd42efc3d720ab60d878c245f6e681/src/dom/PosAnimation.js#L77

The fix would be to somehow pass an option to PosAnimation to round the coordinates on every animation frame.

Widdershin commented 6 years ago

Rounding is not necessarily an ideal solution, because on a retina display you actually have twice the number of physical pixels as what the browser reports, so translate(0.5px) will actually have a visual and useful consequence on retina.

I was able to create a minimal reproducer without using Leaflet.js, so it looks like it's actually a bug in Blink.

I've opened an issue over on the Chromium tracker so hopefully we can get it resolved there:

https://bugs.chromium.org/p/chromium/issues/detail?id=825711&can=2&q=subpixel%20image&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified

If you'd like to see this bug resolved I think they like people to star issues to reflect that.

Widdershin commented 6 years ago

Additionally, I think this issue actually spans beyond zooms, I think it's about any subpixel translation.

I can reproduce this consistently:

1) Open this demo: https://esri.github.io/esri-leaflet/examples/switching-basemaps.html 2) Switch the basemap to "Imagery" to increase the contrast 3) Pan the map to the east. If you finish such that the pan is not a whole number, you'll see gray lines between the basemaps.

ghost commented 6 years ago

For consideration, the borders even though I don't see them on panning in Firefox 59.0.1 (rpm) they show during the animation on every zoom-operation.

@Widdershin Hi, for retina the physical pixels are calculated to CSS-pixels, and treated as such, so why would you need to take the actual physical pixels into account for the layout? I think that is irrelevant. If translate(0.5px) have a visual effect for you is it not because it has been rounded by the layout engine to display as 1 CSS-pixel? https://www.w3.org/TR/css3-values/#absolute-lengths

hyperknot commented 6 years ago

@Widdershin zoom is only important here, because it's been like this forever for fractional zoom levels. Now this introduced the same bug to integer zoom levels as well.

hyperknot commented 6 years ago

Hi everyone, I've also commented on the Chrome bug (@Widdershin thanks for reporting), the Chromium team seems to be interested in resolving it, and are asking which was the version which introduced it. Can you help with this? I cannot install old versions of Chrome on macOS, and in a Parallels Virtual Machine the issue is not present.

If you are on a different OS, maybe you can try portable Chrome or something similar to find out which version introduced it. Can you help finding this out?

ghost commented 6 years ago

@hyperknot Hello, sorry I don't know the first version, I downgraded and checked Chromium 61.0.3163.100-1.fc27 and the borders show there too if I do a quick pan and release the mouse button, they show until the animation has ended.

Widdershin commented 6 years ago

For consideration, the borders even though I don't see them on panning in Firefox 59.0.1 (rpm) they show during the animation on every zoom-operation.

Sounds like the zoom bug is actually different from the pan bug I reported to the chromium team, sorry for taking over this issue!

Widdershin commented 6 years ago

Related/possible duplicate of #3575.

Also see the Chromium issue that was raised as a result of that issue.

https://bugs.chromium.org/p/chromium/issues/detail?id=600120

lapo-luchini commented 6 years ago

Mhh, they upped the priority on July… let's hope.

Widdershin commented 6 years ago
image

Unfortunately the lower the number the higher the priority.

https://bugs.chromium.org/p/chromium/fields/detail?field=Pri

oliverheilig commented 6 years ago

What's most frustrating: You see these grid lines in Chrome even together with Google maps, and nobody seems to be bothered by this. Just use a scaling > 100% for the Windows desktop or the browser and open

https://www.google.de/maps/@54.3061614,2.0559393,5z grid lines

Maybe we are just too pedantic, but a dark theme renders Leaflet almost unusable with Chrome. Switch to the base map 'blackmarble' here

https://ptv-logistics.github.io/xserverjs/boilerplate/Leaflet.1.0.html

This problem doesn't occur with LL0.7 btw

https://ptv-logistics.github.io/xserverjs/boilerplate/Leaflet.0.7.html

So after years of suffering from this issue the only options i see:

  1. Make the map background black/dark for dark base maps
    .leaflet-container {
    background: #000;
    }  
  2. Use FireFox or Edge
  3. Use Leaflet 0.7
hyperknot commented 5 years ago

I can confirm that @oliverheilig's example is right, the 1px lines only appear in the 1.0 version, not in 0.7. So it seem that there is a way to solve this Leaflet side. If someone has the energy to find what causes Chrome to introduce the 1px lines in 1.0 and not in 0.7, it might allow a fix.

Widdershin commented 5 years ago

Latest update to that Chrome issue confirms they have no intention of fixing the issue anytime soon.

image

If anyone wants to fix this, I would recommend running a git bisect manually to find the issue.

oliverheilig commented 5 years ago

I've compared the code of 0.7 and 1.x. For me it looks like 1.x uses nested CSS transforms, which Chrome doesn't handle correctly. I guess this was introduced with the fractional zoom in LL. I'm afraid this can only be resolved by a complete rewrite of the tile-stitching using canvas, like OL does:

https://ptv-logistics.github.io/xserverjs/boilerplate/OpenLayers3.html

perliedman commented 5 years ago

There is already a plugin for tile stitching on canvas: https://github.com/Leaflet/Leaflet.TileLayer.NoGap (might or might not be updated to work with latest Leaflet, but it worked at some point).

oliverheilig commented 5 years ago

Now we have this "experience" also on Firefox (62.0.2) great! So currently the only flawless browsers are IE and edge!

image

meawoppl commented 5 years ago

Gross, has any progress been made on this, and/or is there a workaround that is the accepted approach that people are using?

oliverheilig commented 5 years ago

Looks like we all have to live with it. And also the new chromium-based Edge will inherit this issue. image

oijkn commented 5 years ago

From cmulders "hack" here is a good workaround to make the tiles 1 pixel larger, with the side effect that they overlap by 1 px. Besides that the tiles will be slightly enlarged and scaled (by 1px).

/* 
 * Workaround for 1px lines appearing in some browsers due to fractional transforms
 * and resulting anti-aliasing.
 * https://github.com/Leaflet/Leaflet/issues/3575
 */
(function(){
    var originalInitTile = L.GridLayer.prototype._initTile
    L.GridLayer.include({
        _initTile: function (tile) {
            originalInitTile.call(this, tile);

            var tileSize = this.getTileSize();

            tile.style.width = tileSize.x + 1 + 'px';
            tile.style.height = tileSize.y + 1 + 'px';
        }
    });
})()
shodge17 commented 4 years ago

Just want to say that Oijkn's function above works. I just copied and pasted it in my code and the white grid lines are gone. Thanks Oijkn!

ebrensi commented 4 years ago

The fix works for me too. Thanks @oijkn! I want to stay posted on this issue though, in case it gets fixed in a future release of Leaflet so I can get rid of that hack.

zdila commented 3 years ago

I can reproduce this issue on Debian Linux, XFCE, after upgrading to HDPI monitor (4k 32"). Reproducible in Chrome, not in FF. Page not scaled.

Sample: https://www.freemap.sk/?map=15/48.687986/20.446608&layers=Z

2020-11-06_14-54

Lines are stable when moving the map and changed its width when scaling the page.

brgrz commented 3 years ago

At the moment I only experience this issue on 4K displays with Chrome based browsers. FF seems fine.

Under same conditions (4K, Chromium browsers) other mapping solution do not seem to suffer from this issue: Google Maps, OL, Mapbox.

So I guess we should be expecting Leaflet to fix this?

Widdershin commented 3 years ago

Looks like there might be a bit more hope of getting this resolved in Chrome:

https://bugs.chromium.org/p/chromium/issues/detail?id=600120

Screen Shot 2021-03-26 at 2 28 37 PM
GeomaticaNet commented 2 years ago

Any solution?

dravnic commented 2 years ago

here is a workaround we did based on the idea of increasing tile size. this workaround increase tile size only during animations, so while map is at rest there are no visual glitches due to the minor tile overlap.

for 256px tiles:

.leaflet-pan-anim .leaflet-tile,
.leaflet-zoom-anim .leaflet-tile {
    width: 256.5px !important;
    height: 256.5px !important;
}

for 512px tiles:

.leaflet-pan-anim .leaflet-tile,
.leaflet-zoom-anim .leaflet-tile {
    width: 512.5px !important;
    height: 512.5px !important;
}

as tile size is set during layer initialization maybe a general solution would be to setup such css animation override per layer during its initialization?

Falke-Design commented 2 years ago

I close this because it is a duplicate of #3575.

@dravnic the animation workaround is a good idea, can you please post it in #3575 again.

moshanghuage commented 10 months ago

.leaflet-pan-anim .leaflet-tile, .leaflet-zoom-anim .leaflet-tile { width: 256.5px !important; height: 256.5px !important; }

This method actually increases the gap on the Edge browser