本文将从比较多的方面详细阐述如何利用 CSS 3D 的特性,实现各类有趣、酷炫的动画效果。认真读完,你将会收获到:
- 了解 CSS 3D 的各种用途
- 激发你新的灵感,感受动画之美
- 对于提升 CSS 动画制作水平会有所帮助
CSS 3D 基础知识
本文默认读者掌握一定的 CSS 3D 知识,能够绘制初步的 3D 动画效果。当然这里会再简单过一下 CSS 3D 的基础知识。
使用 transform-style 启用 3D 模式
要利用 CSS3 实现 3D 的效果,最主要的就是借助 transform-style 属性。transform-style 只有两个值可以选择:
// 语法: transform-style: flat|preserve-3d; transform-style: flat; // 默认,子元素将不保留其 3D 位置 transform-style: preserve-3d; // 子元素将保留其 3D 位置。
当我们指定一个容器的 transform-style 的属性值为 preserve-3d 时,容器的后代元素便会具有 3D 效果,这样说有点抽象,也就是当前父容器设置了 preserve-3d 值后,它的子元素就可以相对于父元素所在的平面,进行 3D 变形操作。
利用 perspective & perspective-origin 设置 3D视距,实现透视/景深效果
perspective 为一个元素设置三维透视的距离,仅作用于元素的后代,而不是其元素本身。
简单来说,当元素没有设置 perspective 时,也就是当 perspective:none/0 时所有后代元素被压缩在同一个二维平面上,不存在景深的效果。
而如果设置 perspective 后,将会看到三维的效果。
// 语法 perspective: number|none; // 语法 perspective-origin: x-axis y-axis; // x-axis : 定义该视图在 x 轴上的位置。默认值:50% // y-axis : 定义该视图在 y 轴上的位置。默认值:50%
而 perspective-origin 表示 3D 元素透视视角的基点位置,默认的透视视角中心在容器是 perspective 所在的元素,而不是他的后代元素的中点,也就是 perspective-origin: 50% 50%。
通过绘制 Webpack Logo 熟悉 CSS 3D
对于初次接触 CSS 3D 的同学而言,可以通过绘制正方体快速熟悉语法,了解规则。
而 Webpack 的 Logo,正是由 2 个 立方体组成:
以其中一个正方体而言,实现它其实非常容易:
- 一个正方体由 6 个面组成,所以首先设定一个父元素 div,然后这个 div 再包含 6 个子 div,同时,父元素设置 transform-style: preserve-3d;
- 6 个子元素,依次首先旋转不同角度,再通过 translateZ 位移正方体长度的一半距离即可
- 父元素可以通过 transform 和 perspective 调整视觉角度
以一个正方体为例子,简单的伪代码如下:
<ul class="cube-inner"> <li class="top"></li> <li class="bottom"></li> <li class="front"></li> <li class="back"></li> <li class="right"></li> <li class="left"></li> </ul>
.cube { width: 100px; height: 100px; transform-style: preserve-3d; transform-origin: 50px 50px; transform: rotateX(-33.5deg) rotateY(45deg); li { position: absolute; top: 0; left: 0; width: 100px; height: 100px; background: rgba(141, 214, 249); border: 1px solid #fff; } .top { transform: rotateX(90deg) translateZ(50px); } .bottom { transform: rotateX(-90deg) translateZ(50px); } .front { transform: translateZ(50px); } .back { transform: rotateX(-180deg) translateZ(50px); } .left { transform: rotateY(-90deg) translateZ(50px); } .right { transform: rotateY(90deg) translateZ(50px); } }
叠加两个,调整颜色和透明度,我们可以非常轻松的实现 Webpack 的 LOGO:
当然,这里的 LOGO 为了保证每条线条视觉上的一致性,其实是没有设置景深效果 perspective 的,我们可以尝试给顶层父容器添加一下如下代码,通过 transform 和 perspective 调整视觉角度,设置景深效果:
.father { transform-style: preserve-3d; perspective: 200px; transform: rotateX(10deg); }
就可以得到真正的 3D 效果,感受很不一样:
完整的代码,你可以戳这里:CodePen Demo -- Webpack LOGO
OK,热身完毕,接下来,让我们插上想象的翅膀,走进 CSS 3D 的世界。
实现文字的 3D 效果
首先,看看一些有意思的 CSS 3D 文字特效。
要实现文字的 3D 效果,看起来是立体的,通常的方式就是叠加多层。
下面有一些实现一个文字的 3D 效果的方式。
假设我们有如下结构:
<div class="g-container"> <p>Lorem ipsum</p> </div>
如果什么都不加,文字的展示可能是这样的:
我们可以通过叠加阴影多层,营造 3D 的感觉,主要是合理控制阴影的距离及颜色,核心 CSS 代码如下:
p { text-shadow: 4px 4px 0 rgba(0, 0, 0, .8), 8px 8px 0 rgba(0, 0, 0, .6), 12px 12px 0 rgba(0, 0, 0, .4), 16px 16px 0 rgba(0, 0, 0, .2), 20px 20px 0 rgba(0, 0, 0, .05); }
这样,就有了基础的 3D 视觉效果。
3D 氖灯文字效果
基于此,我们可以实现一些 3D 文字效果,来看一个 3D 氖灯文字效果,核心就是:
- 利用 text-shadow 叠加多层文字阴影
- 利用 animation 动态改变阴影颜色
<div class="container"> <p class="a">CSS 3D</p> <p class="b">NEON</p> <p class="a">EFFECT</p> </div>
核心 CSS 代码:
.container { transform: rotateX(25deg) rotateY(-25deg); } .a { color: #88e; text-shadow: 0 0 0.3em rgba(200, 200, 255, 0.3), 0.04em 0.04em 0 #112, 0.045em 0.045em 0 #88e, 0.09em 0.09em 0 #112, 0.095em 0.095em 0 #66c, 0.14em 0.14em 0 #112, 0.145em 0.145em 0 #44a; animation: pulsea 300ms ease infinite alternate; } .b { color: #f99; text-shadow: 0 0 0.3em rgba(255, 100, 200, 0.3), 0.04em 0.04em 0 #112, 0.045em 0.045em 0 #f99, 0.09em 0.09em 0 #112, 0.095em 0.095em 0 #b66, 0.14em 0.14em 0 #112, 0.145em 0.145em 0 #a44; animation: pulseb 300ms ease infinite alternate; } @keyframes pulsea { // ... 阴影颜色变化 } @keyframes pulseb { // ... 阴影颜色变化 }
可以得到如下效果:
完整的代码,你可以猛击这里 CSS 灵感 -- 使用阴影实现文字的 3D 氖灯效果
利用 CSS 3D 配合 translateZ 实现真正的文字 3D 效果
当然,上述第一种技巧其实没有运用 CSS 3D。下面我们使用 CSS 3D 配合 translateZ 再进一步。
假设有如下结构:
<div> <h1>Glowing 3D TEXT</h1> <h1>Glowing 3D TEXT</h1> <h1>Glowing 3D TEXT</h1> <h1>Glowing 3D TEXT</h1> <h1>Glowing 3D TEXT</h1> <h1>Glowing 3D TEXT</h1> <h1>Glowing 3D TEXT</h1> <h1>Glowing 3D TEXT</h1> <h1>Glowing 3D TEXT</h1> <h1>Glowing 3D TEXT</h1> </div>
我们通过给父元素 div 设置 transform-style: preserve-3d,给每个 <h1> 设定不同的 translateZ()来达到文字的 3D 效果:
div { transform-style: preserve-3d; } h1:nth-child(2) { transform: translateZ(5px); } h1:nth-child(3) { transform: translateZ(10px); } h1:nth-child(4) { transform: translateZ(15px); } h1:nth-child(5) { transform: translateZ(20px); } h1:nth-child(6) { transform: translateZ(25px); } h1:nth-child(7) { transform: translateZ(30px); } h1:nth-child(8) { transform: translateZ(35px); } h1:nth-child(9) { transform: translateZ(40px); } h1:nth-child(10) { transform: translateZ(45px); }
当然,辅助一些旋转,色彩变化,就可以得到更纯粹一些 3D 文字效果:
完整的代码,你可以猛击这里 CSS 灵感 -- 3D 光影变换文字效果
利用距离、角度及光影构建不一样的 3D 效果
还有一种很有意思的技巧,制作的过程需要比较多的调试。
合理的利用距离、角度及光影构建出不一样的 3D 效果。看看下面这个例子,只是简单是设置了三层字符,让它们在 Z 轴上相距一定的距离。
简单的伪代码如下:
<div> <span class='C'>C</span> <span class='S'>S</span> <span class='S'>S</span> <span></span> <span class='3'>3</span> <span class='D'>D</span> </div>
$bright : #AFA695; $gold : #867862; $dark : #746853; $duration : 10s; div { perspective: 2000px; transform-style: preserve-3d; animation: fade $duration infinite; } span { transform-style: preserve-3d; transform: rotateY(25deg); animation: rotate $duration infinite ease-in; &:after, &:before { content: attr(class); color: $gold; z-index: -1; animation: shadow $duration infinite; } &:after{ transform: translateZ(-16px); } &:before { transform: translateZ(-8px); } } @keyframes fade { // 透明度变化 } @keyframes rotate { // 字体旋转 } @keyframes shadow { // 字体颜色变化 }
简单捋一下,上述代码的核心就是:
- 父元素、子元素设置 transform-style: preserve-3d
- 用 span 元素的两个伪元素复制两个相同的字,利用 translateZ() 让它们在 Z 轴间隔一定距离
- 添加简单的旋转、透明度、字体颜色变化
可以得到这样一种类似电影开片的标题 3D 动画,其实只有 3 层元素,但是由于角度恰当,视觉上的衔接比较完美,看上去就非常的 3D。
为什么上面说需要合理的利用距离、角度及光影呢?
还是同一个动画效果,如果动画的初始旋转角度设置的稍微大一点,整个效果就会穿帮:
可以看到,在前几帧,能看出来简单的分层结构。又或者,简单调整一下 perspective,设置父容器的 perspective 由 2000px 改为 500px,穿帮效果更为明显:
也就是说,在恰当的距离,合适的角度,我们仅仅通过很少的元素,就能在视觉上形成比较不错的 3D 效果。
上述的完整代码,你可以猛击这里:CSS 灵感 -- 3D 文字出场动画