Leaflet: Webkit浏览器中分数缩放级别上的图块之间的空间

创建于 2015-06-30  ·  96评论  ·  资料来源: Leaflet/Leaflet

screen shot 2015-06-30 at 14 39 12

如屏幕截图所示,图块之间有一个很小的空间。 我在Safari,Chrome和Opera中的部分缩放级别上会发生这种情况。 似乎此问题已在#2377中修复,但后来在3ccbe5b中删除,以提高性能。

我尝试重新实施此修复程序以查看性能对我自己的影响,而且还很糟糕,甚至没有解决Chrome的问题。

有谁知道如何解决这个问题? 分数缩放级别对于我们的应用程序来说将是一个很棒的功能,但是只要这个错误仍然存​​在,我们就无法真正使用它们。

编辑:我设置了一个显示问题的jsFiddle: http :

bug in progress

最有用的评论

尤其是在较暗的地图或图像上(以我为例),这个问题非常明显。 我认为,浏览器中的抗锯齿会由于缩放期间的_fractional_变换而导致图块之间的间隔,如Ivan所述。

在找到更好的解决方案之前,我将使用此解决方法(或修改)使图块变大1像素,而副作用是它们重叠1 px。 除此之外,图块将被略微放大和缩放(按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';
        }
    });
})()

所有96条评论

不知道。 :(尽管我只在Safari中看到问题,但-Chrome / Opera正常运行。

有谁知道如何解决这个问题?

我有一个主意,但它与“激进”和“实验”一词相关联:

https://github.com/IvanSanchez/Leaflet.gl

我发现的一件事是纹理必须被夹紧。 即,如果删除此行: https :

到目前为止,瓦工三角形形成了一个完整的网格,该网格被渲染时没有裂痕……但是“实验性”一词目前将遍及整个网格。

@mourner在Safari中效果更强,但在Chrome中也可见。
screen shot 2015-06-30 at 15 42 07

@IvanSanchez哇,工作不错,但我认为我还不能使用它。

@Eschon是的,我可能没有注意到这一点,因为在Retina屏幕上,它甚至不可见。

在某些情况下,这似乎也影响了Firefox。
我无法在jsFiddle中复制它,但是如果您查看该站点
我在Firefox 39和41.0a2中获得了相同的空间

编辑:这似乎是iframe的问题。 如果我直接打开地图,则不会复制。

我怀疑1.0可能会在没有太多黑客的情况下实现。 推至待办事项列表的底部。

我们在最新的Chrome浏览器上也遇到相同的问题。 我希望您能找到可能的解决方法,因为这些行在OpenStreet地图上显示不佳。 谢谢。

尤其是在较暗的地图或图像上(以我为例),这个问题非常明显。 我认为,浏览器中的抗锯齿会由于缩放期间的_fractional_变换而导致图块之间的间隔,如Ivan所述。

在找到更好的解决方案之前,我将使用此解决方法(或修改)使图块变大1像素,而副作用是它们重叠1 px。 除此之外,图块将被略微放大和缩放(按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';
        }
    });
})()

@cmulders感谢您的解决方法!
由于我们主要有大部分白色和蓝色的滑雪胜地地图。 我们暂时忽略了空格,使用您的解决方法看起来要好得多。

用cartodb深色瓷砖制作jsbin,即使在视网膜屏幕上也可以看到线条:
http://jsbin.com/ratoli/5/edit?html,js ,输出

Safari / Chrome越野车,FF对我来说不错。

为此,我们应该制作一个无传单的Chrome错误报告,因此它将在以后的Chrome版本中修复。

@hyperknot我认为已经有一个Chrome错误报告,但是我现在找不到。

我正在使用leafletjs 1.0 beta ,有时也在osx El Capitan上的(最新:chrome,safari,firefox)上也看到此错误。 当我将图片的 transform css属性编辑1px时,编辑后的图块与其旁边的图块对齐。

// ex.
 transform: translate3d(1556px, -81px, 0px);
 // to
 transform: translate3d(1555px, -80px, 0px);

