1. 前言
随着移动互联网的发展,用户对于网页的要求越来越高。在过去的几年中,前端开发人员们不断地探索实现炫酷的转场动画的方式,从而提升用户体验。而利用CSS实现转场动画,成为了一种非常流行的方式。
2. CSS动画基础
在进行CSS转场动画之前,我们需要先掌握CSS动画的基础。CSS3中提供了4种创建动画的方式:transition、animation、@keyframes和transform。在本文中,我们将使用前两种方式,分别利用transition
和animation
实现不同的转场动画。
2.1 transition实现动画
transition
是一种可以让元素在多个状态之间进行转换的CSS属性。通过定义元素属性的起始状态和结束状态,transition
可以让我们控制元素如何变化。
下面是一个使用transition
实现的简单动画效果:
.box {
width: 100px;
height: 100px;
background: red;
transition: width 2s;
}
.box:hover {
width: 200px;
}
这段代码的效果是,当鼠标移动到红色的方形元素上时,width
属性的值由初始值100px
变成结束值200px
,并且这个变化过程持续2秒钟。
2.2 animation实现动画
与transition
不同的是,animation
属性允许我们定义一个由多个关键帧组成的动画序列,这些关键帧描述了元素在整个动画中的不同状态。在使用animation
时,我们需要通过@keyframes
规则来定义动画的关键帧。
下面是一个使用animation
实现的简单动画效果:
.box {
width: 100px;
height: 100px;
background: red;
animation: mymove 2s infinite;
}
@keyframes mymove {
0% {transform: translate(0, 0);}
50% {transform: translate(50px, 50px);}
100% {transform: translate(0, 0);}
}
这段代码的效果是,元素在2秒钟内沿着横向和纵向分别移动了50像素的距离,并且在动画结束时回到了初始位置。由于指定了infinite
属性,所以这个动画会一直循环播放。
3. 利用transition实现转场动画
了解了transition
的基本用法,下面我们来看如何利用它来实现转场动画效果。由于每个元素都可以应用transition
属性,我们可以利用这个特性来创建从一个页面到另一个页面之间的过渡效果。是的,你可以在两个页面之间创建动画转场效果,不必借助于JavaScript!
在下面的例子中,我们将实现一个从一个页面到另一个页面的转场动画效果。当点击按钮时,原始页面变得模糊并暗淡,以模仿深度模糊效果,然后新页面会在 1 秒钟内淡入,覆盖在底层页面上。
注意,在下面的转场中,第一页和第二页的页面布局和样式都相同,不同之处只是内容的不同。这是一种常见的转场方式,可以最大程度保持用户对页面的熟悉感,并减少页面过渡带来的注意力分散。
<body>
<div class='container'>
<div class='page page1'>
<h1>Page 1</h1>
<button>Click me</button>
</div>
<div class='page page2'>
<h1>Page 2</h1>
<button>Back</button>
</div>
</div>
</body>
接下来,我们需要为两个页面添加样式,并且定义transition
属性。在第一页中,我们将定义一个包含filter
属性的类,当用户点击按钮时,filter
属性将变得更加模糊并暗淡。同时,我们还使用opacity
属性来实现淡出的效果。在第二页中,我们将定义一个opacity
属性,使得第二页能够在模糊的底层页面上淡入。
.container {
height: 100%;
width: 100%;
overflow: hidden;
}
.page {
height: 100%;
width: 100%;
position: relative;
z-index: 0;
transition: opacity 1s, z-index 0s 1s;
}
.page1 {
background: #f2f2f2;
}
.page2 {
background: #cbcbcb;
opacity: 0;
z-index: -1;
}
.blur {
filter: blur(5px);
opacity: 0.5;
}
最后,我们需要添加一些JavaScript代码,以便在用户点击转场按钮时切换页面。代码非常简单,只需要在按钮的 click 事件中切换两个页面的样式即可。页面一开始处于激活状态,而页面二则处于非激活状态。当用户点击按钮时,当前激活状态的页面会添加模糊类'blur'
,同时将第二页的z-index
值设置为1
,使得第二页能够覆盖在底层页面上。在转场动画结束时,我们将第一页的z-index
值设置为-1
,使得页面能够被完全隐藏。这时,只有第二页才能够被用户看到。
let button = document.querySelector('button')
let page1 = document.querySelector('.page1')
let page2 = document.querySelector('.page2')
button.addEventListener('click', () => {
page1.classList.add('blur')
page2.classList.add('fade-in')
setTimeout(() => {
page1.classList.remove('blur')
page1.style.zIndex = -1
page2.style.zIndex = 0
page2.classList.remove('fade-in')
}, 1000)
})
以上就是利用transition
属性和JavaScript实现转场动画的完整示例。这个示例只是一个简单的展示,你可以根据自己的需求进行改进或优化。
4. 利用animation实现转场动画
我们已经展示了利用transition
属性实现转场动画的方式,那么现在我们来看一下如何利用animation
属性实现转场动画。
在下面的例子中,我们将创建一个5个任务列表之间的切换动画效果。任务列表是一个垂直排列的列表,每个列表项包含一个代表任务名称的文本和一个代表任务完成度的进度条。当点击任务列表时,进度条会按照一个特定的动画效果显示,同时列表会淡出并消失,下一个列表会淡入并居中显示。
<body>
<div class='container'>
<ul class='task-list'>
<div class='task'>
<h2>Task 1</h2>
<div class='progress-bar' style='width: 80%;'></div>
</div>
<div class='task'>
<h2>Task 2</h2>
<div class='progress-bar' style='width: 60%;'></div>
</div>
<div class='task'>
<h2>Task 3</h2>
<div class='progress-bar' style='width: 40%;'></div>
</div>
<div class='task'>
<h2>Task 4</h2>
<div class='progress-bar' style='width: 20%;'></div>
</div>
<div class='task'>
<h2>Task 5</h2>
<div class='progress-bar' style='width: 10%;'></div>
</div>
</div>
</body>
接下来,我们需要为每个任务列表项添加样式,并且定义animation
属性。我们使用transform
属性来实现从固定的顶部位置到可变的中心位置的动画效果。progress-bar的width
属性用来表示任务完成的进度。
.container {
height: 100%;
width: 100%;
overflow: hidden;
}
.task-list {
padding: 0;
margin: 0;
list-style: none;
height: calc(100vh - 100px);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.task-list li {
opacity: 1;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: calc(100vh - 100px);
display: flex;
align-items: center;
justify-content: center;
transform: translateY(-100%);
animation: slide-up 1s forwards;
}
.task-list .selected {
z-index: 1;
}
.task {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 20px;
}
.progress-bar {
height: 10px;
max-width: 100%;
width: 0;
background: lightgrey;
margin-left: 20px;
}
.task:nth-child(1) .progress-bar {
background: #5dc8b7;
}
.task:nth-child(2) .progress-bar {
background: #7f7f7f;
}
.task:nth-child(3) .progress-bar {
background: #ffd75f;
}
.task:nth-child(4) .progress-bar {
background: #f8961e;
}
.task:nth-child(5) .progress-bar {
background: #f94144;
}
@keyframes slide-up {
0% {transform: translateY(0);}
50% {opacity: 1;}
100% {
transform: translateY(0);
opacity: 1;
}
}
@keyframes slide-down {
0% {
transform: translateX(0);
opacity: 1;
}
100% {
transform: translateX(-200%);
opacity: 0;
}
}
@keyframes slide-up-and-center {
0% {transform: translateY(-100%);}
100% {transform: translateY(0);}
}
.pulse {
animation: pulse 1s infinite alternate;
}
@keyframes pulse {
0% {transform: scale(1);}
100% {transform: scale(1.2);}
}
最后,我们需要为每个任务列表项添加事件监听器。当用户点击任务列表项时,animation
属性将开始工作。当前选定的任务列表项将运用slide-down
效果淡出,同时下一个任务列表将运用slide-up-and-center
效果淡入。此外,我们还需要对进度条添加一个pulse类,以产生脉冲效果。
let taskList = document.querySelector('.task-list')
let tasks = taskList.querySelectorAll('.task')
let previousTask = tasks[0]
tasks.forEach(task => {
task.addEventListener('click', () => {
// remove previous classes
previousTask.classList.remove('selected', 'pulse')
task.classList.add('selected', 'pulse')
previousTask.querySelector('.progress-bar').style.width = '0'
// animate previous task
previousTask.addEventListener('animationend', () => {
previousTask.classList.remove('selected')
previousTask.style.animationName = 'none'
previousTask.style.opacity = 1
previousTask.style.transform = 'translateY(-100%)'
previousTask.querySelector('.progress-bar').style.width = '0'
})
previousTask.style.animationName = 'slide-down'
// animate current task
task.style.animationName = 'slide-up-and-center'
previousTask = task
task.querySelector('.progress-bar').style.width = task.querySelector('.progress-bar').getAttribute('style').split(':')[1].trim()
})
})
在上面的代码中,我们定义了一个previousTask
变量,以便我们在切换任务时知道哪些任务是已完成过的。我们利用previousTask
来保持当前选择的任务,直到用户选择另一个任务。我们还使用querySelectorAll('
)方法来获取所有的任务列表项,并为每个任务列表项添加click事件监听器。当用户点击某个任务时,我们将从previousTask
变量中删除之前的'selected'
类,并将当前任务添加到'selected'
类中。然后,我们将为之前的任务和当前任务添加动画效果。在切换任务动画结束后,我们从前一个任务的animationName
和opacity
属性中删除之前设置的值,这样就能让它们重新定位到原始状态上。在我们为前一个任务执行淡出效果的同时,我们将前一个任务的'pulse'
类删除,并将前一个任务的进度条宽度重置为0。我们还需要为以前的任务和当前任务分别设置适当的animationName
属性。
总结
通过学习本文中的内容,我们了解了如何利用transition
和animation
属性实现炫酷转场动画。我们讲解了两个不同的案例,通过这些案例,我们掌握了这两种属性的基本用法以及常见的应用场景。最后,我们还详细介绍了每个案例中使用的@keyframes
规则和JavaScript部分的实现。
利用CSS作为转场动画的实现方式,相比于使用JavaScript,更加的灵活、安全和可靠。因此,学会CSS转场动画