谁能解释一下这段代码为什么在别的浏览器能工作但在 Safari 下不能工作吗?太离奇了

2022-02-04 10:46:32 +08:00
 weijar

测试地址:

https://www.oxyry.com/test/img.html

点 Move 后,图片在动画移动中消失了!动画完成后才出来。

这个在别的浏览器没问题,在我的 iPhone 13 Safari 中图片会消失。

虽然 Safari 成吨的 Bug,但这个奇怪在于大部分移动图片操作不消失,但移动到有些位置会消失,想不通为什么。

我的 App 中很多这类移动,最近有点崩溃因为想不到绕过这个 Bug 的方法,你们碰到过吗怎么解决的?

文件源码:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

<style>
  body { margin: 0; }
  a[href], button { padding: 0.5em; font-size: xx-large; }
  #root { width: 320px; height: 300px; overflow: hidden; }
  #pic {
    transform: translateX(-1000px) scale(2.5);
    transform-origin: left top;
  }
</style>

<button id=btnMove>Move</button>

<div id="root">
  <img id=pic src="https://s3.ifanr.com/wp-content/uploads/2022/01/ms_070621_item1_AI_BehavioralHealth.jpg">
</div>

<script>
btnMove.onclick = () => {
  pic.style.transition = 'transform 1000ms'
  pic.style.transform = `translateX(-1100px) scale(2.5)`
}
</script>
5959 次点击
所在节点    Web Dev
26 条回复
BigDogWang
2022-02-04 11:03:13 +08:00
Safari 15.3 测试正常
BigDogWang
2022-02-04 11:03:56 +08:00
手机上确实有问题
Mutoo
2022-02-04 11:24:51 +08:00
没有细纠,应该是插值的 BUG 。
如果项目中这类移动多的话,可以考虑使用 matrix

transform: translateX(-1000px) scale(2.5)
等价于
transform: matrix(2.5, 0, 0, 2.5, -1000, 0)

亲测,这方法在 iOS 可行。

ref: https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix()
Biwood
2022-02-04 11:29:26 +08:00
iOS 上的 CSS 动画是有点与众不同,我在 iPhone 测试了一下,Chrome 和 Safari 都没有动画,图片直接消失然后重现。猜测是不是应该把 transition 属性放到 css 里面提前设置。
weijar
2022-02-04 11:32:20 +08:00
@Mutoo 非常感谢!测试下改成 matrix 真的没问题了
weijar
2022-02-04 11:34:34 +08:00
@Biwood iPhone 上任何浏览器都是强制和 safari 共用同一内核,所以还是 safari 的问题。我没在 android 上试过,别的浏览器内核应该是没有这类问题的,这个写法应该是没问题的。
learningman
2022-02-04 11:35:42 +08:00
@Biwood #4 iOS 上的 Chrome 叫 CriOS ,内核并不是 chromium ,只是接入了谷歌的生态
maplerecall
2022-02-04 12:00:31 +08:00
也可以试着添加 translateZ(0)或者 will-change

Safari 尤其是移动端的的渲染问题非常多,overflow 加 transform 更是重灾区,现在代码里很多 hack 都是为 Safari 写的,不愧为当代 IE
weijar
2022-02-04 12:20:39 +08:00
@maplerecall 的确 bug 很多。之前在圆角框里的元素 transform 动画直接把圆角破坏了,要加 will-change 才能护住圆角。但在这里之前试过似乎 will-change 没用。
EIJAM
2022-02-04 12:39:13 +08:00
不兼容很正常吧。谷歌为了推自家 Chrome ,还时不时地给 Firefox 下个绊子,定制一个 Firefox 专属 bug 。
EIJAM
2022-02-04 12:41:19 +08:00
maplerecall
2022-02-04 13:42:26 +08:00
@EIJAM 这可不是不兼容或者被下拌子,而是对标准实现有问题,简单的说就是 bug ,和 Chrome 与 Firefox 没有任何关系。
Mutoo
2022-02-04 14:23:14 +08:00
@Mutoo 稍微测试了一下,不是插值的问题。我试了一些边界条件,发现是 Safari iOS 做了不恰当的优化。假定 scale 为 1 ,当图片的 translate 发生在屏幕外的时候,safari 不渲染这个 translation ,但它没考虑到 scale 的情况。

测试了几个边界条件:
translateX(-600px) scale(1) 到 translateX(-700px) scale(1) 有动画
translateX(-600px) scale(2.5) 到 translateX(-700px) scale(2.5) 有动画
translateX(-700px) scale(1) 到 translateX(-800px) scale(1) 无动画
translateX(-700px) scale(2.5) 到 translateX(-800px) scale(2.5) 无动画
jinliming2
2022-02-04 14:32:28 +08:00
经过测试,应该确定确实是 iOS Safari 的 bug ,应该是 safari 在做优化的时候,只考虑了 translate 而忘记考虑 scale 的影响了,具体现象:
你同时为图片增加了 translateX 和 scale ,图片原本宽度为 620px ,它发现你 translateX(-1000px) 之后,图片应该已经在可见范围之外了,并且动画运动到 translateX(-1100px) 全程都应该在可见范围之外,所以直接将动画“优化”掉不执行了,反正效果就是元素在原来的位置消失,在动画结束之后再在新位置显示出来,那就直接不计算动画了,直接“跳刀 blink”即可。
但是它没料到实际上你同时为图片增加了 scale(2.5),把图片放大了,此时图片宽度变成了 1550px ,动画全程都在可见范围之内了,导致这个“优化”露馅了。

按照这个理论,你将动画改为从 translateX(620px) 变化到 translateX(621px) 就会触发 bug ,但是只要某一个值小于 620px (图片原始宽度),bug 就不会复现。

@Mutoo #3 给出的用 matrix 的解决方案,应该是绕过了这个 bug ,将 translateX 和 scale 的结果融合进同一个矩阵,Safari 就会考虑完整的变换结果之后再进行动画的优化。

应该可以给 webkit 提 issue 了。
EIJAM
2022-02-04 14:47:42 +08:00
@maplerecall 引用:“它们最近在 YouTube 视频网站上添加了一个隐藏的空 div 参数,导致我们无法启用 fast-path 硬件加速”
weijar
2022-02-04 14:48:30 +08:00
@Mutoo @jinliming2 感谢二位让我过个好年

我之前是一点都没想到原因。特别是我的图片查看器在手指拖来拖去时图片很跟手不会消失,手指一松图片就不见,简直见鬼,因为拖动时虽也是一样的 translate 参数但没用 transition 所以就不触发 bug
EIJAM
2022-02-04 14:50:57 +08:00
makelove
2022-02-04 14:53:15 +08:00
@EIJAM 不要像个精神股东一样强行洗地,这不是一回事。开放 Web 不符合苹果利益对自家内核不上心甚至不让别人用自研内核符合自私的人性,这是垄断之恶
EIJAM
2022-02-04 14:59:55 +08:00
@makelove 不是精神股东啊,就是股东,这两年还赚了不少呢。谷歌的股票也买了点,但我讨厌的浏览器还是 chrome ,以开放之名行垄断之实。
rabbbit
2022-02-04 15:01:38 +08:00
这种 bug 挺多的, 例如有时候给 safari 添加了 overflow-scrolling 之后有些子元素直接没了.简直无语.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/831846

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX