提到动画效果,很多人会想到transition、animation、canvas,亦或者用js实现动画效果
那么requestanimationframe和他们有什么不一样的呢?
transition:过渡,只能控制开始和结束时的动画效果,过程中间是无法干预的,transition并不能实现独立的动画,只能在某个标签元素样式或状态改变时进行平滑的动画效果过渡,而不是马上改变。
animation:真正意义上的CSS3动画。通过对关键帧和循环次数的控制,页面标签元素会根据设定好的样式改变进行平滑过渡。而且关键帧状态的控制是通过百分比来控制的。
canvas:作为H5新增元素,是借助Web API来实现动画的。主要优势是可以应对页面中多个动画元素渲染较慢的情况,完全通过javascript来渲染控制动画的执行。可用于实现较复杂动画。
js:setInterval、setTimeout实现动画通常会导致页面频繁性重排重绘,消耗性能,一般应该在桌面端浏览器。在移动端上使用会有明显的卡顿。而且大部分时候我们都是设置16ms作为动画循环,因为人眼对于即时渲染的画面要达到60hz才觉得流畅,电影的25hz是有动态模糊的,页面是没有的。
requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点:
1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
2,在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
3, requestAnimationFrame也带有停止动画cancelAnimationFrame(rafId)
代码例子
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
<style>
#e{
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;
top: 0;
zoom: 1;
}
</style>
</head>
<body>
<div id="e"></div>
<script>
var e = document.getElementById("e");
var flag = true;
var left = 0;
var rafId = null
function render() {
if(flag == true){
if(left>=100){
flag = false
}
e.style.left = ` ${left++}px`
}else{
if(left<=0){
flag = true
}
e.style.left = ` ${left--}px`
}
}
//requestAnimationFrame效果
(function animloop(time) {
console.log(time,Date.now())
render();
rafId = requestAnimationFrame(animloop);
//如果left等于50 停止动画
if(left == 50){
cancelAnimationFrame(rafId)
}
})();
//setInterval效果
// setInterval(function(){
// render()
// },1000/60)
</script>
</body>
</html>
自定义时间间隔循环执行(
解决方案是 当和服务端通信时 记录下一个时间差,(时间差等于服务端时间-本地时间)不管正负我们只要这个时间差。这样每当我们接受到消息 或者发送消息的时候我们就拿本地时间和是价差相加。这样就可以保证和服务端时间是一致的了,)
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
<style>
#e{
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;
top: 0;
zoom: 1;
}
</style>
</head>
<body>
<div id="e"></div>
<script>
var e = document.getElementById("e");
var flag = true;
var left = 0;
//当前执行时间
var nowTime = 0;
//记录每次动画执行结束的时间
var lastTime = Date.now();
//我们自己定义的动画时间差值
var diffTime = 40;
function render() {
if(flag == true){
if(left>=100){
flag = false
}
e.style.left = ` ${left++}px`
}else{
if(left<=0){
flag = true
}
e.style.left = ` ${left--}px`
}
}
//requestAnimationFrame效果
(function animloop() {
//记录当前时间
nowTime = Date.now()
// 当前时间-上次执行时间如果大于diffTime,那么执行动画,并更新上次执行时间
if(nowTime-lastTime > diffTime){
lastTime = nowTime
render();
}
requestAnimationFrame(animloop);
})()
</script>
</body>
</html>
备注:主要写requestAnimationFrame,后续优化添加其他