有时这个错误虽然没有出现(相差1px)! 不知道为什么:(但我目前猜测它与地图容器的样式有关。

编辑:假设图块在渲染时正确对齐,并且没有显示任何1px的差异,在地图移动事件中将看到一个间隙。 行为就像在瓦片周围闪烁1px边框。

我发现了一个CSS解决方法,可以在OS X El Capitan的Safari 9.1上解决我的问题:

.leaflet-tile-container img {
    box-shadow: 0 0 1px rgba(0, 0, 0, 0.05);
}

但是,我不能承担太多功劳,我从以下Stackoverflow答案中获得了答案,该答案还暗示_why_这有帮助: http ://stackoverflow.com/a/17822836/138103

使用box-shadow可以更直接地解决该问题:它扩展了box的重绘尺寸,从而迫使WebKit重绘多余的像素。 移动浏览器中盒阴影的已知性能影响与所使用的模糊半径直接相关,因此一个像素的阴影应几乎没有影响。

也许可以将其用作适当的修复方法,但是如果其他人首先尝试这样做可能会很好。 但是,它对我有用,并且似乎不会在其他浏览器中引起任何问题。

@href也许您可以使用该修复程序发出请求请求? 这样可以使测试更加容易。

@href @IvanSanchez您确定这不会影响渲染性能吗? 我认为我们应该介绍一下添加具有Alpha透明度的盒子阴影如何影响移动设备,例如,它可能对性能产生明显影响,甚至可能禁用硬件加速。

@IvanSanchez完成。

您确定这不会影响渲染性能吗? 我认为我们应该介绍一下如何添加具有Alpha透明度的盒子阴影如何影响移动设备,例如,它可能会对性能产生明显影响,甚至可能会禁用用于平移的硬件加速。

我完全不确定这会带来什么影响。 从Stackoverflow答案来看,这似乎没有效果,但这只是相信其他人对切线相关问题的看法。 如果更博学的人可以调查一下并介绍我的解决方法,那肯定是一个好主意。

当我在Google周围搜索时,我只是很幸运,我希望其他人知道。

@hyperknot @href我将在几周内愉快地针对我的一组测试浏览器执行一些基准测试。

@IvanSanchez @href此外,将这种hack限制为仅影响到的浏览器可能会很好,而不仅仅是全局应用。

@IvanSanchez是否有推荐的工作流程来分析Leaflet渲染性能?

同样,将这种黑客行为仅限制于受影响的浏览器可能会是一件好事,而不仅仅是在全球范围内应用。

我个人只在Safari中看到它,因此将其限制为野生动物园是有意义的。 有提到有人在Chrome中看到了这一点。 还有人在其他Webkit浏览器中仍然看到此错误吗?

仅在L.Map构造函数中为选定的浏览器添加CSS类到地图很简单。

@href问题存在于我的Chromium 49中

@hyperknot我不知道分析此类情况的最佳方法。 让我们谈论这个周末;-)

@href此外,此修复还使我的Chromium 49中的瓷砖弄乱了……它模糊了整个图像,而不仅仅是边缘。 原稿,带有.leaflet-container { background: black }

fractional-space

使用img.leaflet-tile.leaflet-tile-loaded { box-shadow: 0 0 1px rgba(0, 0, 0, 0.05); }

fractional-space1

:crying_cat_face:

那真是怪了。 在Chromium 49(OS X El Capitan)中,这个问题对我来说并不存在,盒子阴影似乎也没有任何影响。

制作了一个最新的游乐场: http :

我将向Webkit和Blink团队提交无Leaflet的错误。

好的,成功地制作了一个最小化无传单的示例来重现此问题:
http://playground-leaflet.rhcloud.com/say/1/edit?html ,输出

提交了Chromium错误报告: https

提交的Webkit错误: https ://bugs.webkit.org/show_bug.cgi?id

不含img版本: http

Chromium错误报告的一些更新,来自[email protected]

嘿,只是想给大家一个快速更新。 我正在这个问题上积极工作。

问题是由于我们在元素的本地空间中对事物进行栅格化。 如果元素具有分数平移,则光栅化的纹理将使用线性重采样进行分数平移粘贴到屏幕上,从而导致模糊。

解决方案是在与我们的物理屏幕像素对齐的空间中光栅化事物。 即,将分数平移应用于矢量图形命令而不是栅格纹理。

该修复程序将分为两个部分:

  1. 第一部分允许我们的栅格系统使用任何常规矩阵进行栅格化。 这部分差不多完成了。 我有一个WIP,但它仍然存在一个导致性能下降的错误。 我希望在几天内完成。
    https://codereview.chromium.org/2075873002/
  2. 第二部分使我们的切片管理能够管理不同栅格转换附带的一组纹理。 我本来打算使用通用矩阵,但结果是瓦片覆盖范围的计算变得非常困难。 相反,我将做一个仅支持翻译和缩放的简单版本。 我估计这需要再工作一周。

我将尝试通过M53分支降落,但时间紧迫。 可以肯定的是,可以通过M54进行修复。

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

给错误报告者:

您上传的测试用例在Chromium中触发了一个边缘情况,我们以另一种方式处理像素捕捉。 如果您向图块添加一些内容,则背景中将不再出现接缝。 我们可以轻松地修复边缘情况,但是,图块内容中仍然存在接缝。

这是一个难题,唯一已知的完美解决方案是使用FSAA,由于CPU /内存成本,没有浏览器可以做到这一点。 每个供应商都开发自己的试探法,以使某些内容看起来更好,但代价是某些内容看起来不正确。

例如: http :

镀铬以正确的几何形状进行绘制,但是边缘会像卡住的猪一样流血。
Firefox将第一个框绘制为49x49,第二个框绘制为49x50。
Edge将第一个框绘制为50x50,第二个框绘制为50x49。 两者都带有别名。

同样,如果向容器添加旋转,则所有实现都会使边缘出血。

我建议的解决方法是在磁贴之间添加一些重叠。 您知道,就像用A4纸制作海报一样。 这个想法是确保在所有缩放后,每个图块都会覆盖至少一个像素,因此,保证每个物理像素至少被一个不透明像素覆盖。 重叠的宽度取决于您要支持的最小比例。 例如,如果要缩小到1/4尺寸,则添加4个重叠像素。

以下是针对其他想要解决此问题的开发人员的详细分析。

