精通 CSS 第 10 章 变换过渡与动画 学习笔记
Posted GoldenaArcher
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了精通 CSS 第 10 章 变换过渡与动画 学习笔记相关的知识,希望对你有一定的参考价值。
精通 CSS 第 10 章 变换、过渡与动画 学习笔记
这一章主要讲的还是让元素“动”起来的特性,主要内容在以下几章学习笔记中有讲到,这里可以算是一个系统性整合了:
-
中含了
transition
特性,即过渡 -
2D 变换的笔记在这里
-
动画,即 关键帧动画
@keyframe
的笔记在这里 -
学完一起做个走马灯吧 - CSS 3D 转换学习笔记&学习案例
3D 变换的笔记在这里
都学过了,所以这一章的内容会很快的过一遍,顺便拾遗补漏。
概述
翻了一下书中讲的狗家的案例,是真的挺好看的:
点进去之后还能够看到狗家的各个产品,都是用这种三维的效果制作的,体感挺好。
二维变换
从技术角度来说,变换(transform) 改变的是元素所在的 坐标系统。
一种看待变换的角度是把他们看成“畸变场”——任何落在元素渲染空间内的像素都会被畸变场必火,然后再将他们传输到页面上的新位置,或改变大小。元素本身还在页面上原来的位置,但它们畸变之后的“影像”已经变换了。
为元素应用变化后,会为元素最初所在的位置创建所谓的 局部坐标系统。页面上任会保留原本的像素空间位置,但是畸变后的局部坐标系不会影响原本的像素空间。
这种说法也能够解释为什么二维转换不会影响到其他元素,毕竟元素本身的位置没有产生任何的改变,受到影响的是元素的“投影”。
例如说下面这个例子:
畸变后元素的局部过标系统如上图所示,并不会影响到原本的的位置坐标系:
这部分源码为:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Document</title> <style> body { padding: 100px; } .box { width: 100px; height: 100px; margin-top: 20px; top: 200px; left: 200px; background-color: #eee; outline: 1px solid; transform: rotate(45deg); } </style> </head> <body> abcdefg <div class="box"></div> hijklmn </body> </html>
变换原点
即 transform-origin
属性,默认情况下,变换是以元素边框盒子的中心作为原点。
变换原点会对元素的旋转产生不同的效果,如将原点从中心修改成左上角,再进行 45° 旋转所产生的效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Simple transform</title>
<style>
body {
padding: 50px 200px;
}
.box {
width: 100px;
height: 100px;
background-color: #eee;
outline: 1px solid;
/* 注视下面这行代码查看不同效果 */
transform-origin: 0 0;
transform: rotate(45deg); /* 1 */
}
</style>
</head>
<body>
origin left-top:
<div class="box"></div>
</body>
</html>
平移
即 translate
属性,使得元素沿着 x 轴 和/或 y 轴进行移动。
多重变换
案例中是结合了 transform 和 translate,效果图如下:
其实现方法是利用伪元素 before
添加 § 3
,再用绝对定位将伪元素中的内容放到 list-style
占用的空间上。before
中的数字是使用了另一种 CSS 的特性 counter 去实现的计数效果。
最初的效果如下:
设置了绝对定位之后,作为 自定义的列表样式属性 的定位如下:
为了能够更清楚地看到样式,我暂时将 li
元素 中的内容注释掉了。
实现平移后的效果如下:
这里已经设置了 transform-origin: 100% 100%;
,即等同于 transform-origin: right bottom;
,将右下角作为旋转中心后,实现旋转 -90° 就完成了最终的效果。
完整实现代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Using transform-origin to rotate text</title>
<style>
body {
font-family: Baskerville, Times, Times New Roman, serif;
font-size: 1.25em;
padding: 3em;
}
h1 {
font-weight: 400;
}
.rules {
counter-reset: rulecount 2;
list-style: none;
padding: 0;
margin: 0;
}
.rules li {
line-height: 1.5;
min-height: 1.75em;
counter-increment: rulecount;
max-width: 35em;
border-left: 1.5em solid #777;
padding-left: 0.5em;
position: relative;
margin-bottom: 0.5em;
}
.rules li:before {
position: absolute;
top: 0;
left: 0;
padding-right: 0.25em;
display: block;
color: #777;
color: #fff;
line-height: 1.5em;
padding-left: 0.25em;
content: "§ " counter(rulecount);
transform: translate(-100%, -100%) rotate(-90deg);
transform-origin: 100% 100%;
}
</style>
</head>
<body>
<h1>Fight Club rules</h1>
<ol class="rules" start="3">
<li>If someone says ”stop”, goes limp or taps out, the fight is over.</li>
<li>Only two guys to a fight.</li>
<li>One fight at a time.</li>
<li>No shirts, no shoes.</li>
<li>Fights will go on as long as they have to.</li>
<li>If this is your first night at FIGHT CLUB, you HAVE to fight.</li>
</ol>
</body>
</html>
平移与旋转的顺序是非常重要的,因为平移的是相对于元素的局部坐标系进行的操作。如果先旋转再进行位移,那么就需要重新计算位移的角度,否则会产生下面的结果:
将 transform
属性修改为 transform: rotate(-90deg) translate(80%, -120%);
还是能够产生一样的效果。
缩放和变形
即 scale
和 skew
两个属性。
scale
,缩放理解起来比较简单,就是对元素产生放大和缩小的变化。
skew
我觉得比较好理解的代入方法是斜体,斜体是对字体倾斜,skew
是对元素倾斜。以上面多重变换的例子,简单的修改一下后会有这样的效果:
修改过的 CSS 部分如下
.rules li {
line-height: 2.5;
min-height: 1.75em;
counter-increment: rulecount;
max-width: 35em;
padding-left: 0.5em;
position: relative;
background-color: #e5212e;
border-left: 1.5em solid #aa031c;
transform: skewX(15deg);
}
.rules li:nth-child(even) {
background-color: #aa031c;
border-color: #6b0011;
transform: skewX(-15deg);
}
只是对颜色的搭配进行了一点儿的修改,就有了深浅折叠的感觉,模拟出了 3D 的效果。
二维矩阵变换
本质上来说,旋转也好,位移也好,都是在一个平面上对元素进行操作,CSS 也提供了一个更加直观明了的属性去进行计算平面直角坐标系:矩阵matrix()
。
以数学的角度来说,它能够更加直观明了的表明想要操作的结果,如:
.some-content {
transform: matrix(1.41, 1.41, -1.16, 1.66, 70.7, 70.7);
/* 与下面的效果一样 */
transform: rotate(45deg) translate(100px, 0) scale(2) skewX(10deg);
}
但是很明显,对于人来说,第二条 CSS 更加方便理解,能够直观的理解这条 CSS 想要实现的目的是什么。
变换与性能
使用 变换(transform) 只会影响到相关元素的直角坐标系,不需要浏览器去重新计算对整个页面造成的影响,因此相应的性能会高一些。
过渡
过渡是一种动画,可以从一个状态过渡到另一个状态,常见的有按钮的点击、菜单栏的展开、元素的切入等。
只需要指定想要的效果以及延续的时间,浏览器能够相对快速地对页面的变化进行重绘,并且会自动双向运行。如当元素处于 hover
状态时触发时会产生的过渡,不再 hover
状态时即会反向运行。
实现代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Button transition</title>
<style>
button {
cursor: pointer;
border: 0;
padding: 0.5em 1em;
color: #fff;
border-radius: 0.25em;
outline: none;
font-size: 1em;
background-color: #173b6d;
background-image: linear-gradient(to bottom, #1a4a8e, #173b6d);
box-shadow: 0 0.25em 0 rgba(23, 59, 109, 0.3), inset 0 1px 0 rgba(0, 0, 0, 0.3);
transition: all 150ms ease-in;
}
button:active {
box-shadow: 0 0 0 rgba(23, 59, 109, 0.3), inset 0 1px 0 rgba(0, 0, 0, 0.3);
transform: translateY(0.25em);
}
</style>
</head>
<body>
<button>Press me!</button>
</body>
</html>
过渡计时函数
即 transition-timing-function
属性,目前有 9 个值,比较值得注意的有以下几个:
-
ease,即默认值
开始的时候稍慢些,迅速加快,最后快接近终值的时候再慢下来
-
ease-in
开始慢,后来快
-
ease-out
与 ease-in 相反
-
ease-in-out
ease-in 和 ease-in-out 的结合,两头慢中间快
-
linear
线性匀速
-
三次贝塞尔函数
即
cubic-bezier(p1, p2, p3, p4)
,需要提供 4 个点去定义三次贝塞尔函数上面的实现,包括 ease 的系列和 linear 底层都是依赖于三次贝塞尔函数实现的。如 ease 可以被重写为
cubic-bezier(0.25, 0.1, 0.25, 1.0)
,linear 的三次贝塞尔函数为cubic-bezier(0.0, 0.0, 1.0, 1.0)
等。和
matrix
一样,都不是给普通人看和用的,如果有特殊需求应该是可以网上找到公式去套用的。 -
步进函数(steps)
steps 的原理和 翻书画 相似,以前看到过就是通过图像快速的闪现,使其在视网膜中停留的时间过短,人的大脑就会自动的产生联想,看起来就和动画效果相似。
之前做的一个特效是奔跑的北极熊,使用的就是
steps
实现的:
使用不同的正向和反向过渡
就是一个有持续的过度效果,但是通过覆写其他的属性,即刻取消过渡效果,依旧以 hover
为例:
.sample {
transition: background-position 0s stpes(6);
}
.sample:hover {
transition-duration: 0.6s;
}
上面的代码中,当鼠标悬浮时会有一个时间长为 0.6s 的过渡阶段,但是一旦鼠标不悬浮于元素上了,因为过度的时间只有 0s,所以反向过度看起来即刻就消失了。
“黏着”过渡
即无限延长过渡时间段,使得反向过渡看起来失效,从而达成实现的过渡效果悬停的感觉。
.sample {
transition: background-position 9999999999s stpes(6);
}
.sample:hover {
transition-duration: 0.6s;
}
延迟过渡
即控制在多久之后才会令过渡效果触发。
过渡的能与不能
过渡只能应用于二者之间有明确的过渡阶段的效果,例如说颜色的变化——本质上来说,网页上的颜色还是通过 rgb
或是 16 进制 转换的值,从纯黑色的 #000 到纯白色的#fff 自然是可以通过计算中间值来达到过度的效果的。
但是对于没有过渡阶段的属性,过渡就无法应用了,例如说 display
属性,display: none;
到 display: block;
中间不存在过渡属性,自然也无法产生过渡动画。
另外一种就是过渡属性有可计算的变化量,但是所赋的值无法进行计算,例如说高度宽度盒子大小等都需要提供参数,但是当参数值为 auto
的时候,过渡就无法正确的计算可变化的数值,因此也就无法产生动画效果。
CSS 关键帧动画
过渡给予了一段动画开始和结束的定义,但是如果中间有其他的动画定义就无法被实现了,而使用关键帧动画可以从仅有两个阶段的尴尬境地脱离出来。
书中的案例就很厉害了,将「生命的幻象」部分的动画展示出来了,下面是关键帧的分割:
结合起来的效果如下:
关键帧部分的实现为:
@keyframes roll {
from {
transform: translateX(-100%);
animation-timing-function: ease-in-out;
}
20% {
transform: translateX(-100%) skewX(15deg);
}
28% {
transform: translateX(-100%) skewX(0deg);
animation-timing-function: ease-out;
}
45% {
transform: translateX(-100%) skewX(-5deg) rotate(20deg) scaleY(1.1);
animation-timing-function: ease-in-out;
}
50% {
transform: translateX(-100%) rotate(45deg) scaleY(1.1);
animation-timing-function: ease-in;
}
60% {
transform: translateX(-100%) rotate(90deg);
}
65% {
transform: translateX(-100%) rotate(90deg) skewY(10deg);
}
70% {
transform: translateX(-100%) rotate(90deg) skewY(0deg);
}
to {
transform: translateX(-100%) rotate(90deg);
}
}
三维变换
关于三维变换,书中实现的一个案例是菜单案例,其效果与下图相似:
这部分内容大多都在 学完一起做个走马灯吧 - CSS 3D 转换学习笔记&学习案例 中讲过了,这里也就不再赘述了。
以上是关于精通 CSS 第 10 章 变换过渡与动画 学习笔记的主要内容,如果未能解决你的问题,请参考以下文章