CSS 基础
取值单位
外观样式
布局样式
动画样式
工具与规范
实例练习
关键帧动画
animation
属性设定了元素的动画效果,与过渡动画不同的是,关键帧动画可以被设定为一直存在,无需在属性值改变时才触发。
<div class="box"></div>
<style>
.box {
width: 100px;
height: 50px;
background-color: teal;
animation: 2s infinite effect;
}
@keyframes effect {
to {
width: 300px;
}
}
</style>
$$demo
<div class="box"></div>
<style>
.box {
width: 100px;
height: 50px;
background-color: teal;
animation: 2s infinite effect;
}
@keyframes effect {
to {
width: 300px;
}
}
</style>
$$
animation
是多个样式属性的缩写:
- animation-name:动画关键帧名。
- animation-duration:动画时长。
- animation-timing-function:动画曲线。
- animation-delay:延迟时长。
- animation-iteration-count:播放次数。
- animation-direction:播放方向。
- animation-play-state:播放状态。
animation-name
animation-name
设定了动画关键帧名,搭配 @keyframes
指定一系列关键帧。
<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/zYpKRLV?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
@keyframes
@keyframes
中使用百分比来定义在不同阶段的动画效果,也有关键字取值:
- from:等同于 0%。
- to:等同于 100%。
$$tip
未设置 from
和 to
的情况下,它们的样式等同于元素设定的样式值。
$$
<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/jOYMZoe?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
animation-duration
animation-duration
定义了动画播放的时长,默认值 0s
,取值是时间单位。
<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/MWrjVqa?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
animation-timing-function
animation-timing-function
定义了动画的变化曲线,默认值是 ease
,有以下取值:
- 关键字:参考 animation-timing-function - MDN。
- 使用函数:参考 easing-function - MDN , 更好的选择是去 easings.net 复制一个定义好的函数。
<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/GRyjxPY?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
animation-delay
animation-delay
决定了动画延迟播放的时长,默认值是 0s
,取值是时间单位。
<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/QWaKmRW?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
animation-iteration-count
animation-iteration-count
定义了动画的播放次数,默认值是 1
,有以下取值:
- 非负数字:播放的次数,可以为小数,比如
0.5
就表示播放一半的动画效果。 - infinite:无限次循环。
animation-direction
animation-direction
决定了动画的播放方向,有以下取值:
- normal:默认值,正向播放,播放结束后返回最初的状态。
- alternate:正反交替,正向开始,动画正向与反向交替播放。
- reverse:反向播放。
- alternate-reverse:正反交替,反向开始,动画正向与反向交替播放。
<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/rNpMvOy?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
animation-play-state
animation-play-state
定义了元素的播放状态,有两个取值:
- running:默认值,正常播放。
- paused:暂停。
<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/qBpaYNo?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
练习
- 实现以下的实例效果。
$$demo
<div class="box">三眼鸭的编程教室</div>
<style>
.box {
display: inline-block;
padding: 10px 20px;
border: 4px solid black;
animation-name: roll;
animation-duration: 4s;
animation-iteration-count: infinite;
}
@keyframes roll {
to {
transform: rotateY(360deg);
}
}
</style>
$$
$$answer
<div class="box">三眼鸭的编程教室</div>
<style>
.box {
display: inline-block;
padding: 10px 20px;
border: 4px solid black;
animation-name: roll;
animation-duration: 4s;
animation-iteration-count: infinite;
}
@keyframes roll {
to {
transform: rotateY(360deg);
}
}
</style>
$$
- 实现以下的时钟效果。 $$tip
transform-origin 可以设置变换的原点。
$$ $$demo <div class="dial"> <div class="second pointer"></div> <div class="minute pointer"></div> </div> <style> .dial { width: 200px; height: 200px;
border-radius: 50%;
border: 10px solid black;
position: relative;
}
.pointer {
/* 指针尾部多余的长度 */
--out-len: 20px;
/* 指针的宽度 */
width: 10px;
position: absolute;
left: 0;
right: 0;
margin: auto;
bottom: calc(50% - var(--out-len));
/* 旋转的原点: x 为中心, y 为元素的长度减去尾部的长度 */
transform-origin: center calc(100% - var(--out-len));
animation-name: effect;
/* 线性播放动画效果 */
animation-timing-function: linear;
/* 无限循环 */
animation-iteration-count: infinite;
}
.second {
/* 45% 的长度加上指针尾部的长度 */
height: calc(45% + var(--out-len));
background-color: red;
/* 每圈 60 秒 */
animation-duration: 60s;
/* 秒针在分针之上 */
z-index: 99;
}
.minute {
/* 30% 的长度加上指针尾部的长度 */
height: calc(30% + var(--out-len));
background-color: teal;
position: absolute;
/* 每圈 3600 秒 */
animation-duration: 3600s;
z-index: 0;
}
@keyframes effect {
to {
transform: rotate(360deg);
}
}
</style> $$
$$answer
<div class="dial">
<div class="second pointer"></div>
<div class="minute pointer"></div>
</div>
<style>
.dial {
width: 200px;
height: 200px;
border-radius: 50%;
border: 10px solid black;
position: relative;
}
.pointer {
/* 指针尾部多余的长度 */
--out-len: 20px;
/* 指针的宽度 */
width: 10px;
position: absolute;
left: 0;
right: 0;
margin: auto;
bottom: calc(50% - var(--out-len));
/* 旋转的原点: x 为中心, y 为元素的长度减去尾部的长度 */
transform-origin: center calc(100% - var(--out-len));
animation-name: effect;
/* 线性播放动画效果 */
animation-timing-function: linear;
/* 无限循环 */
animation-iteration-count: infinite;
}
.second {
/* 45% 的长度加上指针尾部的长度 */
height: calc(45% + var(--out-len));
background-color: red;
/* 每圈 60 秒 */
animation-duration: 60s;
/* 秒针在分针之上 */
z-index: 99;
}
.minute {
/* 30% 的长度加上指针尾部的长度 */
height: calc(30% + var(--out-len));
background-color: teal;
position: absolute;
/* 每圈 3600 秒 */
animation-duration: 3600s;
z-index: 0;
}
@keyframes effect {
to {
transform: rotate(360deg);
}
}
</style>
$$