报告者上传的repro并不是很好的repro,因为它会触发cc中的优化代码路径。 当我们检测到完全纯色的图层时,将其绘制为SolidColorLayerImpl,它没有内容缩放的概念。 这是简化的复制品: http :

黑盒将以大小为(100,100)的SolidColorLayerImpl进行绘制,这将生成大小为(100,100)的单个纯色四边形,通过绘制变换将其投影到屏幕上,使其变为(99.5,99.5)。 使用抗锯齿功能时,最右边的像素列和最下面一行的像素将以半透明方式绘制。

另一方面,如果我们在图层中添加一些内容以欺骗cc使其认为该图层不是纯色,那么问题出在两种情况下:

  1. 最后一块是纯色,例如: http :

内容大小将被四舍五入,因此尽管缩放后的图层大小仅为(600,300)* 0.995 =(597,298.5),但将被过度绘制为(597,299)。

  1. 列表图块为非单色,例如: http :

内容大小将四舍五入。 同样,实际缩放的内容仅覆盖(600,300)* 0.995 =(597,298.5),生成的四边形将覆盖(597,299)。 由于抗锯齿,像素的最后一行应该是半透明的,但实际上我们用图层背景色填充了该背景色,这是创建图层的元素的背景色。

背景中将没有接缝,但是,当内容物覆盖背景时,背景会在边缘渗出。 例如: http :

使用非纯色图块的另一个测试用例:
http://playground-leaflet.rhcloud.com/giqo/edit?output

@hyperknot很棒的更新,但是这两个引号似乎彼此矛盾(其中一个人说他正在修复,而下一个人说不可能修复)。 那么,我们是等待修复还是只是接受它将永远这样?

@mourner对不起,我没有提供完整的内容,您当然是正确的。 因此,原始错误报告为:
https://bugs.chromium.org/p/chromium/issues/detail?id=600120

在某一点上,它已合并为另一问题:
https://bugs.chromium.org/p/chromium/issues/detail?id=521364

在另一个问题中,我们得到了最初的长答复并提供了解决方案。 我问他是否可以检查Leaflet案是否确实由他的工作解决,他回答:

抱歉,传单问题实际上是另一个问题。 我将重新打开问题600120,并分享我的分析。

因此,现在重新打开了Leaflet bug,我们在Leaflet bug 1中得到了第二个答复。 顺便说一句,现在的最新更新是:

我看了看移动Google地图,看看他们是如何处理的。 事实证明,他们也同样受此问题困扰,但是他们做了一些UI技巧,使其不那么明显。

首先,他们使用视口标签禁止浏览器缩小缩放,并在JS中实现缩小缩放。 在收缩缩放期间,您仍然可以看到图块之间的接缝(在高分辨率显示器上非常细微)。 缩放手势完成后,他们会将比例因子捕捉到最接近的图块集。 因此,除了缩放手势外,基本上,图块始终以原始分辨率显示。

老实说,我们还没有一个可靠的计划。 我将在星期一与其他油漆工讨论。

顺便说一句,似乎移动Google Maps(我猜是一个网站)正在使用与我们完全相同的技术。

@mourner @IvanSanchez某些核心问题以及使用will-change的可能解决方案:
https://bugs.chromium.org/p/chromium/issues/detail?id=600120#c15

当前的分层重要吗? 我看到每个图块都被强制进入自己的图层(translate3d),并且这些图层分别按一定的分数值进行缩放。

只要我们独立缩放每个地图图块(使用图层或通过drawImageRect +分数CTM),对于分数比例值,我们将获得未像素对齐的边缘。 这会触发ole重叠边缘抗锯齿问题,其中离散的AA会导致背景颜色渗色。

我认为这可行的方式是使用非分数比例(例如1.0)对地图进行栅格化,然后进行原子缩小:

1)避免单独的图块分层(使用“ transform:translate()”代替“ transform:translate3d()”)
2)强制容器(整个地图)分层(在容器上使用“ transform:scale3d()”)
3)以比例== 1.0强制容器层栅格化

进行这些更改后,应以1.0的比例对地图拼贴图像进行栅格化(=>边缘已像素对齐=>没有接缝痕迹),然后应按原子方式缩小整个地图图层的比例。

不幸的是,#3并非微不足道,我能想到的唯一hack是

  • 从scale(1)开始并会改变:transform(有关详细信息,请参见https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/Ufwrhx_iZ7U)
  • 第一次通过栅格后将图层比例重置为所需值

例如http://jsbin.com/yaqeru/10/embed?output

chrishtr / danakj我是否正确理解了图层栅格比例缩放语义,并且有更好的方法将图层栅格化比例锁定为特定值吗?

你能帮忙回答吗?

我知道正在进行修复(感谢大家继续努力!),但是与此同时... @cmulders的monkeypatch最适合我。 这是一个将Leaflet作为npm模块引入,使用ES6并确保没有双重修补的版本,以防万一有人在寻找一些复制粘贴的优点。

https://gist.github.com/ericsoco/5712076f69f9068b11d41262b9e93666

