简单介绍 CSS 动画
简单讲,CSS 动画是用于实现元素从一个 CSS 样式配置转换到另一个 CSS 样式配置的呈现效果。
CSS 动画的作用
CSS 动画语法介绍
动画语法包括两个部分:
/* 指定动画的样式规则 */
.div {
width: 200px;
height: 200px;
animation: change 3s;
}
/* 指定动画开始、结束点样式的关键帧。 */
@keyframes change {
0% {
background-color: #f00;
}
100% {
background-color: #fff;
}
}
结合上例,对一个元素创建动画,需要在元素的 CSS 选择器上使用animation
属性或其子属性来配置动画时长、动画呈现方式及其他动画运行时相关参数,而动画在不同时间点的关键帧的表现样式则需要通过@keyframes
来配置。
CSS 动画属性
animation–name
指定由 @keyframes 定义动画名称标识,多个使用逗号隔开。
animation–duration
设置动画一个周期的时长,值必须为正数或 0,单位:秒(s)或毫秒(ms)。
示例:说明:本文示例代码由 vue3 + element-plus 构建
<template>
<el-card header="animation-duration">
<div class="ani-box slow" :class="{ running: playState }">
<div>10s</div>
</div>
<div class="ani-box fast" :class="{ running: playState }">
<div>3s</div>
</div>
<el-button type="primary" @click="handleAnimationRunning"
>播放动画</el-button
>
</el-card>
</template>
<style scoped>
.ani-box {
width: 80px;
height: 80px;
background-color: darkcyan;
border-radius: 40px;
animation-name: move;
animation-fill-mode: forwards;
animation-play-state: paused;
text-align: center;
line-height: 80px;
color: wheat;
font-size: 20px;
margin-bottom: 20px;
}
.ani-box.slow {
animation-duration: 10s;
}
.ani-box.fast {
animation-duration: 3s;
}
.ani-box.running {
animation-play-state: running;
}
@keyframes move {
0% {
transform: translateX(0px);
}
100% {
transform: translateX(500px);
}
}
</style>
<script setup>
import { ref } from "vue";
const playState = ref(false);
const handleAnimationRunning = () => {
playState.value = true;
};
</script>
animation-delay
设置延时,指定从应用动画到元素开始执行之前等待的时间,值可以是负值,单位:秒(s)或毫秒(ms)。
<template>
<el-card header="animation-delay">
<div class="ani-box default" :class="{ running: playState }">
<div>0s</div>
</div>
<div class="ani-box positive" :class="{ running: playState }">
<div>5s</div>
</div>
<div class="ani-box negative" :class="{ running: playState }">
<div>-5s</div>
</div>
<el-button type="primary" @click="handleAnimationRunning"
>播放动画</el-button
>
</el-card>
</template>
<style scoped>
.ani-box {
width: 80px;
height: 80px;
background-color: darkcyan;
border-radius: 40px;
text-align: center;
line-height: 80px;
color: wheat;
font-size: 20px;
margin-bottom: 20px;
animation-name: move;
animation-fill-mode: forwards;
animation-play-state: paused;
animation-duration: 10s;
animation-timing-function: linear;
}
.ani-box.default {
animation-delay: 0s;
}
.ani-box.positive {
animation-delay: 5s;
}
.ani-box.negative {
animation-delay: -5s;
}
.ani-box.running {
animation-play-state: running;
}
@keyframes move {
0% {
transform: translateX(0px);
}
100% {
transform: translateX(500px);
}
}
</style>
<script setup>
import { ref } from "vue";
const playState = ref(false);
const handleAnimationRunning = () => {
playState.value = true;
};
</script>
animation-direction
设置动画是正向播放、反向播放、还是在正向和反向之间交替播放。可选值:
- normal:动画在每个循环中正向播放。即每次动画循环时,动画将重置为起始状态并重新开始。默认值。
- reverse:动画在每个循环中反向播放。即每次动画循环时,动画将重置为结束状态并重新开始。
- alternate:动画在每个循环中正反交替播放,第一次是正向播放。
- alternate-rever:动画在每个循环中正反交替播放,第一次是反向播放。
示例代码:
<template>
<el-card header="animation-direction">
<div class="ani-box normal" :class="{ running: playState }">
<div>normal</div>
</div>
<div class="ani-box reverse" :class="{ running: playState }">
<div>reverse</div>
</div>
<div class="ani-box alternate" :class="{ running: playState }">
<div>alternate</div>
</div>
<div class="ani-box alternate-reverse" :class="{ running: playState }">
<div>alternate-reverse</div>
</div>
<el-button type="primary" @click="handleAnimationRunning"
>播放动画</el-button
>
</el-card>
</template>
<style scoped>
.ani-box {
width: 80px;
height: 80px;
background-color: darkcyan;
border-radius: 40px;
text-align: center;
line-height: 1;
display: flex;
align-items: center;
justify-content: center;
color: wheat;
font-size: 16px;
margin-bottom: 20px;
animation-name: move;
animation-fill-mode: forwards;
animation-play-state: paused;
animation-duration: 2s;
animation-timing-function: linear;
animation-iteration-count: 4;
}
.ani-box.normal {
animation-direction: normal;
}
.ani-box.reverse {
animation-direction: reverse;
}
.ani-box.alternate {
animation-direction: alternate;
}
.ani-box.alternate-reverse {
animation-direction: alternate-reverse;
}
.ani-box.running {
animation-play-state: running;
}
@keyframes move {
0% {
transform: translateX(0px);
}
100% {
transform: translateX(500px);
}
}
</style>
<script setup>
import { ref } from "vue";
const playState = ref(false);
const handleAnimationRunning = () => {
playState.value = true;
};
</script>
animation-iteration-count
设置动画在停止前应播放的次数。可选值:
示例代码:
<template>
<el-card header="animation-iteration-count">
<div class="ani-box half" :class="{ running: playState }">
<div>0.5次</div>
</div>
<div class="ani-box once" :class="{ running: playState }">
<div>1次</div>
</div>
<div class="ani-box twice" :class="{ running: playState }">
<div>2次</div>
</div>
<el-button type="primary" @click="handleAnimationRunning"
>播放动画</el-button
>
</el-card>
</template>
<style scoped>
.ani-box {
width: 80px;
height: 80px;
background-color: darkcyan;
border-radius: 40px;
text-align: center;
line-height: 80px;
color: wheat;
font-size: 20px;
margin-bottom: 20px;
animation-name: move;
animation-fill-mode: forwards;
animation-play-state: paused;
animation-duration: 6s;
animation-timing-function: linear;
}
.ani-box.half {
animation-iteration-count: 0.5;
}
.ani-box.once {
animation-iteration-count: 1;
}
.ani-box.twice {
animation-iteration-count: 2;
}
.ani-box.running {
animation-play-state: running;
}
@keyframes move {
0% {
transform: translateX(0px);
}
100% {
transform: translateX(500px);
}
}
</style>
<script setup>
import { ref } from "vue";
const playState = ref(false);
const handleAnimationRunning = () => {
playState.value = true;
};
</script>
animation-play-state
示例代码:
<template>
<el-card header="animation-play-state">
<div class="ani-box running">51BLOG</div>
<el-alert
title="鼠标悬浮时运行动画,离开时暂停动画。"
:closable="false"
show-icon
type="warning"
></el-alert>
</el-card>
</template>
<style lang="scss" scoped>
.ani-box {
width: 80px;
height: 80px;
background-color: darkcyan;
border-radius: 4px;
text-align: center;
line-height: 80px;
color: wheat;
font-size: 16px;
text-shadow: 1px 2px 1px red;
margin-bottom: 30px;
cursor: pointer;
animation-name: move;
animation-fill-mode: forwards;
animation-play-state: paused;
animation-duration: 5s;
animation-timing-function: linear;
}
.ani-box:hover {
animation-play-state: running;
}
@keyframes move {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
</style>
运行结果:
animation-timing-function
- 关键字值
- ease 默认值,表示动画在中间加速,在结束时减速。等同于
cubic-bezier(0.25, 0.1, 0.25, 1.0)
- ease-in 表示动画一开始较慢,随着动画属性的变化逐渐加快,直至完成。等同于
cubic-bezier(0.42, 0, 1.0, 1.0)
- ease-out 表示动画一开始较快,随着动画的进行逐渐减速。等同于
cubic_bezier(0, 0, 0.58, 1.0)
- ease-in-out 表示动画一开始缓慢变化,随后加速变化,最后再次减速变化。等同于
cubic_bezier(0.42, 0, 0.58, 1.0)
- linear 表示动画以匀速运动。等同于
cubic-bezier(0.0, 0.0, 1.0, 1.0)
- step–start 等同于
steps(1, jump-start)
- step–end 等同于
steps(1, jump-end)
ease、ease-in、ease-out、ease-in-out、linear 称之为非阶跃(non–step)关键字值,代表了固定的四点值的三次贝塞尔曲线
- ease 默认值,表示动画在中间加速,在结束时减速。等同于
示例代码:
<template>
<el-card header="animation-timing-function: ease">
<div class="ani-box ease" :class="{ running: playState }">
<div>ease</div>
</div>
<div class="ani-box ease-in" :class="{ running: playState }">
<div>ease-in</div>
</div>
<div class="ani-box ease-out" :class="{ running: playState }">
<div>ease-out</div>
</div>
<div class="ani-box ease-in-out" :class="{ running: playState }">
<div>ease-in-out</div>
</div>
<div class="ani-box linear" :class="{ running: playState }">
<div>linear</div>
</div>
<div class="ani-box cubic-bezier" :class="{ running: playState }">
<div>cubic-bezier</div>
</div>
<el-button type="primary" @click="handleAnimationRunning"
>播放动画</el-button
>
</el-card>
</template>
<style scoped>
.ani-box {
width: 80px;
height: 80px;
background-color: darkcyan;
border-radius: 40px;
text-align: center;
line-height: 1;
display: flex;
justify-content: center;
align-items: center;
color: wheat;
font-size: 16px;
margin-bottom: 20px;
animation-name: move;
animation-fill-mode: forwards;
animation-play-state: paused;
animation-duration: 10s;
animation-timing-function: linear;
}
.ani-box.ease {
animation-timing-function: ease;
}
.ani-box.ease-in {
animation-timing-function: ease-in;
}
.ani-box.ease-out {
animation-timing-function: ease-out;
}
.ani-box.ease-in-out {
animation-timing-function: ease-in-out;
}
.ani-box.linear {
animation-timing-function: linear;
}
.ani-box.cubic-bezier {
animation-timing-function: cubic-bezier(0.19, 1, 0.86, 0.01);
}
.ani-box.running {
animation-play-state: running;
}
@keyframes move {
0% {
transform: translateX(0px);
}
100% {
transform: translateX(800px);
}
}
</style>
<script setup>
import { ref } from "vue";
const playState = ref(false);
const handleAnimationRunning = () => {
playState.value = true;
};
</script>
运行结果:
- 函数值
- Step 函数关键字,语法:
steps(n, <jumpterm>)
语法解析:按照 n 个定格在过渡中显示动画迭代,每个定格等长时间显示。
例如:如果 n 为 5,则有 5 个步骤。
动画是否在 0%、20%、40%、60%、80%处,或 20%、40%、60%、80%、100%处暂停,或动画在 0%和 100%之间的 5 个定格,又或者在包括 0%和 100%的情况下设置 5 个定格(0%、25%、50%、75%、100%处),取决于 jumpterm 的值:
<template>
<el-card header="animation-timing-function: steps(n, <jumpterm>)">
<div class="ani-box jump-start" :class="{ running: playState }">
<div>jump-start</div>
</div>
<div class="ani-box jump-end" :class="{ running: playState }">
<div>jump-end</div>
</div>
<div class="ani-box jump-none" :class="{ running: playState }">
<div>jump-none</div>
</div>
<div class="ani-box jump-both" :class="{ running: playState }">
<div>jump-both</div>
</div>
<el-button type="primary" @click="handleAnimationRunning"
>播放动画</el-button
>
</el-card>
</template>
<style scoped>
.ani-box {
width: 80px;
height: 80px;
background-color: darkcyan;
border-radius: 40px;
text-align: center;
line-height: 1;
display: flex;
justify-content: center;
align-items: center;
color: wheat;
font-size: 16px;
margin-bottom: 20px;
animation-name: move;
animation-fill-mode: none;
animation-play-state: paused;
animation-duration: 10s;
}
.ani-box.jump-start {
animation-timing-function: steps(5, jump-start);
}
.ani-box.jump-end {
animation-timing-function: steps(5, jump-end);
}
.ani-box.jump-none {
animation-timing-function: steps(5, jump-none);
}
.ani-box.jump-both {
animation-timing-function: steps(5, jump-both);
}
.ani-box.running {
animation-play-state: running;
}
@keyframes move {
0% {
transform: translateX(0px);
}
100% {
transform: translateX(800px);
}
}
</style>
<script setup>
import { ref } from "vue";
const playState = ref(false);
const handleAnimationRunning = () => {
playState.value = true;
};
</script>
运行结果:
animation-fill-mode
- none 当未执行动画时,动画将不会将任何样式应用于目标,而是以已经赋予该元素的样式来显示。这是默认值。
- forward 动画执行完之后,目标将保留由执行遇到的最后一个关键帧计算值,最后一个关键帧取决于 animation-direction 和 animation-iteration-count 的值。
- backwards 动画将在应用于目标时(执行前)立即应用第一个关键帧中定义的值,并在 animation-delay 期间保留此值。第一个关键帧取决于 animation-direction 的值。
- both 动画将遵循 forwards 和 backwards 的规则,从而在两个方向上扩展动画属性。
示例代码:
<template>
<el-card header="animation-fill-mode">
<div class="ani-box none" :class="{ running: playState }">
<div>none</div>
</div>
<div class="ani-box forwards" :class="{ running: playState }">
<div>forwards</div>
</div>
<div class="ani-box backwords" :class="{ running: playState }">
<div>backwards</div>
</div>
<div class="ani-box both" :class="{ running: playState }">
<div>both</div>
</div>
<el-button type="primary" @click="handleAnimationRunning"
>播放动画</el-button
>
</el-card>
</template>
<style scoped>
.ani-box {
width: 80px;
height: 80px;
background-color: darkcyan;
border-radius: 40px;
text-align: center;
line-height: 80px;
color: wheat;
font-size: 16px;
margin-bottom: 20px;
animation-name: move;
animation-play-state: paused;
animation-duration: 5s;
animation-timing-function: linear;
animation-delay: 1s;
}
.ani-box.none {
animation-fill-mode: none;
}
.ani-box.forwards {
animation-fill-mode: forwards;
}
.ani-box.backwords {
animation-fill-mode: backwards;
}
.ani-box.both {
animation-fill-mode: both;
}
.ani-box.running {
animation-play-state: running;
}
@keyframes move {
0% {
transform: translateX(200px);
}
100% {
transform: translateX(500px);
}
}
</style>
<script setup>
import { ref } from "vue";
const playState = ref(false);
const handleAnimationRunning = () => {
playState.value = true;
};
</script>
运行结果:
animation
animation 是上面这些属性的一个简写属性形式。后续会单独写篇文章来详细介绍。
原文地址:https://blog.csdn.net/assokoo123/article/details/131693081
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_7421.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!