Webcourse/02-CSS基础/12-CSS3属性详解:动画详解.md
2019-10-08 17:32:55 +08:00

1440 lines
33 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

> 本文最初发表于[博客园]()并在[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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSS 过渡</title>
<style>
body {
margin: 0;
padding: 0;
background-color: #eeeeee;
}
.content {
width: 800px;
height: 320px;
padding-left: 20px;
margin: 80px auto;
}
.item {
width: 230px;
height: 300px;
text-align: center;
margin-right: 20px;
background-color: #FFF;
float: left;
position: relative;
top: 0;
overflow: hidden; /* 让溢出的内容隐藏起来。意思是让下方的橙色方形先躲起来 */
transition: all .5s; /* 从最初到鼠标悬停时的过渡 */
}
.item img {
margin-top: 30px;
}
.item .desc {
position: absolute;
left: 0;
bottom: -80px;
width: 100%;
height: 80px;
background-color: #ff6700;
transition: all .5s;
}
/* 鼠标悬停时,让 item 整体往上移动5px且加一点阴影 */
.item:hover {
top: -5px;
box-shadow: 0 0 15px #AAA;
}
/* 鼠标悬停时,让下方的橙色方形现身 */
.item:hover .desc {
bottom: 0;
}
</style>
</head>
<body>
<div class="content">
<div class="item">
<img src="./images/1.png" alt="">
</div>
<div class="item">
<img src="./images/2.png" alt="">
<span class="desc"></span>
</div>
<div class="item">
<img src="./images/3.jpg" alt="">
<span class="desc"></span>
</div>
</div>
</body>
</html>
```
效果如下
![](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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 1000px;
margin: 100px auto;
}
.box div {
width: 300px;
height: 150px;
background-color: pink;
float: left;
margin-right: 15px;
color: white;
text-align: center;
font: 400 30px/150px “宋体”;
}
.box .box2 {
background-color: green;
transition: all 1s;
}
.box .box2:hover {
/*width: 500px;*/
/*height: 400px;*/
background-color: yellowgreen;
/* transform: css3中用于做变换的属性
scale(x,y):缩放 */
transform: scale(2, 0.5);
}
</style>
</head>
<body>
<div class="box">
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">3</div>
</div>
</body>
</html>
```
效果
![](http://img.smyhvae.com/20180208_1551.gif)
上图可以看到 box1 设置 2D 转换并不会把兄弟元素挤走
### 2位移translate
格式
```javascript
transform: translate(水平位移, 垂直位移);
transform: translate(-50%, -50%);
```
参数解释
- 参数为百分比相对于自身移动
- 正值向右和向下 负值向左和向上如果只写一个值则表示水平移动
格式举例
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 1000px;
margin: 100px auto;
}
.box > div {
width: 300px;
height: 150px;
border: 1px solid #000;
background-color: red;
float: left;
margin-right: 30px;
}
div:nth-child(2) {
background-color: pink;
transition: all 1s;
}
/* translate:(水平位移,垂直位移)*/
div:nth-child(2):hover {
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div class="box">
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">3</div>
</div>
</body>
</html>
```
效果
![](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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 200px;
height: 200px;
background-color: red;
margin: 50px auto;
color: #fff;
font-size: 50px;
transition: all 2s; /* 过渡:让盒子在进行 transform 转换的时候,有个过渡期 */
}
/* rotate角度旋转 */
.box:hover {
transform: rotate(-405deg); /* 鼠标悬停时,让盒子进行旋转 */
}
</style>
</head>
<body>
<div class="box">1</div>
</div>
</body>
</html>
```
效果
![](http://img.smyhvae.com/20180208_1630.gif)
注意上方代码中我们给盒子设置了 transform 中的 rotate 旋转但同时还要给盒子设置 transition 过渡如果没有这行过渡的代码旋转会直接一步到位效果如下不是我们期望的效果
![](http://img.smyhvae.com/20180208_1635.gif)
**案例1**小火箭
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
html,body{
height:100%;
}
body{
background-color: #DE8910;
}
.rocket{
position: absolute;
left:100px;
top:600px;
height: 120px;
transform:translate(-200px ,200px) rotate(45deg);
transition:all 1s ease-in;
}
body:hover .rocket{
transform:translate(500px,-500px) rotate(45deg);
}
</style>
</head>
<body>
<img class="rocket" src="images/rocket.png" alt=""/>
</body>
</html>
```
上方代码中我们将 transform 的两个小属性合并起来写了
小火箭图片的url<http://img.smyhvae.com/20180208-rocket.png>
**案例2**扑克牌
rotate 旋转时默认是以盒子的正中心为坐标原点的如果想**改变旋转的坐标原点**可以用`transform-origin`属性格式如下
```javascript
transform-origin: 水平坐标 垂直坐标;
transform-origin: 50px 50px;
transform-origin: center bottom; //旋转时,以盒子底部的中心为坐标原点
```
我们来看一下 rotate 结合 transform-origin 的用法举例
代码如下
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body {
/*background-color: #eee;*/
}
.box {
width: 300px;
height: 440px;
margin: 100px auto;
position: relative;
}
img {
width: 100%;
transition: all 1.5s;
position: absolute; /* 既然扑克牌是叠在一起的,那就都用绝对定位 */
left: 0;
top: 0;
transform-origin: center bottom; /*旋转时,以盒子底部的中心为坐标原点*/
box-shadow: 0 0 3px 0 #666;
}
.box:hover img:nth-child(6) {
transform: rotate(-10deg);
}
.box:hover img:nth-child(5) {
transform: rotate(-20deg);
}
.box:hover img:nth-child(4) {
transform: rotate(-30deg);
}
.box:hover img:nth-child(3) {
transform: rotate(-40deg);
}
.box:hover img:nth-child(2) {
transform: rotate(-50deg);
}
.box:hover img:nth-child(1) {
transform: rotate(-60deg);
}
.box:hover img:nth-child(8) {
transform: rotate(10deg);
}
.box:hover img:nth-child(9) {
transform: rotate(20deg);
}
.box:hover img:nth-child(10) {
transform: rotate(30deg);
}
.box:hover img:nth-child(11) {
transform: rotate(40deg);
}
.box:hover img:nth-child(12) {
transform: rotate(50deg);
}
.box:hover img:nth-child(13) {
transform: rotate(60deg);
}
</style>
</head>
<body>
<div class="box">
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
<img src="images/pk2.png"/>
<img src="images/pk1.png"/>
</div>
</body>
</html>
```
效果如下
![](http://img.smyhvae.com/20180208_1650.gif)
### 4倾斜
暂略
## 3D 转换
### 1旋转rotateXrotateYrotateZ
**3D坐标系左手坐标系**
![](http://img.smyhvae.com/20180208_2010.png)
如上图所示伸出左手让拇指和食指成L大拇指向右食指向上中指指向前方拇指食指和中指分别代表XYZ轴的正方向这样我们就建立了一个左手坐标系
浏览器的这个平面是X轴Y轴垂直于浏览器的平面是Z轴
**旋转的方向左手法则**
左手握住旋转轴竖起拇指指向旋转轴的**正方向**正向就是**其余手指卷曲的方向**
从上面这句话我们也能看出所有的3d旋转对着正方向去看都是顺时针旋转
**格式**
```javascript
transform: rotateX(360deg); //绕 X 轴旋转360度
transform: rotateY(360deg); //绕 Y 轴旋转360度
transform: rotateZ(360deg); //绕 Z 轴旋转360度
```
**格式举例**
1rotateX 举例
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.rotateX {
width: 300px;
height: 226px;
margin: 200px auto;
/* 透视 :加给变换的父盒子*/
/* 设置的是用户的眼睛距离 平面的距离*/
/* 透视效果只是视觉上的呈现并不是正真的3d*/
perspective: 110px;
}
img {
/* 过渡*/
transition: transform 2s;
}
/* 所有的3d旋转对着正方向去看都是顺时针旋转*/
.rotateX:hover img {
transform: rotateX(360deg);
}
</style>
</head>
<body>
<div class="rotateX">
<img src="images/x.jpg" alt=""/>
</div>
</body>
</html>
```
效果
![](http://img.smyhvae.com/20180208_2025.gif)
上方代码中我们最好加个透视的属性方能看到3D的效果没有这个属性的话图片旋转的时候像是压瘪了一样
而且透视的是要加给图片的父元素 div方能生效我们在后面会讲解透视属性
2rotateY 举例
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.rotateY {
width: 237px;
height: 300px;
margin: 100px auto;
/* 透视 */
perspective: 150px;
}
img {
transition: all 2s; /* 过渡 */
}
.rotateY:hover img {
transform: rotateY(360deg);
}
</style>
</head>
<body>
<div class="rotateY">
<img src="images/y.jpg" alt=""/>
</div>
</body>
</html>
```
效果
![](http://img.smyhvae.com/20180208_2030.gif)
3rotateZ 举例
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.rotateZ {
width: 330px;
height: 227px;
margin: 100px auto;
/* 透视*/
perspective: 200px;
}
img {
transition: all 1s;
}
.rotateZ:hover img {
transform: rotateZ(360deg);
}
</style>
</head>
<body>
<div class="rotateZ">
<img src="images/z.jpg" alt=""/>
</div>
</body>
</html>
```
效果
![](http://img.smyhvae.com/20180208_2035.gif)
**案例**百度钱包的水平翻转效果
现在有下面这张图片素材
![](http://img.smyhvae.com/20180208_2055.png)
要求做成下面这种效果
![](http://img.smyhvae.com/20180208_2100.gif)
上面这张图片素材其实用的是精灵图实现的代码如下
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body {
background-color: cornflowerblue;
}
.box {
width: 300px;
height: 300px;
/*border: 1px solid #000;*/
margin: 50px auto;
position: relative;
}
.box > div {
width: 100%;
height: 100%;
position: absolute;
/*border: 1px solid #000;*/
border-radius: 50%;
transition: all 2s;
backface-visibility: hidden;
}
.box1 {
background: url(images/bg.png) left 0 no-repeat; /*默认显示图片的左半边*/
}
.box2 {
background: url(images/bg.png) right 0 no-repeat;
transform: rotateY(180deg); /*让图片的右半边默认时旋转180度就可以暂时隐藏起来*/
}
.box:hover .box1 {
transform: rotateY(180deg); /*让图片的左半边转消失*/
}
.box:hover .box2 {
transform: rotateY(0deg); /*让图片的左半边转出现*/
}
</style>
</head>
<body>
<div class="box">
<div class="box1"></div>
<div class="box2"></div>
</div>
</body>
</html>
```
### 2移动translateXtranslateYtranslateZ
**格式**
```javascript
transform: translateX(100px); //沿着 X 轴移动
transform: translateY(360px); //沿着 Y 轴移动
transform: translateZ(360px); //沿着 Z 轴移动
```
**格式举例**
1translateX 举例
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 200px;
height: 200px;
background: green;
transition: all 1s;
}
.box:hover {
transform: translateX(100px);
}
</style>
</head>
<body>
<div class="box">
</div>
</body>
</html>
```
效果
![](http://img.smyhvae.com/20180208_2036.gif)
2translateY 举例
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 200px;
height: 200px;
background: green;
transition: all 1s;
}
.box:hover {
transform: translateY(100px);
}
</style>
</head>
<body>
<div class="box">
</div>
</body>
</html>
```
效果
![](http://img.smyhvae.com/20180208_2037.gif)
3translateZ 举例
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body {
/* 给box的父元素加透视效果*/
perspective: 1000px;
}
.box {
width: 250px;
height: 250px;
background: green;
transition: all 1s;
margin: 200px auto
}
.box:hover {
/* translateZ必须配合透视来使用*/
transform: translateZ(400px);
}
</style>
</head>
<body>
<div class="box">
</div>
</body>
</html>
```
效果
![](http://img.smyhvae.com/20180208_2040.gif)
上方代码中如果不加透视属性是看不到translateZ的效果的
### 3透视perspective
电脑显示屏是一个 2D 平面图像之所以具有立体感3D效果其实只是一种视觉呈现通过透视可以实现此目的
透视可以将一个2D平面在转换的过程当中呈现3D效果但仅仅只是视觉呈现出 3d 效果并不是正真的3d
格式有两种写法
- 作为一个属性设置给父元素作用于所有3D转换的子元素
- 作为 transform 属性的一个值做用于元素自身
格式举例
```css
perspective: 500px;
```
### 43D呈现transform-style
3D元素构建是指某个图形是由多个元素构成的可以给这些元素的**父元素**设置`transform-style: preserve-3d`来使其变成一个真正的3D图形属性值可以如下
```css
transform-style: preserve-3d; /* 让 子盒子 位于三维空间里 */
transform-style: flat; /* 让子盒子位于此元素所在的平面内(子盒子被扁平化) */
```
**案例**立方体
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 250px;
height: 250px;
border: 1px dashed red;
margin: 100px auto;
position: relative;
border-radius: 50%;
/* 让子盒子保持3d效果*/
transform-style: preserve-3d;
/*transform:rotateX(30deg) rotateY(-30deg);*/
animation: gun 8s linear infinite;
}
.box > div {
width: 100%;
height: 100%;
position: absolute;
text-align: center;
line-height: 250px;
font-size: 60px;
color: #daa520;
}
.left {
background-color: rgba(255, 0, 0, 0.3);
/* 变换中心*/
transform-origin: left;
/* 变换*/
transform: rotateY(90deg) translateX(-125px);
}
.right {
background: rgba(0, 0, 255, 0.3);
transform-origin: right;
/* 变换*/
transform: rotateY(90deg) translateX(125px);
}
.forward {
background: rgba(255, 255, 0, 0.3);
transform: translateZ(125px);
}
.back {
background: rgba(0, 255, 255, 0.3);
transform: translateZ(-125px);
}
.up {
background: rgba(255, 0, 255, 0.3);
transform: rotateX(90deg) translateZ(125px);
}
.down {
background: rgba(99, 66, 33, 0.3);
transform: rotateX(-90deg) translateZ(125px);
}
@keyframes gun {
0% {
transform: rotateX(0deg) rotateY(0deg);
}
100% {
transform: rotateX(360deg) rotateY(360deg);
}
}
</style>
</head>
<body>
<div class="box">
<div class="up">上</div>
<div class="down">下</div>
<div class="left">左</div>
<div class="right">右</div>
<div class="forward">前</div>
<div class="back">后</div>
</div>
</body>
</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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 100px;
height: 100px;
margin: 100px;
background-color: red;
/* 调用动画*/
/* animation: 动画名称 持续时间 执行次数 是否反向 运动曲线 延迟执行。infinite 表示无限次*/
/*animation: move 1s alternate linear 3;*/
animation: move2 4s;
}
/* 方式一:定义一组动画*/
@keyframes move1 {
from {
transform: translateX(0px) rotate(0deg);
}
to {
transform: translateX(500px) rotate(555deg);
}
}
/* 方式二:定义多组动画*/
@keyframes move2 {
0% {
transform: translateX(0px) translateY(0px);
background-color: red;
border-radius: 0;
}
25% {
transform: translateX(500px) translateY(0px);
}
/*动画执行到 50% 的时候,背景色变成绿色,形状变成圆形*/
50% {
/* 虽然两个方向都有translate但其实只是Y轴上移动了200px。
因为X轴的500px是相对最开始的原点来说的。可以理解成此时的 translateX 是保存了之前的位移 */
transform: translateX(500px) translateY(200px);
background-color: green;
border-radius: 50%;
}
75% {
transform: translateX(0px) translateY(200px);
}
/*动画执行到 100% 的时候,背景色还原为红色,形状还原为正方形*/
100% {
/*坐标归零,表示回到原点。*/
transform: translateX(0px) translateY(0px);
background-color: red;
border-radius: 0;
}
}
</style>
</head>
<body>
<div class="box">
</div>
</body>
</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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
div {
width: 3px;
height: 200px;
background-color: #000;
margin: 100px auto;
transform-origin: center bottom; /* 旋转的中心点是底部 */
animation: myClock 60s steps(60) infinite;
}
@keyframes myClock {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div></div>
</body>
</html>
```
上方代码我们通过一个黑色的长条div旋转360度耗时60s分成60步完成即可实现
效果如下
![](http://img.smyhvae.com/20180209_1030.gif)
### 动画举例摆动的鱼
现在我们要做下面这种效果
![](http://img.smyhvae.com/20180209_1245.gif)
PS图片的url是<http://img.smyhvae.com/20180209_1245.gif>,图片较大,如无法观看,可在浏览器中单独打开。
为了作出上面这种效果要分成两步
**1第一步**让鱼在原地摆动
鱼在原地摆动并不是一张 gif动图她其实是由很多张静态图间隔地播放一秒钟播放完毕就可以了
![](http://img.smyhvae.com/20180209_shark.png)
上面这张大图的尺寸是 509 px 2160 px
我们可以理解成每一帧的尺寸是 509 px 270 px`270 * 8 = 2160`让上面这张大图在一秒内从 0px 的位置往上移动2160px分成8步来移动就可以实现了
代码是
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.shark {
width: 509px;
height: 270px; /*盒子的宽高是一帧的宽高*/
border: 1px solid #000;
margin: 100px auto;
background: url(images/shark.png) left top; /* 让图片一开始位于 0 px的位置 */
animation: sharkRun 1s steps(8) infinite; /* 一秒之内,从顶部移动到底部,分八帧, */
}
@keyframes sharkRun {
0% {
}
/* 270 * 8 = 2160 */
100% {
background-position: left -2160px; /* 动画结束时,让图片位于最底部 */
}
}
</style>
</head>
<body>
<div class="sharkBox">
<div class="shark"></div>
</div>
</div>
</body>
</html>
```
效果如下
![](http://img.smyhvae.com/20180209_1250.gif)
我们不妨把上面的动画的持续时间从`1s`改成 `8s`就可以看到动画的慢镜头
![](http://img.smyhvae.com/20180209_1330.gif)
这下你应该恍然大悟了
**2第二步**让鱼所在的盒子向前移动
实现的原理也很简单我们在上一步中已经让`shark`这个盒子实现了原地摇摆现在 shark 所在的父盒子 `sharkBox`向前移动即可完整版代码是
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.shark {
width: 509px;
height: 270px; /* 盒子的宽高是一帧的宽高 */
border: 1px solid #000;
margin: 100px auto;
background: url(images/shark.png) left top; /* 让图片一开始位于 0 px的位置 */
animation: sharkRun 1s steps(8) infinite; /* 一秒之内,从顶部移动到底部,分八帧 */
}
/* 鱼所在的父盒子 */
.sharkBox {
width: 509px;
height: 270px;
animation: sharkBoxRun 20s linear infinite;
}
@keyframes sharkRun {
0% {
}
/* 270 * 8 = 2160 */
100% {
background-position: left -2160px; /* 动画结束时,让图片位于最底部 */
}
}
@keyframes sharkBoxRun {
0% {
transform: translateX(-600px);
}
100% {
transform: translateX(3000px);
}
}
</style>
</head>
<body>
<div class="sharkBox">
<div class="shark"></div>
</div>
</div>
</body>
</html>
```
![](http://img.smyhvae.com/20180209_1350.gif)
大功告成
工程文件如下
- [2018-02-09-fishes.rar](http://download.csdn.net/download/smyhvae/10255540)
## 我的公众号
想学习**代码之外的技能**不妨关注我的微信公众号**千古壹号**id`qianguyihao`
扫一扫你将发现另一个全新的世界而这将是一场美丽的意外
![](http://img.smyhvae.com/20190101.png)