import leaflet from 'leaflet';
// ...
patchMapTileGapBug();
// ...
function patchMapTileGapBug () {

    // Workaround for 1px lines appearing in some browsers due to fractional transforms
    // and resulting anti-aliasing. adapted from <strong i="9">@cmulders</strong>' solution:
    // https://github.com/Leaflet/Leaflet/issues/3575#issuecomment-150544739
    let originalInitTile = leaflet.GridLayer.prototype._initTile;
    if (originalInitTile.isPatched) return;

    leaflet.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';
        }
    });

    leaflet.GridLayer.prototype._initTile.isPatched = true;

}

我很高兴人们正在对此进行调查。 万一对所有人来说都是不太理想的解决方法:如果您愿意牺牲惯性,则在地图init上设置intertia:false消除差距,并且可能会减少zoomAnimation:false

我想我为此找到了一个(过于复杂的)解决方案,我将其放在https://github.com/Leaflet/Leaflet.TileLayer.NoGap-欢迎发表评论,因为我不确定性能在旧计算机/电话上的东西。

抄送@Eschon @hyperknot

顺便说一句,在高DPI(2560x1140)屏幕上使用Chrome时,无需使用传单小数缩放或浏览器缩放,该错误也会发生。

这么晚才回复很抱歉。

我刚刚测试了您的解决方案。 该演示版对我来说效果很好,因此我尝试将修复程序添加到我的应用程序中。 由于我仍在使用旧的1.0-dev版本的Leaflet,因此我从http://leafletjs.com/download.html将其更新为1.0.0-rc3。

我注意到的第一件事是,有似乎是一个错误在这里。 它显示了一个映射未定义的错误,因此我将其更改为this._map

之后,它可以工作,但是在我的工作计算机上确实很慢。 尤其是在Chrome浏览器中,但Firefox也运行缓慢。

令人惊讶的是,它对我测试的手机没有太大影响。
Android上的Firefox似乎与以前相同,Chrome的速度稍慢,但还算不错。
iOS上的Safari似乎也和以前一样。

我注意到的另一件奇怪的事情是,在移动版Chrome和Safari上,捏缩放似乎可以固定到固定水平

@Eschon感谢您对此进行测试!

我总是犯错输入map而不是this._map :-(

之后,它可以工作,但是在我的工作计算机上确实很慢。 尤其是在Chrome浏览器中,但Firefox也运行缓慢。

您可以在那台计算机上运行一些探查器吗? 很高兴知道减速是否与画布操作有关。 我注意到IE9-IE11的性能受到一些影响。

根据此解决方案是否会使地图在某些平台上变慢,使其完全可选并默认关闭是有意义的。 这里的一些反馈很重要!

我还没有真正研究过OL3人员如何解决此问题,也没有研究过在启用画布合成之前他们是否在浏览器上进行了一些性能检测。 可能值得一看。

我注意到的另一件奇怪的事情是,在移动版Chrome和Safari上,捏缩放似乎可以固定到固定水平

我敢打赌,这只是摆弄zoomDeltazoomSnap选项,与这个错误无关。

您可以在那台计算机上运行一些探查器吗? 很高兴知道减速是否与画布操作有关。 我注意到IE9-IE11的性能受到一些影响。

我是否应该仅使用Chrome开发工具记录JavaScript CPU配置文件? 我在性能测试方面没有太多经验,所以我真的不知道该如何显示数据。

是的,就是这样。 然后在火焰图上查找较宽的东西。

我只是做了一个带有修复程序的配置文件,而另一个没有它。 我尝试对两个配置文件执行相同的操作。

我注意到的第一件事是,带有修复程序的版本还有一个额外的“峰值”(不知道这是否是正确的词),这是由_onZoomTransitionEnd

在没有修复的版本中, _onZoomTransitionEnd花了1.8毫秒,我什至没有在图表中看到它。 在具有此修复程序的版本中,它花费了6毫秒的时间,并导致活动达到“峰值”。

在这两个配置文件中,其他两个“峰值”看起来非常相似,只是看起来有些不同,但是在修复版本中,它们之间的差距更大。

希望对您有所帮助。 我还保存了两个配置文件,因此如果您需要它们,可以将它们上传到某个地方。

作为暂时的变通方法,我只是在原始函数中添加了0.002的比例因子,该函数将每个平铺的平移属性设置为translate3d,从而几乎完全消除了差距。 “ .002”是我的测试用例中最小的比例因子,它使间隙完全消失。 我没有发现任何副作用。

在最新的Chrome,Firefox和IE 11中进行了测试。在40英寸4k显示器上进行了测试,并且窗口缩放比例设置为150%,并且浏览器中具有各种缩放值。

这个错误有什么进展吗? @AlexanderUhl您的解决方案是否会在放置图像时引起图像修改,还是仅在移动/缩放时受到影响?

似乎添加了will-change CSS属性来解决此问题,只需要检查FF性能警告,就可以在这里进行描述: https :

@themre :scale属性在添加后适用于所有图像图块,并且是永久的。 样式属性将如下所示:
style="width: 256px; height: 256px; transform: translate3d(545px, 745px, 0px) scale(1.002); opacity: 1;"

但这会导致图像拉伸过长,这是不想要的效果。 我尝试了1.0.3版本,该版本具有will-change CSS属性,但仍然会导致空白。 会尝试看起来更多。

Ofc扩展了img,那就是方法;-)我同意这种解决方法不是理想的,但是通常这是解决方法的本质,不是吗? 但是,这种方法对我来说效果最好,副作用可以忽略不计(对于我的用例来说,这是一个映射应用程序,其中包含来自mapbox,此处,osm等的图块)

