CSS 3D动画,如何实现?

12

我想要在三维空间中制作动画效果。我知道这可以通过CSS和HTML5实现,但我找不到一个好的、实用的教程!

我发现这个网站是一个例子。你可以选择文本等。一直处于活动状态。 请问有人能够给出一个非常简单易懂的小例子来说明如何实现吗?我看到了源代码,但我并不真正理解它...

这是CSS3还是HTML5,还是两者都包括?

需要多少JavaScript编程知识?

哪些浏览器支持此功能?


1
如果你想的话,可以看一下WebGL。它是JavaScript编写的,链接为http://www.ibiblio.org/e-notes/webgl/webgl.htm。 - C0D3
1
这个问题过于宽泛。你应该将问题限制在某个具体的方面。例如:如何在HTML5中制作旋转立方体动画? - nico
2个回答

86

这有两个部分。

  1. 第一部分是关于构建3D形状的。
  2. 第二部分涉及动画化它(这是简单的部分)。

2019年8月更新

这是一个非常老的答案,我将保留原始内容,只删除不再有效的链接。

但自从我写了这篇文章以来,我的编码能力和浏览器已经进步了,所以如果你想以更高效的方式构建CSS立方体,请查看我在此主题上撰写的文章:

使用自定义属性简化CSS立方体


我会详细介绍每一部分,但首先简要回答您最后问的三个问题。

这是CSS3还是HTML5还是两者兼而有之?

这是CSS3。CSS 3D变换关键帧动画

需要多少JavaScript?

好吧,如果您不想使用JavaScript创建3D形状本身,则不需要任何JavaScript来对其进行动画处理。任何支持3D变换的浏览器也支持关键帧动画,并且,如果浏览器支持关键帧动画,则可能要使用这些动画而不是jQuery(甚至是您自己的自定义JS)动画。

哪些浏览器支持此功能?

两年前情况不太好,但现在正在改善...

✓ Chrome, Safari, Firefox(虽然Firefox的3D动画抖动且对我的CPU不友好...我确实有一台6年旧的笔记本电脑,这是真的),Opera 15+ (WebKit) 支持3D变换。当然还有关键帧动画。

Firefox支持所有无前缀的内容,Chrome/Safari/Opera需要使用-webkit-前缀 - 更新: Chrome 36+ 和 Opera 23+同样支持无前缀的内容,所以现在只有Safari还需要加前缀。我在答案或演示中不会使用任何前缀(-prefix-free会处理这些)。另一个更新: Safari 9去掉了transforms的前缀。

在转换为WebKit之前,Opera不支持3D transforms。

✗ IE 9及以下版本不支持3D transforms。IE10IE11支持3D transforms,但是不支持3D transformed元素的嵌套(不能通过在父级和子级元素上应用3D transforms来创建逼真的3D形状,因为被3D transformed的子元素会被压平到父元素的平面上)。更新: Edge现在支持3D transformed元素的嵌套。


好的,希望这能解决一些问题。现在...

1 构建CSS立方体。

1.2 什么是立方体以及从HTML开始

首先,尝试想象一个立方体。也许这个链接有帮助?或者我们也可以在这里放一张图片。

cube

它有6个正方形面。1个顶面,1个底面;1个前面,1个后面;1个左面,1个右面。这意味着HTML只需简单地写成:

<ul class='cube'>
    <li class='face'></li>
    <li class='face'></li>
    <li class='face'></li>
    <li class='face'></li>
    <li class='face'></li>
    <li class='face'></li>
</ul>

首先你需要让这些面具有一定的规律性,使它们具有相等的宽度和高度,并将它们绝对定位,使它们全部垂直叠放在一起,为它们分配不同的背景颜色(它们并不介意),你可以给它们一些边距,加入一些虚拟文本或其他内容...

接下来是有趣的部分:将它们移动以形成一个空间立方体。您可以使用3D变换来实现。

1.2 坐标系

考虑这个三维坐标系:

3D coordinate system

