css 2d旋转-探究CSS混合模式filter导致的CSS 3D失效问题

作者 | 乔可可

来源|

今天我正在编写一个小型 CSS 演示,一个关于 3d 球的旋转动画。 对于 CSS 3D,以下属性是不可或缺的:

{
    transform-style: preserve-3d;
    perspective1000;
    transformtranslate3d();
}

大家可以戳这里这个Demo,大致是这样的:CodePen Demo - 3D ball():

嗯,说到疗效,我想到了CSS混合模式mix-blend-mode,思考使用混合模式是否能让疗效更上一层楼,或者和其他一些火花碰撞。

mix-blend-mode:我们一般称之为混合模式。 使用混合模式混合多个视口可以获得新的效果。 mix-blend-mode描述了元素的内容应该与元素的父元素的内容一致,如何与元素的背景混合。

混合模式的一些用途可以在这里看到:难以置信的混合模式,

CSS 3D 与混合混合模式

然而,在对元素应用混合模式后,神奇的事情发生了,3D 效果消失了。

也就是在每个点的CSS元素代码中添加这样一句话:

{
    mix-blend-mode: lighten;
}

效果从 CSS 3D 更改为 2D。

这很奇怪css 2d旋转,预期的混合没有发生,取而代之的是3D的失败。 我认为这可能与内核有关。 上述疗效是在chrome 65.0.3325.181试验中得到的。

和浏览器内核有关系吗?

带着这样的疑问,我测试了其他几个内核:

Safari可以正常显示,但是我只能感觉应该和内核有关。 应该有很多人遇到过同样的问题。 带着这个问题,google了一下。

Explosive Stack Network 也有同事提出了类似的疑问:StackOverflow -- mix-blend-mode is bad by 3D conversions on page()

后来在chromium bug提交网站上,找到了15年的bug列表,我也想知道这个问题:

BUG - CSS mix-blend-mode 关闭 CSS 透视。()

最后,我在错误列表的底​​部找到了一个可能可靠的答案:

当我们有混合混合模式时,创建堆叠上下文的最近祖先将隔离混合。 我们在这个隔离组的根部创建一个渲染表面,因为渲染表面不支持preserve-3d(因为它们渲染到单独的FBO中),所以我们看到一个扁平化的结果。

ajuma@ 表示,如果我们能够以某种方式从图层中解开变换,那么在 Slimming Paint v2 之后,这个错误可能会更容易修复。

翻译一下,大致意思是:当我们使用CSS混合模式时,堆叠上下文会在使用混合模式的元素的根节点处重新创建一个独立的渲染平面,但不幸的是,这个渲染平面不支持preserve—— 3D(因为它们渲染到单独的 FBO 中),因此我们看到 2D 平面效果。

css绕中心旋转_css 2d旋转_旋转css

验证图层边界

上面这句话应该已经可以作为推论了。 我会使用chrome提供的工具来验证一下,打开开发者工具的Rendering -> Layer borders:

黄色代表CSS渲染时的GraphicsLayer层,蓝色网格代表图块(tile)。 你可以将它们视为层(而不是层)的单元,Chrome内核可以将它们作为大层GPU的一部分上传以进行渲染加速。

在普通3D模式下,启用图层边框效果:

在添加了 mix-blend-mode 的 3D 模式下,启用图层边框效果:

可以看到,在mix-blend-mode的3D模式下,整个球形元素外面确实多了一层红色瓷砖。 也就是上面提到的独立渲染平面,也就是因为这个渲染平面不支持preserve-3d,所以我们最终得到了一个2D平面图形。

旋转css_css绕中心旋转_css 2d旋转

过滤器也会导致 CSS 3D 失败

完成了吗? 不不不,这谁受得了啊。

那么如果是因为 mix-blend-mode 生成了额外的独立渲染平面导致 3D 失败,是否还有其他元素会导致相同的结果呢?

带着困惑,我删除了 mix-blend-mode,并向 3d 元素添加了一个过滤器:

{
-    mix-blend-mode: lighten;
+    filter: blur(1px);
}

果然,同样的问题出现了,3D失败:

综上所述

嗯。 那么应该可以初步推断,凡是渲染时需要独立生成渲染平面,并且包含preserve-3d属性的,都会导致内部CSS 3D失败。

暂时我发现有以下属性,会导致CSS 3D失败:

其他问题

这个错误有什么影响

一般来说,很少有人在使用 CSS 3D 时使用混合模式或滤镜。 这两个属性更多的是锦上添花的作用,所以大多数时候,不使用也不会有问题。 所以影响不是很大。

上述 FBO 是什么?

我不能 100% 确定上述确切的固定基地运营基地 (FBO)。 推测应该是一个Frame Buffer Object,帧缓冲对象,存在于内存中。 帧缓冲区是 OpenGL 使用的二维数组和存储区域的集合:颜色缓冲区、深度缓冲区、模板缓冲区和累积缓冲区。

各类3D场景在屏幕上渲染css 2d旋转,首先放置在一个FBO中,可以理解为用于加速渲染的离屏图像。

bug什么时候修复

在 chromium bugs 网站上,上述 bug 被合并到了 Issue 575099 中,最终状态为 Untriged,这意味着它还没有被分配优先级,意味着等待有人来决定谁应该声明并修复该特定 bug。 因此,短期内解决的可能性不大。