好吧,如果我们使用普通的translate ,问题就解决了。 真的不知道translate3d CSS属性是否比普通的translate快得多,也许最好添加此标志作为选项。我想我要用translate替换translate3d。

查看实际情况:
translatemap

image
面对相同的问题,最新版本(1.0.3)。

可能会在1.1中修复

2017年3月8日,星期三10:13,Gaurav [email protected]写道:

[image:图片]
https://cloud.githubusercontent.com/assets/13112509/23697357/7dcc4cf6-040d-11e7-881a-df3a44254015.png
面对相同的问题,最新版本(1.0.3)。

-
您收到此邮件是因为有人提到您。
直接回复此电子邮件,在GitHub上查看
https://github.com/Leaflet/Leaflet/issues/3575#issuecomment-284987808
或使线程静音
https://github.com/notifications/unsubscribe-auth/AAeKj_23QbtFCaXeFjGRJcU-jg0284xBks5rjnEvgaJpZM4FO8Jh

如果将用于转换.leaflet-pane.leaflet-map-pane div的nx和ny的值四舍五入为整数,则在Safari上可以解决行/间隙问题。 我看不到任何有害的副作用(供我暂时使用)。

找到这个:
translate3d("+n.x+"px,"+n.y+"px,0)")
并替换为:
translate3d("+Math.round(n.x)+"px,"+Math.round(n.y)+"px,0)")

@LudwigBogner ,一旦您进行了一些缩放(例如,设置浏览器缩放,或在缩放动画期间),它可能仍然会失败。 参见上面链接的以下示例,其中的翻译本身经过了四舍五入: http :

刚被这一点。 对我来说,它似乎在Chromium或FireFox上并不存在。 Safari上的部分缩放比例。

进展?

此问题在Chrome和Firefox(Mac)上仍然存在。 我使用的是zoomDelta和zoomSnap为0.25。

奇怪的是,设置.leaflet-tile { will-change: auto !important; } (或“未设置”)可解决Firefox中的问题(仅适用)。 仍在寻找Chrome的解决方法。

提出的其他其他一些禁用惯性和更改translate3d代码以添加舍入的修补程序也都无效。

@jawinn我认为通过将L_DISABLE_3Dtrue可能会成功,IIRC与更改will-change具有相同的效果,即在渲染地图。 请注意,它可能会给您带来缩放动画,平移等更差的性能。

所有这些对浏览器实现细节都很敏感,因此,花一点时间就可以了,因为我研究了很长时间。

@jawinn
我使用的解决方法是上述@cmulders的解决方法