最初,6个面都恰好位于您看到蓝色正方形的位置,在xOy平面上(其中O是3个轴的交点)。

注意y轴的方向。作为数学背景,这对我来说一开始有点奇怪,但这就是屏幕的坐标系。

在2D中,原点O位于左上角,所以x轴+(正方向)指向右,而y轴+指向下。

1.2.a 沿轴的平移

因此,x轴正值的平移(例如translateX(10px))会将应用于其上的元素向右移动(朝向x轴+),而负值的x轴平移(例如translateX(-10px))则向左移动。

同样地,y轴正值的平移(例如translateY(10px))会将元素向下移动(朝向y轴+),而负值的y轴平移(例如translateY(-10px))则向上移动。

现在再添加另一个维度,即z轴z轴+(正方向)是从屏幕外面指向您的方向。因此,沿着z轴正值的平移(例如translateZ(10px))会将元素向前移动(朝向z轴和您的方向的+),而沿着z轴负值的平移(例如translateZ(-10px))则向后移动(远离您)。

1.2.b 绕轴旋转

正角度值的旋转(例如rotate(15deg) - 注意如果没有指定旋转轴,则默认为z轴)在CSS中是顺时针方向的,负角度值的旋转(如rotate(-15deg))是逆时针方向的。

顺时针意味着从您旋转元素的轴的+方向看去是顺时针旋转的。

因此,围绕x轴的正旋转意味着从x轴+方向看,它在yOz平面中顺时针旋转,x轴位于右侧。

围绕y轴的正旋转意味着从y轴+方向看,它在zOx平面(水平平面)中顺时针旋转,y轴位于底部。

围绕z轴的正旋转意味着从z轴+方向看,它在xOy平面(屏幕平面)中顺时针旋转,这是您自然看到屏幕的方式。

1.3 将面放在正确的位置以形成立方体

1.3.1 将一个面放在前面

这意味着将其沿z轴正方向向前移动。这是什么?是正值的translateZ。要使用多少值?嗯,它应该是宽度的一半(或高度,不要紧,它们相等)。

假设我有width: 16em;

那么在这种情况下,您需要将面向前(沿着正z轴)移动16em/2 = 8em。在CSS中,它是:

.face:nth-child(1) { transform: translateZ(8em); }

注意: translate 变换会移动整个被变换元素的坐标系(因此,后续变换的 transform-origin 也随之移动)。

1.3.2 将第二个面放在背面

这很简单,对吧?只需要沿着 z 轴 反方向平移同样的距离就好了。如下所示:.face:nth-child(2) { transform: translateZ(-8em); }。是这样吗?

嗯...实际上,只有当你不想在该面上放置任何内容时,或者当你不想将一个有左右区分的背景图像作为其背景时,才是这样。

每个构成立方体的正方形都有一个正面和一个反面。正面朝向 z 轴 的正方向;即从电脑屏幕“看向你”的一面。如果在正面放置文本,它将正常流动。但是在背面上,看起来会垂直镜像。

这就是为什么你首先应该做的事情是将第二个正方形绕垂直轴(y 轴)旋转 180°。这样做后,你可以将这个第二个正方形沿着 z 轴 平移以将其移动到背面。

在这种情况下,平移值再次为正。就像 translate 变换会移动被变换元素的坐标系一样,rotate 变换则可以旋转它。这意味着,在应用了 rotateY(180deg) 后,z 轴+指向背面(而不是前面)。

因此,将第二个面旋转并平移到立方体上正确位置的 CSS 是:

.face:nth-child(2) { transform: rotateY(180deg) translateZ(8em); }

注意:方块是一个非常简单的3D形状,但我觉得一个非常有用的CSS属性来检查我是否正确旋转了面部是backface-visibility。如果我设置它为hidden并且我看不到旋转的元素,那么这意味着我正在从后面观察它。

1.3.3 将第三个面放在右侧

首先,它的正面必须“朝向”右侧。这意味着它必须围绕y轴旋转,以使z轴+指向右侧,然后必须沿着正的z轴移动相同的正值(在这种情况下为8em),这是正方形边长的一半。

