【问题标题】:Opacity change during a transition flickers in SafariSafari 中过渡期间的不透明度变化闪烁
【发布时间】:2014-08-19 09:04:25
【问题描述】:

我有一个带有 opacity 转换的复合 div(它有 translate3d):

#bad {
    background-color: red;
    -webkit-transition: opacity .5s linear;
    -webkit-transform: translate3d(0, 0, 0);
}

如果我在转换过程中更改其opacity,它将在 Safari 中闪烁。
闪烁大约每三秒发生一次,类似于白色闪光。

Chrome 没有这个问题。

Scroll up and down in this fiddle to see what I mean.

问题似乎并不局限于不透明度——在其过渡过程中更改 -webkit-transform 会产生类似的效果:元素有时会呈现在过渡的最终状态之一。

如果我删除 -webkit-transform,问题就会消失,但不幸的是,现在这不是一个选项。
我可以通过其他方式在 Safari 中解决此问题吗?

【问题讨论】:

标签: safari webkit css-transitions flicker translate3d


【解决方案1】:

这似乎是 CoreAnimation 中的一个错误。
Kevin Doughty blogged about it 并提供 a simple fiddle to reproduce it

我不确定,但我相信它是由核心动画错误 rdar://problem/12081774 也就是非动画内容的闪烁引起的。

[...]

我相信 Safari 过渡闪烁与我提交的错误直接相关。解决方法是使用kCAFillModeBackwardskCAFillModeBoth 的核心动画fillMode。动画计时似乎有问题,其中属性值更改和动画在同一事务中在该属性上开始实际上并没有同时开始。向后填充通过扩展延迟开始动画的效果以在其实际开始时间之前应用来解决此问题。

Kevin 也将此报告为 #115278 in WebKit 并尝试解决此问题,但据我了解,他没有继续处理此问题,补丁未被接受。

当然这不是一个真正的答案(不能解决问题),但至少它解释了问题。

【讨论】:

    【解决方案2】:

    问题是更改属性值和添加动画需要同时发生。

    在用 C++ 重写 Core Animation 时,引入了 OSX 10.5 中不存在的竞争条件。当我对附加动画的实验产生相同的闪烁时,我了解到了这一点。我发现解决方法是 Core Animation 的 kCAFillModeBackwards。我还发现相同的解决方法对 CSS 过渡很有效,方法是破解我自己的 WebKit 分支,重点是破解部分。但是猜想对 WebKit 开发者没有帮助,我不想再惹恼他们。我确实认为问题在于核心动画,而不是 WebKit。我猜他们应该在任何给定的 CATransaction 中使用从对 CACurrentMediaTime 的单个调用派生的相同 CFTimeInterval。

    与过渡不同,CSS 动画确实允许填充模式。重现转换行为可能很困难,但这是一种选择。特别是,挑战将用新的动画替换中断的动画,从前一个中断的地方开始。换句话说,从 0 到 1 或 1 到 0 的不透明度动画很容易,但是如果用户想要在当前动画进度为 0.577564 时开始,会发生什么?这可能需要手动修改@keyframes 样式规则,这不是一件容易的事。

    然后是适当的动画填充模式的问题。通常你不想使用前向填充动画来执行布局,你会使用 CSS 属性本身。但在这种情况下,不设置底层值可能很简单,而是仅使用前向填充 CSS 动画,该动画被替换但在完成时从不删除。另一种方法是通过 element.style 设置底层值,同时添加一个向后填充的 CSS 动画。

    当然,如果 WebKit 不使用 Core Animation,闪烁也不会发生。到目前为止,在您的情况下防止闪烁的最简单方法是不启用硬件加速。

    代替:

    -webkit-transform: translate3d(100px, 100px, 0);
    

    尝试:

    -webkit-transform: translate(100px, 100px);
    

    http://jsfiddle.net/z6ejt/9/

    【讨论】:

    • 我花了两天时间才意识到同样的事情(使用香草translate)!感谢您的精彩文章。
    【解决方案3】:

    就我而言,我发现 3 个操作解决了同样的问题:

    我需要在 ready 事件中淡入图像,尝试使用 jQuery 动画,但图像在 OSX Safari 上闪烁。

    通过以下操作解决:

    1) 分析 CSS 并删除应用在图像上的所有过渡规则,它们似乎与动画命令冲突。

    我有这个规则

    img {
    /*DON'T COPY !!!*/
    -webkit-transition:all 0.2s ease-in-out;
    -moz-transition:all 0.2s ease-in-out;
    -ms-transition:all 0.2s ease-in-out;
    -o-transition:all 0.2s ease-in-out;
    transition:all 0.2s ease-in-out;
    /*DON'T COPY !!!*/
    }
    

    我删了。

    2) 将此 CSS 规则添加到您需要淡入的元素中:

    display: none;/*initial state modified by the fadeIn function*/
    -webkit-backface-visibility: hidden;
    -webkit-perspective: 1000;
    -webkit-font-smoothing: antialiased;
    -webkit-transform-style: preserve-3d;
    -webkit-transform: translateZ(0); 
    

    3) 使用 jQuery 函数“fadeIn”,不要使用命令“.animate({opacity: 1} ecc..”。

    这些操作解决了 OSX Safari 上的闪烁问题。

    【讨论】:

    • 仅供参考,现在是 2021 年,这个答案解决了仅在 Safari 中进行 CSS 不透明度转换时出现的问题(而不是通过 javascript)。在我的情况下,不透明度过渡会导致父元素在过渡开始时向上移动 1 个像素,然后在过渡结束时回到原来的位置。 -webkit-transform: translateZ(0); 解决了。
    • 我很高兴它仍然有帮助!
    【解决方案4】:

    以下 CSS 修复了 safari 上的过渡闪烁

    * {
    -webkit-backface-visibility: hidden;
    }
    

    【讨论】:

      猜你喜欢
      • 2012-08-31
      • 1970-01-01
      • 2011-11-26
      • 1970-01-01
      • 1970-01-01
      • 2014-04-09
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      相关资源
      最近更新 更多