/* 
 * 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';
        }
    });
})()

它不是完美的,但据我所知它不会影响性能

多谢你们。 @Eschon可行。 Chrome或Firefox中不再出现空白。

对于那些打算使用“ 1px修复程序”的用户,请准备好使您的图像变得模糊且有点破损:

对于我来说,花了数小时来渲染和照相原始图像,这是不可接受的。 所以我不得不使用L_DISABLE_3D = true并忍受闪烁的动画和最后的跳跃缩放。

更多信息:我使用leaflet-rastercoords插件,我的地图设置如下:

    map = L.map('map', {
        center: [3250, 1700],
        zoom: 5,
        minZoom: 2,
        maxZoom: 6,
        maxBoundsViscosity: 1,
    });

问:Leaflet的下一个最佳替代方法是什么,它没有这种“图块之间的空间”错误?

我将自己使用Google,但也许有人已经走了这条路。

@ n3tman您是否也尝试过NoGap插件? 可能值得一试。

@perliedman感谢您提及这一点。
不幸的是,无法使其在本地运行。.在_initContainer函数中出现Cannot read property 'appendChild' of undefined错误。
尝试使用传单的早期版本(最高1.0.2)-结果相同。 该演示在Chrome / Firefox中显示了相同的错误。
也许我缺少明显的东西,可以请您帮忙吗?

同样的1px间距。

Chrome版本66.0.3359.139(64位)
Windows 10(1709)
传单1.3.1

最初打开此问题时,我发现它与小数缩放级别有关,但这可能不再是唯一的原因。

我最近开始了一个使用GoogleMutant插件的项目,当我将缩放级别设置为整数并稍微平移一点时,我也发现这种情况也会发生。

它似乎与#6069和#6240固定的(种类)有关,尽管在缩放和平移时仍会出现间隙。

我还从其他项目中删除了解决方法,它似乎也在那里发生,因此它不是特定于GoogleMutant插件的

受到@cmulders 1px解决方法的启发...它可以工作,但是在某些图像上出现的模糊效果不好。 我改用下面的方法(虽然我还没有做很多测试...),但似乎可以解决这些问题,并且仍可以使用非小数缩放级别保持清晰的图像。 额外的0.5px似乎足以弥补这些空白(Linux上的Chrome和Firefox以及Android 1上的Chrome尝试过Leaflet 1.3.4)

(function(){
    var originalInitTile = L.GridLayer.prototype._initTile
    L.GridLayer.include({
        _initTile: function (tile) {
            originalInitTile.call(this, tile);

            var tileSize = this.getTileSize();
            var map = this._map;
            var isFix = function() {
                return !(parseFloat(tile.style.width) % 0 === 0);
            };
            var fixOn = function() {
                if(!isFix()) return;
                tile.style.width = tileSize.x + 0.5 + 'px';
                tile.style.height = tileSize.y + 0.5 + 'px';
            };
            var fixOff = function() {
                if(isFix()) return;
                tile.style.width = tileSize.x + 'px';
                tile.style.height = tileSize.y + 'px';
            };
            var checkFix = function(){
                var zoom = map.getZoom();
                if(zoom % 1 === 0) {
                    fixOff();
                }
                else {
                    fixOn();
                }                
            };
            map.on('zoomstart',fixOn);
            map.on('zoomend',checkFix);
            checkFix();
        }
    });
})()

screen shot 2018-09-28 at 3 56 33 pm
3年多以后,此错误仍未在Chrome中解决! 我在Firefox或Safari中看不到效果。 谢谢@cmulders的工作!

此处相同(Windows 7 Enterprise SP1)。 在Firefox中到处都是行,在Chrome中是完整的行网格,但在IE11中是行。 @cmulders修复程序可在Firefox和Chrome中使用。

以下是更多测试的完整结果:

  • Windows 7企业版SP1

    • IE11:好的

    • Chrome,Firefox:不正常

  • Windows 10

    • IE11,Edge,Firefox:确定

    • Chrome:不行

  • 苹果系统

    • Safari,Chrome,Firefox:确定

  • Linux:

    • Chrome,Firefox:确定

  • Android:

    • Chrome,Firefox:确定

    • 使用WebView的应用程序:确定

进一步的测试表明,这显然是一个非常低级的问题,与Leaflet无关。
在Windows 7 Enterprise SP1上进行的测试最初是在两台不同的PC上进行的,但都具有NVIDIA图形。

当在具有AMD Radeon显卡的Windows 7 Enterprise SP1上进行相同的测试时,一切正常,Chrome或Firefox上的图块之间没有任何线条!

正如之前提到的NoGap一样,我只是想让您知道我采用了原始代码并对其进行了修改,以使其能够与当前的传单版本(即传单^ 1.3.3)一起使用:
https://github.com/Endebert/squadmc/blob/master/src/assets/Leaflet_extensions/NoGapTileLayer.js

然后可以像常规的TileLayer一样使用它: https :

它使用的是es6功能,因此您可能需要进行一些修改才能使其正常工作。

正如之前提到的NoGap一样,我只是想让您知道我采用了原始代码并对其进行了修改,以使其能够与当前的传单版本(即传单^ 1.3.3)一起使用:
https://github.com/Endebert/squadmc/blob/master/src/assets/Leaflet_extensions/NoGapTileLayer.js

然后可以像常规的TileLayer一样使用它: https :

它使用的是es6功能,因此您可能需要进行一些修改才能使其正常工作。

@Endebert您设法让NoGap工作了吗? 前段时间我遇到了与
Cannot read property 'appendChild' of undefined _initContainer函数中的Cannot read property 'appendChild' of undefined错误。

我在您的版本中发现的唯一变化是将try ... catch到通话level.ctx.drawImage(imageSource, offset.x, offset.y, tileSize.x, tileSize.y);
并没有帮助。

@TomazicM是的,我的应用程序SquadMC中正在使用我的实现。 在台式机上可能并不那么明显,但是在移动设备上,显然启用了不捕捉的部分缩放。

关于实现:原始版本使用TileLayer.include() ,而我使用TileLayer.extend() 。 我相信那是重要的区别。 如前所述,这是一个新类,旨在代替TileLayer使用。

好吧,这是我经过2个小时的调查得出的结果。 问题是由translate3d内的像素小数引起的。

<div class="leaflet-pane leaflet-map-pane" style="transform: translate3d(-10.7773px, -8.41406px, 0px);"></div>

这就是为什么它可以与L_DISABLE_3D = true一起很好地工作的原因,因为根据源代码的这一translate3d

只是不允许小数点像素。 例如,可以通过以下方式实现此目的:

```js
var pos = (offset && offset.round()) || new Point(0, 0);
```

  • 或通过许多其他解决方案...

好吧,这是我经过2个小时的调查得出的结果。 问题是由translate3d内的像素小数引起的。

我想今天是2019年,使用translate3d强制现代浏览器使用GPU已经过时了。 干得

@mdorda嗨! 听起来很有趣,但是请注意,此线程之前已讨论过四舍五入: https :

不知道从那以后是否有重要的改变会有所作为,但是直到我们进行了彻底的测试后,我才寄希望于我。

解决此问题的第一步是提交PR,以便我们进行测试。

对于那些使用Angular 2+的人来说,我已经用这种方法解决了。 它适用于我的简单用例,不知道其他含义...

const tileLayer = new TileLayer(this.tileLayerUrlTemplate, this.tileLayerOptions);
tileLayer.on('load', () => {
    for (const tile of Array.from(document.getElementsByClassName('leaflet-tile'))) {
        (<HTMLElement>tile).style.height = (tile.clientHeight + 1) + 'px';
        (<HTMLElement>tile).style.width = (tile.clientWidth + 1) + 'px';
    }
});
this.map.addLayer(tileLayer);

我在带有Mozilla Firefox 69.0.1(64位)的Windows 10 Pro 1903上的LeafletJS 1.5.1版中看到了部分缩放的像素间隙。
像素间隙
我认为,像素间隙的原因可能不是在translate3d()CSS函数中,而是在scale()中。
image
如我所见,在1.5.1版中,translate3d()参数仅是整数。


最好的问候,IMMSPgisgroup

您找到此错误的任何解决方案了吗?

此刻我遇到了同样的问题,但没有找到解决方案。

error

我正在使用:

  • Windows 10家庭版1803
  • Google ChromeVersión77.0.3865.90(正式版)(64位)
  • 传单1.5.1

当我使用Firefox时,没有出现白线

no_error

@ Arenivar93

不,我已经对此关注了几年了。 他们尝试了许多变通办法,但在没有重大妥协的情况下,没有任何措施可以纠正它。 问题的根源在铬的上游: https :

铬团队的最新信息是,在不破坏其他事情的情况下很难做到这一点,因此我们可能会坚持一段时间。

尤其是在较暗的地图或图像上(以我为例),这个问题非常明显。 我认为,浏览器中的抗锯齿会由于缩放期间的_fractional_变换而导致图块之间的间隔,如Ivan所述。

在找到更好的解决方案之前,我将使用此解决方法(或修改)使图块变大1像素,而副作用是它们重叠1 px。 除此之外,图块将被略微放大和缩放(按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';
        }
    });
})()

我们在这个解决方案上运气很好。 它并不完美,但比我们认为的线条要好。

除此之外,我们确保地图的背景颜色与底图的颜色更加一致。 例如,如果海洋是深蓝色,我们将使用它,以便将瓷砖覆盖在该颜色上,从而最大程度地减少一些明显的不一致性。

还是不完美,但有帮助

@colbyfayock请问您在哪里以及如何实施您的解决方案?

我正在构建一个React应用程序,因此可能有所不同,但是我创建了一个包含以下内容的文件:

// Fix via https://github.com/Leaflet/Leaflet/issues/3575#issuecomment-150544739
import L from 'leaflet';

(function () {
  if (!L || !L.GridLayer || !L.GridLayer.prototype) return;

  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';
    }
  });
})();

返回顶部是因为它会预编译并且并不总是可用(此处不重要)

然后我只是在导入传单后将其导入

import L from 'leaflet';
...
import '../plugins/leaflet-tilelayer-subpixel-fix';

我的解决方法是在不对源代码进行更改的情况下舍入转换值。
与react一起使用,但是可以被任何前端使用,因为它是JQuery
不告诉它是最好的选择,只是做到这一点。
这解决了问题,并且我还没有观察到任何明显的模糊或某种缺陷。 值得一试。

    this.leftMap.on('move', () => {
      const mapDiv = window.document.getElementsByClassName("leaflet-pane leaflet-map-pane")
      let styleString = mapDiv.getAttribute("style");
      const transformValue = styleString.substring(styleString.indexOf("(")+1,styleString.indexOf("px,"));
      const roundedTransformValue = Math.round(parseFloat(transformValue));
      styleString = styleString.replace(transformValue,roundedTransformValue);
      mapDiv.setAttribute("style",styleString);
    });

@colbyfayock-它似乎没有为我解决。 :(

我正在使用带有变焦捕捉0的react传单。

image

该解决方案对我们而言从来都不是完美的,但我们绝对没有像我们这样的一致路线。 我不确定zoomSnap功能,因此必须查找它,我不确定从我如何阅读说明中, 0如何与该属性一起使用。 您是否尝试过删除该行以查看是否没有这些行仍然存在?

https://leafletjs.com/examples/zoom-levels/#fractional -zoom

编辑:在示例gif之后继续阅读

zoomSnap可以设置为零。 这意味着Leaflet将不会捕捉缩放级别。

我猜你正在进入分数状态,该解决方案无法处理超出完整的整数默认快照but‍♂️但不确定

传单1.7-dev,问题仍然存在。 在Windows 7和Windows 10中的Firefox和Chrome中,图块边界处的线。在IE11和旧(非Crome)Edge中没有问题,在基于Chrome的新Edge中也存在相同问题。

有两个可行的解决方案,但我不喜欢其中任何一个。 一种是通过<script>L_DISABLE_3D = true;</script>禁用3d,但这意味着失去动画操作。 其他方法是将图块HTML元素扩展1个像素,但这意味着您会得到稍微模糊的图块。

我找到了一个非常原始的解决方案,但是从本质上来说,它是100%有效的。 也许有人觉得它有用。

解决方法是在两个不同的地图窗格上显示相同的有问题的平铺图层两次,一个放置在另一个下方,并且偏移为[-1,-1]。

代码看起来像这样:

<style>
  .originOffset {
    transform: translate(-1px, -1px);
  }
</style>

<script>
  var pane1 = map.createPane('pane1');
  var pane2 = map.createPane('pane2');

  pane1.style.zIndex = 210;
  pane2.style.zIndex = 220;

  L.DomUtil.addClass(pane1, 'originOffset');

  var layer1 = L.tileLayer( ... , {
    pane: 'pane1',
    ...
  });
  var layer2 = L.tileLayer( ... , {
    pane: 'pane2,
    ...
  });
  var layer = L.layerGroup([layer1, layer2]);
</script>

来自@cmulders的建议,我有这些广告行,并且

map.on('zoomend drag',function(){
$('#map> div.leaflet-pane.leaflet-map-pane> div.leaflet-pane.leaflet-tile-pane> div> div> img')。each(function(){
如果(String($(this).css(“ width”))。includes('。5')=== false){
var imgW = String($(this).css(“ width”))。split(“ px”).join(“ .5”)
var imgH = String($(this).css(“ height”))。split(“ px”).join(“ .5”)
$(this).css(“ width”,imgW);
$(this).css(“ height”,imgH);
}
});

我与@mdorda在一起,当在leaflet-map-pane调用translate3d()时平移和缩放结果的整数时,而不是像素的分数时,问题消失了一切再次变得美丽。 我不要求了解何时需要保留分数的所有细微差别,但如果它为Leaflet减轻了浏览器问题的困扰,那么在某些地板上放置L.Draggable._onMove是可以接受的

    offset.x = Math.floor(offset.x / this._parentScale.x);
    offset.y = Math.floor(offset.y / this._parentScale.y);

甚至L.DomUtils.setTransform

    pos.x = Math.floor(pos.x);
    pos.y = Math.floor(pos.y);

这样就不会为分数提供任何翻译,但这可能很浪费,因为平铺图片不会产生分数翻译(对吗?)。

我浪费了两个小时,才发现浏览器设置被放大了,而不是实际大小
只是将缩放恢复到实际,并且都像魅力一样工作,这就是我的情况

我浪费了两个小时,才发现浏览器设置被放大了,而不是实际大小
只是将缩放恢复到实际,并且都像魅力一样工作,这就是我的情况

@tokenflow :本主题实际上是关于“ Webkit浏览器中分数缩放级别上的图块之间的空间”。 我确实想在这里不要自大,但您是否真的认为您关于缩放到100%的信息对任何人都有用呢?

我在Firefox和Chromium的Linux版本上都遇到了此错误。
问题(至少对于Firefox)似乎是主要.leaflet-tile-container $$$的scale() .leaflet-tile-container ,我可以通过document.querySelector('.leaflet-tile-container:last-of-type').getAttribute('style')
例如您有scale(0.707107) ,但是所有img子元素的宽度/高度均为256。因此,您需要计算: 0.707107 * 256px = 181.019392px ,这是一个十进制数字。 然后,当您舍入像素并将其作为比例时,它似乎可以在Firefox / Linux中运行: 181px / 256px = 0.70703125

我编写了一个有助于调试的函数:

function getCurrentScale (doFix = false) {
    const tileContainer = document.querySelector('.leaflet-tile-container:last-of-type');

    if (!tileContainer) {
        return;
    }

    const tileStyle = tileContainer.getAttribute('style');
    const scaleRegEx = /scale\(([0-9\.]+)\)/i;
    const matches = scaleRegEx.exec(tileStyle);

    if (!matches || matches.length !== 2) {
        return;
    }

    const scale = parseFloat(matches[1]);

    const mod = (scale * 256) % 1;

    if (mod) {
        console.log('scale is off by px:', mod);
        if (doFix) {
            const newScale = Math.round(scale * 256) / 256;
            console.log('old scale / new scale', scale, newScale);
            const newStyle = tileStyle.replace(scaleRegEx, `scale(${newScale})`);
            tileContainer.setAttribute('style', newStyle);
        }
    } else {
        console.log('scale seems to be fine:', scale);
    }
}

如果使用true作为第一个参数调用它,它将尝试固定比例。 但是,这仅对我适用于Firefox。

我发现一个愚蠢的修复程序确实不起作用。

.leaflet-tile-container img {
    width: 256.5px !important;
    height: 256.5px !important;
}

这会导致瓷砖周围产生巨大的震缝,但我完全看不到它们,并且固定了瓷砖之间的空间。

@ ChrisLowe-Takor似乎确实可以正常工作,尽管乍一看我并不能真正说出原因。
这可能比我现在正在使用的JavaScript解决方法更可取,但是我将不得不对其进行更多研究并进行一些测试。

@ ChrisLowe-Takor-哇,它也对我有用! 好发现👍

@ ChrisLowe-Takor似乎也可以使用Leaflet包在R中为我工作。 非常感谢!

@ ChrisLowe-Takor不知何故,此技巧确实可用于所有愚蠢的现代浏览器(对于旧的古老IE11,则不需要)! 只需记住一件事:如果将选项detectRetina用于图块图层,并且显示是视网膜显示,则图块大小将为125 x 125 px。

但是,此解决方案与所有基于tile容器扩展的解决方案具有相同的缺点:tile有点模糊。

@ ChrisLowe-Takor我尝试过。 如果maxZoom大于maxNativeZoom,则磁贴将无法正确显示。

此页面是否有帮助?
0 / 5 - 0 等级