篇首语:本文由编程笔记#小编为大家整理,主要介绍了精通 CSS 第 10 章 变换过渡与动画 学习笔记相关的知识,希望对你有一定的参考价值。
这一章主要讲的还是让元素“动”起来的特性,主要内容在以下几章学习笔记中有讲到,这里可以算是一个系统性整合了:
CSS3 新特性学习
中含了 transition
特性,即过渡
CSS 2D Transform 学习笔记
2D 变换的笔记在这里
CSS 动画 学习笔记和学习案例
动画,即 关键帧动画@keyframe
的笔记在这里
学完一起做个走马灯吧 - CSS 3D 转换学习笔记&学习案例
3D 变换的笔记在这里
都学过了,所以这一章的内容会很快的过一遍,顺便拾遗补漏。
翻了一下书中讲的狗家的案例,是真的挺好看的:
点进去之后还能够看到狗家的各个产品,都是用这种三维的效果制作的,体感挺好。
从技术角度来说,变换(transform) 改变的是元素所在的 坐标系统。
一种看待变换的角度是把他们看成“畸变场”——任何落在元素渲染空间内的像素都会被畸变场必火,然后再将他们传输到页面上的新位置,或改变大小。元素本身还在页面上原来的位置,但它们畸变之后的“影像”已经变换了。
为元素应用变化后,会为元素最初所在的位置创建所谓的 局部坐标系统。页面上任会保留原本的像素空间位置,但是畸变后的局部坐标系不会影响原本的像素空间。
这种说法也能够解释为什么二维转换不会影响到其他元素,毕竟元素本身的位置没有产生任何的改变,受到影响的是元素的“投影”。
例如说下面这个例子:
畸变后元素的局部过标系统如上图所示,并不会影响到原本的的位置坐标系:
这部分源码为:
html>
<html lang&#61;"en">
<head>
<meta charset&#61;"UTF-8" />
<title>Documenttitle>
<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&#61;"box">div>
hijklmn
body>
html>
即 transform-origin
属性&#xff0c;默认情况下&#xff0c;变换是以元素边框盒子的中心作为原点。
变换原点会对元素的旋转产生不同的效果&#xff0c;如将原点从中心修改成左上角&#xff0c;再进行 45° 旋转所产生的效果&#xff1a;
<html lang&#61;"en">
<head>
<meta charset&#61;"UTF-8" />
<title>Simple transformtitle>
<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&#61;"box">div>
body>
html>
即 translate
属性&#xff0c;使得元素沿着 x 轴 和/或 y 轴进行移动。
案例中是结合了 transform 和 translate&#xff0c;效果图如下&#xff1a;
其实现方法是利用伪元素 before
添加 § 3
&#xff0c;再用绝对定位将伪元素中的内容放到 list-style
占用的空间上。before
中的数字是使用了另一种 CSS 的特性 counter 去实现的计数效果。
最初的效果如下&#xff1a;
设置了绝对定位之后&#xff0c;作为 自定义的列表样式属性 的定位如下&#xff1a;
为了能够更清楚地看到样式&#xff0c;我暂时将 li
元素 中的内容注释掉了。
实现平移后的效果如下&#xff1a;
这里已经设置了 transform-origin: 100% 100%;
&#xff0c;即等同于 transform-origin: right bottom;
&#xff0c;将右下角作为旋转中心后&#xff0c;实现旋转 -90° 就完成了最终的效果。
完整实现代码&#xff1a;
<html lang&#61;"en">
<head>
<meta charset&#61;"UTF-8" />
<title>Using transform-origin to rotate texttitle>
<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 rulesh1>
<ol class&#61;"rules" start&#61;"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>
平移与旋转的顺序是非常重要的&#xff0c;因为平移的是相对于元素的局部坐标系进行的操作。如果先旋转再进行位移&#xff0c;那么就需要重新计算位移的角度&#xff0c;否则会产生下面的结果&#xff1a;
将 transform
属性修改为 transform: rotate(-90deg) translate(80%, -120%);
还是能够产生一样的效果。
即 scale
和 skew
两个属性。
scale
&#xff0c;缩放理解起来比较简单&#xff0c;就是对元素产生放大和缩小的变化。
skew
我觉得比较好理解的代入方法是斜体&#xff0c;斜体是对字体倾斜&#xff0c;skew
是对元素倾斜。以上面多重变换的例子&#xff0c;简单的修改一下后会有这样的效果&#xff1a;
修改过的 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);
}
只是对颜色的搭配进行了一点儿的修改&#xff0c;就有了深浅折叠的感觉&#xff0c;模拟出了 3D 的效果。
本质上来说&#xff0c;旋转也好&#xff0c;位移也好&#xff0c;都是在一个平面上对元素进行操作&#xff0c;CSS 也提供了一个更加直观明了的属性去进行计算平面直角坐标系&#xff1a;矩阵matrix()
。
以数学的角度来说&#xff0c;它能够更加直观明了的表明想要操作的结果&#xff0c;如&#xff1a;
.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);
}
但是很明显&#xff0c;对于人来说&#xff0c;第二条 CSS 更加方便理解&#xff0c;能够直观的理解这条 CSS 想要实现的目的是什么。
使用 变换(transform) 只会影响到相关元素的直角坐标系&#xff0c;不需要浏览器去重新计算对整个页面造成的影响&#xff0c;因此相应的性能会高一些。
过渡是一种动画&#xff0c;可以从一个状态过渡到另一个状态&#xff0c;常见的有按钮的点击、菜单栏的展开、元素的切入等。
只需要指定想要的效果以及延续的时间&#xff0c;浏览器能够相对快速地对页面的变化进行重绘&#xff0c;并且会自动双向运行。如当元素处于 hover
状态时触发时会产生的过渡&#xff0c;不再 hover
状态时即会反向运行。
实现代码&#xff1a;
<html lang&#61;"en">
<head>
<meta charset&#61;"UTF-8" />
<meta name&#61;"viewport" content&#61;"width&#61;device-width, initial-scale&#61;1.0" />
<title>Button transitiontitle>
<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
属性&#xff0c;目前有 9 个值&#xff0c;比较值得注意的有以下几个&#xff1a;
ease&#xff0c;即默认值
开始的时候稍慢些&#xff0c;迅速加快&#xff0c;最后快接近终值的时候再慢下来
ease-in
开始慢&#xff0c;后来快
ease-out
与 ease-in 相反
ease-in-out
ease-in 和 ease-in-out 的结合&#xff0c;两头慢中间快
linear
线性匀速
三次贝塞尔函数
即 cubic-bezier(p1, p2, p3, p4)
&#xff0c;需要提供 4 个点去定义三次贝塞尔函数
上面的实现&#xff0c;包括 ease 的系列和 linear 底层都是依赖于三次贝塞尔函数实现的。如 ease 可以被重写为 cubic-bezier(0.25, 0.1, 0.25, 1.0)
&#xff0c;linear 的三次贝塞尔函数为 cubic-bezier(0.0, 0.0, 1.0, 1.0)
等。
和 matrix
一样&#xff0c;都不是给普通人看和用的&#xff0c;如果有特殊需求应该是可以网上找到公式去套用的。
步进函数(steps)
steps 的原理和 翻书画 相似&#xff0c;以前看到过就是通过图像快速的闪现&#xff0c;使其在视网膜中停留的时间过短&#xff0c;人的大脑就会自动的产生联想&#xff0c;看起来就和动画效果相似。
之前做的一个特效是奔跑的北极熊&#xff0c;使用的就是 steps
实现的&#xff1a;
就是一个有持续的过度效果&#xff0c;但是通过覆写其他的属性&#xff0c;即刻取消过渡效果&#xff0c;依旧以 hover
为例&#xff1a;
.sample {
transition: background-position 0s stpes(6);
}
.sample:hover {
transition-duration: 0.6s;
}
上面的代码中&#xff0c;当鼠标悬浮时会有一个时间长为 0.6s 的过渡阶段&#xff0c;但是一旦鼠标不悬浮于元素上了&#xff0c;因为过度的时间只有 0s&#xff0c;所以反向过度看起来即刻就消失了。
即无限延长过渡时间段&#xff0c;使得反向过渡看起来失效&#xff0c;从而达成实现的过渡效果悬停的感觉。
.sample {
transition: background-position 9999999999s stpes(6);
}
.sample:hover {
transition-duration: 0.6s;
}
即控制在多久之后才会令过渡效果触发。
过渡只能应用于二者之间有明确的过渡阶段的效果&#xff0c;例如说颜色的变化——本质上来说&#xff0c;网页上的颜色还是通过 rgb
或是 16 进制 转换的值&#xff0c;从纯黑色的 #000 到纯白色的#fff 自然是可以通过计算中间值来达到过度的效果的。
但是对于没有过渡阶段的属性&#xff0c;过渡就无法应用了&#xff0c;例如说 display
属性&#xff0c;display: none;
到 display: block;
中间不存在过渡属性&#xff0c;自然也无法产生过渡动画。
另外一种就是过渡属性有可计算的变化量&#xff0c;但是所赋的值无法进行计算&#xff0c;例如说高度宽度盒子大小等都需要提供参数&#xff0c;但是当参数值为 auto
的时候&#xff0c;过渡就无法正确的计算可变化的数值&#xff0c;因此也就无法产生动画效果。
过渡给予了一段动画开始和结束的定义&#xff0c;但是如果中间有其他的动画定义就无法被实现了&#xff0c;而使用关键帧动画可以从仅有两个阶段的尴尬境地脱离出来。
书中的案例就很厉害了&#xff0c;将「生命的幻象」部分的动画展示出来了&#xff0c;下面是关键帧的分割&#xff1a;
结合起来的效果如下&#xff1a;
关键帧部分的实现为&#xff1a;
&#64;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);
}
}
关于三维变换&#xff0c;书中实现的一个案例是菜单案例&#xff0c;其效果与下图相似&#xff1a;
这部分内容大多都在 学完一起做个走马灯吧 - CSS 3D 转换学习笔记&学习案例 中讲过了&#xff0c;这里也就不再赘述了。