> 本文最初发表于[博客园](),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 > 以下是正文。 ## 前言 本文主要内容: - 过渡:transition - 2D 转换 transform - 3D 转换 transform - 动画:animation ## 过渡:transition `transition`的中文含义是**过渡**。过渡是CSS3中具有颠覆性的一个特征,可以实现元素**不同状态间的平滑过渡**(补间动画),经常用来制作动画效果。 - 补间动画:自动完成从起始状态到终止状态的的过渡。不用管中间的状态。 - 帧动画:通过一帧一帧的画面按照固定顺序和速度播放。如电影胶片。 参考链接:[补间动画基础](http://mux.alimama.com/posts/1009) transition 包括以下属性: - `transition-property: all;` 如果希望所有的属性都发生过渡,就使用all。 - `transition-duration: 1s;` 过渡的持续时间。 - `transition-timing-function: linear;` 运动曲线。属性值可以是: - `linear` 线性 - `ease` 减速 - `ease-in` 加速 - `ease-out` 减速 - `ease-in-out` 先加速后减速 - `transition-delay: 1s;` 过渡延迟。多长时间后再执行这个过渡动画。 上面的四个属性也可以写成**综合属性**: ```javascript transition: 让哪些属性进行过度 过渡的持续时间 运动曲线 延迟时间; transition: all 3s linear 0s; ``` 其中,`transition-property`这个属性是尤其需要注意的,不同的属性值有不同的现象。我们来示范一下。 如果设置 `transition-property: width`,意思是只让盒子的宽度在变化时进行过渡。效果如下: ![](http://img.smyhvae.com/20180208_1440.gif) 如果设置 `transition-property: all`,意思是让盒子的所有属性(包括宽度、背景色等)在变化时都进行过渡。效果如下: ![](http://img.smyhvae.com/20180208_1445.gif) ### 案例:小米商品详情 代码: ```html CSS 过渡
``` 效果如下: ![](http://img.smyhvae.com/20180208_1500.gif) 动画效果录制的比较差,但真实体验还是可以的。 工程文件: - [2018-02-08-小米商品详情过渡](http://download.csdn.net/download/smyhvae/10245871) ## 2D 转换 **转换**是 CSS3 中具有颠覆性的一个特征,可以实现元素的**位移、旋转、变形、缩放**,甚至支持矩阵方式。 转换再配合过渡和动画,可以取代大量早期只能靠 Flash 才可以实现的效果。 在 CSS3 当中,通过 `transform` 转换来实现 2D 转换或者 3D 转换。 - 2D转换包括:缩放、移动、旋转。 我们依次来讲解。 ### 1、缩放:`scale` 格式: ```javascript transform: scale(x, y); transform: scale(2, 0.5); ``` 参数解释: x:表示水平方向的缩放倍数。y:表示垂直方向的缩放倍数。如果只写一个值就是等比例缩放。 取值:大于1表示放大,小于1表示缩小。不能为百分比。 格式举例: ```html
1
2
3
``` 效果: ![](http://img.smyhvae.com/20180208_1551.gif) 上图可以看到,给 box1 设置 2D 转换,并不会把兄弟元素挤走。 ### 2、位移:translate 格式: ```javascript transform: translate(水平位移, 垂直位移); transform: translate(-50%, -50%); ``` 参数解释: - 参数为百分比,相对于自身移动。 - 正值:向右和向下。 负值:向左和向上。如果只写一个值,则表示水平移动。 格式举例: ```html
1
2
3
``` 效果: ![](http://img.smyhvae.com/20180208_1600.gif) 上图中,因为我在操作的时候,鼠标悬停后,立即进行了略微的移动,所以产生了两次动画。正确的效果应该是下面这样的: ![](http://img.smyhvae.com/20180208_1605.gif) **应用:**让绝对定位中的盒子在父亲里居中 我们知道,如果想让一个**标准流中的盒子在父亲里居中**(水平方向看),可以将其设置`margin: 0 auto`属性。 可如果盒子是绝对定位的,此时已经脱标了,如果还想让其居中(位于父亲的正中间),可以这样做: ``` div { width: 600px; height: 60px; position: absolute; 绝对定位的盒子 left: 50%; 首先,让左边线居中 top: 0; margin-left: -300px; 然后,向左移动宽度(600px)的一半 } ``` 如上方代码所示,我们先让这个宽度为600px的盒子,左边线居中,然后向左移动宽度(600px)的一半,就达到效果了。 ![](http://img.smyhvae.com/20180116_1356.png) 现在,我们还可以利用偏移 translate 来做,这也是比较推荐的写法: ```javascript div { width: 600px; height: 60px; background-color: red; position: absolute; 绝对定位的盒子 left: 50%; 首先,让左边线居中 top: 0; transform: translate(-50%); 然后,利用translate,往左走自己宽度的一半【推荐写法】 } ``` ### 3、旋转:rotate 格式: ```javascript transform: rotate(角度); transform: rotate(45deg); ``` 参数解释:正值 顺时针;负值:逆时针。 举例: ```html
1
``` 效果: ![](http://img.smyhvae.com/20180208_1630.gif) 注意,上方代码中,我们给盒子设置了 transform 中的 rotate 旋转,但同时还要给盒子设置 transition 过渡。如果没有这行过渡的代码,旋转会直接一步到位,效果如下:(不是我们期望的效果) ![](http://img.smyhvae.com/20180208_1635.gif) **案例1:**小火箭 ```html ``` 上方代码中,我们将 transform 的两个小属性合并起来写了。 小火箭图片的url: **案例2:**扑克牌 rotate 旋转时,默认是以盒子的正中心为坐标原点的。如果想**改变旋转的坐标原点**,可以用`transform-origin`属性。格式如下: ```javascript transform-origin: 水平坐标 垂直坐标; transform-origin: 50px 50px; transform-origin: center bottom; //旋转时,以盒子底部的中心为坐标原点 ``` 我们来看一下 rotate 结合 transform-origin 的用法举例。 代码如下: ```html
``` 效果如下: ![](http://img.smyhvae.com/20180208_1650.gif) ### 4、倾斜 暂略。 ## 3D 转换 ### 1、旋转:rotateX、rotateY、rotateZ **3D坐标系(左手坐标系)** ![](http://img.smyhvae.com/20180208_2010.png) 如上图所示,伸出左手,让拇指和食指成“L”形,大拇指向右,食指向上,中指指向前方。拇指、食指和中指分别代表X、Y、Z轴的正方向,这样我们就建立了一个左手坐标系。 浏览器的这个平面,是X轴、Y轴;垂直于浏览器的平面,是Z轴。 **旋转的方向:(左手法则)** 左手握住旋转轴,竖起拇指指向旋转轴的**正方向**,正向就是**其余手指卷曲的方向**。 从上面这句话,我们也能看出:所有的3d旋转,对着正方向去看,都是顺时针旋转。 **格式:** ```javascript transform: rotateX(360deg); //绕 X 轴旋转360度 transform: rotateY(360deg); //绕 Y 轴旋转360度 transform: rotateZ(360deg); //绕 Z 轴旋转360度 ``` **格式举例:** (1)rotateX 举例: ```html
``` 效果: ![](http://img.smyhvae.com/20180208_2025.gif) 上方代码中,我们最好加个透视的属性,方能看到3D的效果;没有这个属性的话,图片旋转的时候,像是压瘪了一样。 而且,透视的是要加给图片的父元素 div,方能生效。我们在后面会讲解透视属性。 (2)rotateY 举例: ```html
``` 效果: ![](http://img.smyhvae.com/20180208_2030.gif) (3)rotateZ 举例: ```html
``` 效果: ![](http://img.smyhvae.com/20180208_2035.gif) **案例:**百度钱包 现在有下面这张图片素材: ![](http://img.smyhvae.com/20180208_2055.png) 要求做成下面这种效果: ![](http://img.smyhvae.com/20180208_2100.gif) 上面这张图片素材其实用的是精灵图。实现的代码如下: ```html
``` ### 2、移动:translateX、translateY、translateZ **格式:** ```javascript transform: translateX(100px); //沿着 X 轴移动 transform: translateY(360px); //沿着 Y 轴移动 transform: translateZ(360px); //沿着 Z 轴移动 ``` **格式举例:** (1)translateX 举例: ```html
``` 效果: ![](http://img.smyhvae.com/20180208_2036.gif) (2)translateY 举例: ```html
``` 效果: ![](http://img.smyhvae.com/20180208_2037.gif) (3)translateZ 举例: ```html
``` 效果: ![](http://img.smyhvae.com/20180208_2040.gif) 上方代码中,如果不加透视属性,是看不到translateZ的效果的。 ### 3、透视:perspective 电脑显示屏是一个 2D 平面,图像之所以具有立体感(3D效果),其实只是一种视觉呈现,通过透视可以实现此目的。 透视可以将一个2D平面,在转换的过程当中,呈现3D效果。但仅仅只是视觉呈现出3d 效果,并不是正真的3d。 格式有两种写法: - 作为一个属性,设置给父元素,作用于所有3D转换的子元素 - 作为 transform 属性的一个值,做用于元素自身。 ### 4、3D呈现(transform-style) 3D元素构建是指某个图形是由多个元素构成的,可以给这些元素的**父元素**设置`transform-style: preserve-3d`来使其变成一个真正的3D图形。属性值可以如下: ```javascript transform-style: preserve-3d; //让 子盒子 位于三维空间里 transform-style: flat; //让子盒子位于此元素所在的平面内(子盒子被扁平化) ``` **案例:**立方体 ```html
``` ## 动画 动画是CSS3中具有颠覆性的特征,可通过设置**多个节点** 来精确控制一个或一组动画,常用来实现**复杂**的动画效果。 ### 1、定义动画的步骤 (1)通过@keyframes定义动画; (2)将这段动画通过百分比,分割成多个节点;然后各节点中分别定义各属性; (3)在指定元素里,通过 `animation` 属性调用动画。 之前,我们在 js 中定义一个函数的时候,是先定义,再调用: ```javascript js 定义函数: function fun(){ 函数体 } 调用: fun(); ``` 同样,我们在 CSS3 中**定义动画**的时候,也是**先定义,再调用**: ```javascript 定义动画: @keyframes 动画名{ from{ 初始状态 } to{ 结束状态 } } 调用: animation: 动画名称 持续时间; ``` 其中,animation属性的格式如下: ```javascript animation: 定义的动画名称 持续时间 执行次数 是否反向 运动曲线 延迟执行。(infinite 表示无限次) animation: move1 1s alternate linear 3; animation: move2 4s; ``` **定义动画的格式举例:** ```html
``` 注意好好看代码中的注释。 效果如下: ![](http://img.smyhvae.com/20180209_1001.gif) ### 2、动画属性 我们刚刚在调用动画时,animation属性的格式如下: animation属性的格式如下: ```javascript animation: 定义的动画名称 持续时间 执行次数 是否反向 运动曲线 延迟执行。(infinite 表示无限次) animation: move1 1s alternate linear 3; animation: move2 4s; ``` 可以看出,这里的 animation 是综合属性,接下来,我们把这个综合属性拆分看看。 (1)动画名称: ```javascript animation-name: move; ``` (2)执行一次动画的持续时间: ```javascript animation-duration: 4s; ``` 备注:上面两个属性,是必选项,且顺序固定。 (3)动画的执行次数: ```javascript animation-iteration-count: 1; //iteration的含义表示迭代 ``` 属性值`infinite`表示无数次。 (3)动画的方向: ```javascript animation-direction: alternate; ``` 属性值:normal 正常,alternate 反向。 (4)动画延迟执行: ```javascript animation-delay: 1s; ``` (5)设置动画结束时,盒子的状态: ```javascript animation-fill-mode: forwards; ``` 属性值: forwards:保持动画结束后的状态(默认), backwards:动画结束后回到最初的状态。 (6)运动曲线: ``` animation-timing-function: ease-in; ``` 属性值可以是:linear ease-in-out steps()等。 注意,如果把属性值写成**` steps()`**,则表示动画**不是连续执行**,而是间断地分成几步执行。我们接下来专门讲一下属性值 `steps()`。 ### steps()的效果 我们还是拿上面的例子来举例,如果在调用动画时,我们写成: ```javascript animation: move2 4s steps(2); ``` 效果如下: ![](http://img.smyhvae.com/20180209_1020.gif) 有了属性值 `steps()`,我们就可以作出很多不连续地动画效果。比如时钟;再比如,通过多张静态的鱼,作出一张游动的鱼。 **step()举例:**时钟的简易模型 ```html
``` 上方代码,我们通过一个黑色的长条div,旋转360度,耗时60s,分成60步完成。即可实现。 效果如下: ![](http://img.smyhvae.com/20180209_1030.gif) ### 动画举例:摆动的鱼 现在,我们要做下面这种效果: ![](http://img.smyhvae.com/20180209_1245.gif) PS:图片的url是,图片较大,如无法观看,可在浏览器中单独打开。 为了作出上面这种效果,要分成两步。 **(1)第一步**:让鱼在原地摆动 鱼在原地摆动并不是一张 gif动图,她其实是由很多张静态图间隔地播放,一秒钟播放完毕,就可以了: ![](http://img.smyhvae.com/20180209_shark.png) 上面这张大图的尺寸是:宽 509 px、高 2160 px。 我们可以理解成,每一帧的尺寸是:宽 509 px、高 270 px。`270 * 8 = 2160`。让上面这张大图,在一秒内从 0px 的位置往上移动2160px,分成8步来移动。就可以实现了。 代码是: ```html
``` 效果如下: ![](http://img.smyhvae.com/20180209_1250.gif) 我们不妨把上面的动画的持续时间从`1s`改成 `8s`,就可以看到动画的慢镜头: ![](http://img.smyhvae.com/20180209_1330.gif) 这下,你应该恍然大悟了。 **(2)第二步**:让鱼所在的盒子向前移动。 实现的原理也很简单,我们在上一步中已经让`shark`这个盒子实现了原地摇摆,现在,让 shark 所在的父盒子 `sharkBox`向前移动,即可。完整版代码是: ```html
``` ![](http://img.smyhvae.com/20180209_1350.gif) 大功告成。 工程文件如下: - [2018-02-09-fishes.rar](http://download.csdn.net/download/smyhvae/10255540) ## 动画案例:太阳系 暂略。 ## 我的公众号 想学习**代码之外的软技能**?不妨关注我的微信公众号:**生命团队**(id:`vitateam`)。 扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: ![](http://img.smyhvae.com/2016040102.jpg)