旋转多少度?嗯,90°,这意味着所需的CSS是:

.face:nth-child(3) { transform: rotateY(90deg) translateZ(8em); }

1.3.4 将第四个面放置在左侧

首先将它以90°旋转,但是反方向,使其正面“看向”左侧。 “反方向”意味着使用rotateY(-90deg),然后应用相同的旧的translateZ(8em)。一行CSS代码实现:

.face:nth-child(4) { transform: rotateY(-90deg) translateZ(8em); }

1.3.5 将第五面放在顶部

先绕着x轴旋转90°,然后沿着z轴平移(旋转后指向上方)。CSS:

.face:nth-child(5) { transform: rotateX(90deg) translateZ(8em); }

1.3.6 将第六(也是最后一个!)面放在顶部

将它沿着x轴反方向旋转90°,然后沿着z轴平移(在旋转后指向下方)。CSS:

.face:nth-child(6) { transform: rotateX(-90deg) translateZ(8em); }

1.4 透视和真实的3D形状

立方体的各个面现在已经就位。但是,如果更接近你的面看起来比更远的面大,它就不会像一个3D形状那样看起来。处理这个问题的CSS属性叫做 perspective ,并应用于对它们进行了3D变换的元素的父级。

如果你垂直于前面的中心观察,它仍然不会像一个3D形状。因为你看不到其他的面。解决这个问题,需要将立方体本身在3D空间中旋转。这就是为什么浏览器允许嵌套3D变换元素的重要性。

使用transform-style: preserve-3d;启用3D变换元素的嵌套(在此示例中为.cube的父元素)。不幸的是,IE10/11不支持preserve-3d值的transform-style属性(只支持flat值),因此你不能在IE中拥有一个逼真的立方体(除非你将应用在立方体上的3D变换链接在每个面变换之前,这意味着如果你想将整个立方体作为一个整体进行动画,则需要为每个面设置一组关键帧)。

更新:transform-style:preserve-3d现在也可以在IE中使用了。

注意:如果你还在.cube上应用了3D变换,则应该将perspective属性移到.cube的父级上。

2 CSS立方体的动画

这只是使用.cube元素的常规关键帧动画完成的。假设你想将其旋转:

@keyframes ani { to { transform: rotate3d(5, 12, 13, 360deg); } }

您可以拥有多个关键帧,旋转围绕不同的轴,但这是基本思想。


这是一些很棒的工作。我对其中的数学部分很感兴趣。不过在你的博客上没有找到相关内容;) - Christoph
1
抱歉,我不明白你的意思。我以为答案中已经包含了数学部分,而且没有博客。 - Ana
@AndreMeinhold 为什么不将被接受的答案更改为这个更有帮助的答案呢? - Vadim Ovchinnikov
@Ana,你能否更新一下链接?它们无法使用。 - theonelucas

3

这全部是由CSS3和JavaScript实现的。只需在您喜爱的检查器中检查该网站,深入DOM,您将看到类似于以下内容:

-webkit-perspective: none;
-webkit-perspective-origin: 200px 200px;
-webkit-transform: matrix3d(-0.9386958080415784, -0.197569680458564, 0.2825179663820851, 0, 0, 0.8194947008605812, 0.5730867606754029, 0, -0.34474654452969944, 0.537954139890128, -0.7692562404101148, 0, 0, 0, 0, 1);
-webkit-transform-style: preserve-3d;
-webkit-transition-delay: 0s;
-webkit-transition-duration: 16s;
-webkit-transition-property: all;
-webkit-transition-timing-function: linear;

您需要多少JavaScript取决于您想如何实现它。 它可以是“很多”或“很少”。

浏览器越现代,运行得越好。 在这里查看哪些浏览器支持什么。


我在我的示例中复制了它,如何自动移动它? - Andre Meinhold
“所有浏览器的最新版本都应支持变换。” — 我认为这不适用于3D变换,请参见http://caniuse.com/#search=3d。 - Paul D. Waite

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接