网页动画初探(一)

其实这是两个月以前折腾的玩意儿。这阵子忙着找实习没空写博文,现在算是尘埃落定了。

本文的灵感来自汇智网的相关js动画课程,动画所依赖的页面也是从相关课程里摘出来的。如果侵权请告知。

我们要写的动画是一个隐藏的菜单,点击屏幕边缘露出的按钮,菜单就会拉出。再次点击则收回。

页面如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE HTML>
<html>
<head>
<style>
*{
margin: 0;
padding: 0;
}
#container{
height: 200px;
width: 200px;
position: relative;
left: -200px;
background-color: #6effcd;
}
#btn{
height: 60px;
width: 30px;
position: absolute;
left: 200px;
top: 75px;
background-color: #73eeff;
}
</style>
</head>
<body>
<div id="container">
<span id="btn"></span>
</div>
</body>
</html>

在很久很久以前,前端是靠setTimeout()setInterval()来实现动画的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
window.onload = function(){
let container = document.getElementById('container');
let btn = document.getElementById('btn');
btn.onclick = function(){
if(container.offsetLeft === 0)
{
moveStart(-200);
}
else{
moveStart(0);
}
};
};
let timer = null;
function moveStart(Target)
{
clearInterval(timer);
timer = setInterval(function(){
let speed=(Target-container.offsetLeft)/5;
speed=speed>0?Math.ceil(speed):Math.floor(speed);
if(container.offsetLeft === Target) {
clearInterval(timer);
}else {
container.style.left =
container.offsetLeft + speed + 'px';
}
},30)
}

后来出现了CSS3动画。它用法简单且功能强大。相同的动画效果可以这样实现:

1
2
3
4
5
6
7
8
9
10
11
@keyframes moveOut {
from {left: -200px;}
to {left: 0;}
}
@keyframes moveBack {
from {left: 0;}
to {left: -200px;}
}
div {
animation: moveOut 3s ease alternate paused forwards;
}

在js里要这样写:

1
2
3
4
5
6
7
8
9
10
11
let btn = document.getElementById('btn');
let container = document.getElementById('container');
btn.onclick = function () {
if(container.offsetLeft === -200) {
container.style.animationName = 'moveOut';
container.style.animationPlayState = 'running';
}else {
container.style.animationName = 'moveBack';
container.style.animationPlayState = 'running';
}
}

是不是明了很多?

除去以上两则,还有一个叫requestAnimationFrame()的东西。它有什么优点呢?可以参看此文:requestAnimationFrame()的意义。简单概括一下,它能解决setTimeout()过度绘制的问题,性能上也特别优化过。而且它的用法和setTimeout()极其相似,不像CSS3动画要另起炉灶。这样能解决浏览器兼容性的问题,还能写出CSS3写不出来的动画。

代码如下。整体结构和setTimeout()的写法差别不大。读者可以试试把前文用setInterval()的写法改写成setTimeout()的写法,再观察一下它们的异同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let container = document.getElementById('container');
let btn = document.getElementById('btn');
btn.onclick = function(){
if(container.offsetLeft === -200)
{
requestAnimationFrame(function () {
move(0);
});
}
else{
requestAnimationFrame(function () {
move(-200);
});
}
};
function move(target) {
if(container.offsetLeft !== target) {
speed = (target - container.offsetLeft)/5;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
container.style.left = container.offsetLeft + speed + 'px';
requestAnimationFrame(function () {
move(target);
});
}
}

除去以上三种,动画还有transitioncanvas的写法。本人写文至此夜已深,颇感困倦,还是以后再叙吧。