最近,项目中发现 safari 缩放模糊的问题,本文是收集了不同资料尽量将 safari 缩放模糊的原因发现,并且给出可能的解决方案。
关于 safari 的资料太少了,又由于 chrome 的 blink 内核是继承自 safari 的 webkit 的,并且 chrome 的内核是开源的,所以可以从 chrome 的开源社区中发现其中猫腻。
在这个 blink-dev 论坛(https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/Ufwrhx_iZ7U)中,我们可以发现在 2016 年的时候,Chrome 也是会因为 scale 而模糊的,下面是发生的原因:
Chrome 会在 scale 时尽量避免重新光栅化合成层的内容,这样可以提高性能。
非合成层的内容在动画的每一帧中总是重新光栅化,而合成层是特殊的,它是为了高性能和 GPU 的优势而设计的,所以是利用了启发式(启发式的意思是相对最优的方法)来进行重新光栅化的。
现在的启发式是当 cc:layer 被创建时按照当时的 scale 进行首次光栅化,如果 scale 变化了,那么它将以 scale 1 重新光栅。 当前的行为是为了使 scale 为 1 的情况看起来不错。
firefox 的内核和 edge 内核是在动画的每一帧按照真实的 scale 进行重新光栅化,而 safari 和 chrome 利用启发式方法进行光栅化的,所以模糊只会发生在 safari 和 chrome(旧版本的)。
如今的 Chrome 已经提供了will-change
来帮助开发者决定在性能和质量上进行抉择,开发者加上will-change: transform
可以选择性能而放弃质量接受模糊,具体可见 https://developers.google.com/web/updates/2016/09/re-rastering-composite。
而 safari 并没有给开发者选择,依旧是默认保证性能放弃质量,我们依然可以在 https://bugs.webkit.org/show_bug.cgi?id=27684 发现这个 bug 依旧没有得到解决,亦或者是没有给开发者权利选择是要性能还是质量。
上面这些解释中的某些名词可能会感觉生涩难懂,所以需要解释一下什么是合成层,什么是光栅化,什么是 c