6. anothers
6.1 transition
transition CSS 属性是 transition-property,transition-duration,transition-timing-function 和 transition-delay 的一个简写属性。
6.2 cubic-bezier
B(t) = P₀(1 - t)³ + 3P₁t(1 - t)² + 3P₂t²(1 - t) + P₃t³ ,t ∈ [0,1]
这是三次贝塞尔曲线的函数P₀ P₃ 分别表示起点和终点P₁ P₂ 表示的是两个控制点 (n 次贝塞尔曲线 有 n-1 个控制点)


cubic-bezier 是 transition-timing-function 属性的属性值
transition-timing-function 的属性值 如上表所示 也可以是关键字 但实际上 它们都有对应的 cubic-bezier 取值
它们实质上都是设置 过渡动画 的运动效果 这个运动效果我们也可以在控制台微调

1 表示 过渡动画 的运动效果
2 表示 cubic-bezier 的取值
P0 和 P3 是起点 (0, 0) 和 (1, 1)
P1 和 P2 是两个控制点(可拖拽) 它们的坐标是 cubic-bezier 的值 即: P1 (0.43, -0.27) P2 (0.54, 1.34)
只要将我们设置好的 cubic-bezier 的值复制到 transition-timing-funtion 中即可, 也就是 transition 的第三个属性值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>cubic-bezier</title>
<style>
div {
border: 1px solid #f40;
border-radius: 10px;
width: 100px;
height: 50px;
transition: all 1s cubic-bezier(0.43, -0.27, 0.54, 1.34);
}
div:hover {
width: 500px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>

当鼠标悬停上去的时候, 它首先会收缩一部分(小于 100px), 然后再伸, 并且会伸过头一部分(大于 500px), 最后再停留到设定值 500px
6.3 animation
transition 实现的过渡动画 仅能在两个状态之间来回切换 但是 animation 可以实现多个状态的动画
animation: name duration timing-function delay iteration-count direction fill-mode play-state;

notes
1. animation-timing-function 设置的是每一个状态切换的运动效果 而非一个完整动画的运动效果; (每一个状态切换的运动效果都一样 若想让它们不一样 可以借助 js 来实现)
2. animation-delay 设置的是一个完整动画的延时 而非 每一个状态切换的延时;
3. animation-play-state 兼容性不好 基本也用不到
4. animation-fill-mode 可以设置动画的状态
forwards 运动结束后 保留最后一帧的状态
backwards 运动开始前 显示第一帧的状态
both 就是 forwards + backwards
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>animation</title>
<style>
.box {
position: absolute;
top: 0;
left: 0;
border-radius: 50%;
width: 100px;
height: 100px;
background-color: #008c8c;
cursor: pointer;
animation: run 4s, color-change 4s; /* 4s 指动画的总时长 */
}
/* @keyframes 关键帧容器
run 关键帧容器的 名称 */
@keyframes run {
0%{ /* 0% 也可以写成 from */
left: 0;
top: 0;
} /* 注意 多个运动状态之间 不需要添加 逗号 作为分隔 */
25%{ /* 当动画的运动时长达到总时长的 25% 时 的状态值 */
left: 100px;
top: 0;
}
50%{
left: 100px;
top: 100px;
}
75%{
left: 0;
top: 100px;
}
100%{ /* 100% 也可以写成 to */
left: 0;
top: 0;
}
}
@keyframes color-change {
from {
background-color: red;
}
50% {
background-color: green;
}
to {
background-color: blue;
}
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>
notes
当动画结束后, 元素的状态 默认 会回归到动画开始前的状态;
可以同时给一个元素添加多个动画;
6.4 animation2
6.5 step
steps() 定义了一个以等距步长划分值域的步长函数。
这个阶跃函数的子类有时也称为阶梯函数。
steps 和 cubic-bezier 一样 都是 timing-function 的属性值
notes
end 保留当前帧状态, 直到这段动画时间结束 (默认值)
解决最后一帧直接跳过的问题:
animation: animation-name steps (num, end) forwards; /* forwards 用于保留最后一帧的状态 */
start 保留下一帧状态, 直到这段动画时间结束
注意: 第一帧的跳过无法使用 backwords 来解决 因为动画开始的时刻就是一个时间点 (同样的道理 若steps的第二个参数是 end 当这个动画运动次数为 infinite 时 那么最后一帧也会变为一个时间点 我们是否设置 forwards 属性 都不影响)
steps(1, end) === step-end
steps(1, start) === step-start
end 和 start
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>steps</title>
<style>
@keyframes run {
from {
left: 0px;
}
20% {
left: 50px;
}
40% {
left: 100px;
}
60% {
left: 150px;
}
80% {
left: 200px;
}
to {
left: 250px;
}
}
.demo1,
.demo2 {
position: absolute;
border-radius: 50%;
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
color: #fff;
background-color: #008c8c;
}
.demo1 {
animation: run 5s steps(1, end) forwards;
/* animation: run 5s steps(1, end) infinite forwards; */
}
.demo2 {
top: 150px;
animation: run 5s steps(1, start);
}
</style>
</head>
<body>
<div class="demo1">end</div>
<div class="demo2">start</div>
</body>
</html>
6.6 step2
6.7 rotate

6.8 scale
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>scale</title>
<style>
* {
padding: 0;
margin: 0;
}
div {
position: absolute;
top: 100px;
left: 100px;
border: 1px solid;
box-sizing: border-box;
height: 100px;
width: 100px;
}
.demo1 {
border-color: #008c8c;
}
.demo2 {
border-color: #f40;
}
</style>
</head>
<body>
<div class="demo1"></div>
<div class="demo2"></div>
</body>
</html>

注意点1:
scale 缩放的并非元素的大小 而是 坐标轴的刻度



注意点2:
scale 可以实现叠加操作


注意点3:
伸缩和旋转的顺序不同 可能会导致结果也不同


scaleZ 不易于演示
6.9 skew
注意点1
skew 不仅具有倾斜效果 还具有拉伸效果

注意点2
skew 和 scale 一样 改变的都是坐标轴
若先操作了 skew 那么也会对后续有关坐标轴的操作造成影响


6.10 translate+perspective
未知尺寸元素的居中问题
/* 在自身的宽高不确定的前提下 若依旧想令该元素水平垂直居中 */
selector {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
perspective 表示 景深 (可叠加)
作用
用于增强 3d 效果
使用
设置在父级上 (单人视角 一双眼睛)
perspective: 800px;
全局 一个 景深
可以调节 origin 的值
常用
设置在每一个子元素上 (多人视角 多双眼睛)
transform: perspective(800px); /* 注意 若不写在最前面 有一些浏览器就识别不了 */
每一个子元素都有对应的 景深
不能调节 origin 的值
不常用

用户所能看到的物体的大小 实际上是该物体在屏幕上投影的大小
transform-style 该属性要设置在直接父级上
6.11 perspective2
6.12 matrix
matrix 矩阵计算规则 transform
矩阵的计算规则: 第一个矩阵的行 * 第二个矩阵的列
| a, c, e | | x | | ax + cy + e |
| b, d, f | * | y | = | bx + dy + f |
| 0, 0, 1 | | 1 | | 0 + 0 + 1 |
参数说明:
matrix (a, b, c, d, e, f)
(x, y) 是变化元素上的每一个像素点的坐标
结果矩阵就是经过 transform 变化之后的元素各像素点的坐标
eg:
1. transform: translate(n, m); === transform: matrix(1, 0, 0, 1, n, m)
| 1, 0, n | | x | | x + 0 + n |
| 0, 1, m | * | y | = | 0 + y + m |
| 0, 0, 1 | | 1 | | 0 + 0 + 1 |
transform 之前 元素身上的所有像素点的坐标值是 (x, y)
经过 transform: translate(n, m); 变化之后
坐标变为 (x + n, y + m)
notes:
(1, 0, 0, 1, n, m) 这 6 个值是倒推出来的结果
2. transform: scale(n, m); === transfor: matrix(n, 0, 0, m, 0, 0)
| n, 0, 0 | | x | | nx + 0 + 0 |
| 0, m, 0 | * | y | = | 0 + my + 0 |
| 0, 0, 1 | | 1 | | 0 + 0 + 1 |
原理: 同1
3. rotate(θ) === matrix(cos(θ), sin(θ), -sin(θ), cos(θ), 0, 0)
...
PS: 上面介绍的仅仅是 transform 的二维变化原理 三维变化实际上原理也相同 也是通过矩阵来计算的 不过暂时没有研究的必要
利用掌握的 matrix 原理 实现图片的 左右翻转效果
思路:
(x, y) -> (-x, y)
| a, c, e | | x | | ax + cy + e |
| b, d, f | * | y | = | bx + dy + f |
| 0, 0, 1 | | 1 | | 0 + 0 + 1 |
matrix (a, b, c, d, e, f);
a 是 -1
d 是 1
其余都是 0
matrix (-1, 0, 0, 1, 0, 0);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>matrix</title>
<style>
body {
background-color: #ddd;
}
div {
position: absolute;
top: 50%;
left: 50%;
/* 图片正常展示效果 */
transform: translate(-50%, -50%);
/* 图片水平翻转后的展示效果 */
/* transform: translate(-50%, -50%) matrix(-1, 0, 0, 1, 0, 0); */
width: 200px;
height: 200px;
background-image: url(./img/dahuyou.jpg); /* 路径也许会有误 得修改 */
background-size: cover;
}
</style>
</head>
<body>
<div></div>
</body>
</html>


