版权声明:哼!坏人!这是我辛辛苦苦码的! https://blog.csdn.net/DurianPudding/article/details/87937938
三种方式
setTimeout
setInterval
requestAnimationFrame
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#myDiv {
background: yellowgreen;
height: 100px;
width: 100px;
}
</style>
</head>
<body>
<h1>JS实现动画</h1>
<pre>基础:<a href="https://juejin.im/post/59e85eebf265da430d571f89" target="_blank">js执行机制</a></pre>
<h2>1.setTimeout</h2>
<p>例子一:设置x秒后显示</p>
<button id="my-btn">点我</button>
<p id="message" style="display: none">啊!我显示了!</p>
<p>例子二:重复调用setTimeout实现向右推动</p>
<div id="myDiv" style="left: 1px; position: relative;"></div>
<pre>js在JavaScript中,通过document.getElementById(id).style.XXX可以获取到XXX的值,
但意外的是这样做只能取到通过 内嵌方式 设置的样式值,即style属性里面设置的值。</pre>
<p>例子三(打开控制台查看)</p>
<h2>2.setInternal</h2>
<p>定义:将定时器代码规则的插入队列中。</p>
<p>规则:仅当没有setInterval的任何其他代码实例时,才将定时器代码添加到队列中。</p>
<pre>即:当定时器代码要插入队列时,已经有一个定时器代码 正在运行,并且有一个 定时器实例 在等待,则此处不插入,跳过。</pre>
<p>缺点:1.某些间隔会被跳过 2.多个定时器的代码执行之间的间隔可能比预期的小。</p>
<p>解决:使用链式setTimeout,见例二</p>
<h2>3.requestAnimationFrame</h2>
<pre>参考:<a href="https://www.cnblogs.com/xiaohuochai/p/5777186.html" target="_blank"></a></pre>
<p>最大区别:采用系统时间间隔,最佳绘制。使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。</p>
<pre>
【1】requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率
【2】在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量
【3】requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销
</pre>
<script>
// setTimeout 1.
var btn = document.getElementById("my-btn");
btn.onclick = function(){ // 给一个按钮设置了一个事件处理程序
setTimeout(function () { // 事件处理程序设置了一个250ms后调用的定时器
// 对setTimeout的调用表示要晚点执行某些代码
document.getElementById("message").style.display = "block";
}, 250); // 重要!!!此处的时间间隔表示何时将定时器的代码添加到队列,而不是何时实际执行代码!
};
// setTimeout 2.
setTimeout(function(){
var div = document.getElementById("myDiv");
left = parseInt(div.style.left) + 1;
div.style.left = left + "px";
if (left < 200){
// 链式setTimeout,解决setInterval忽略时间间隔的问题
setTimeout(arguments.callee, 15);
}
}, 15);
//setTimeout 3:先输出0 后输出2
var Timer = setTimeout(function(){
console.log(Timer);
}, 1000);
console.log(0);
// requestAnimationFrame 1:先输出1,后输出0
// requestID = requestAnimationFrame(callback);
// requestAnimationFrame使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。
// 它返回一个整数,表示定时器的编号,这个值可以传递给cancelAnimationFrame用于取消这个函数的执行
var timer = requestAnimationFrame(function() {
console.log(0); // 0
});
console.log(timer); // 1
// cancelAnimationFrame方法用于取消定时器
var timer = requestAnimationFrame(function(){
console.log(0);
});
cancelAnimationFrame(timer);
// 也可以直接使用返回值进行取消
var timer = requestAnimationFrame(function(){
console.log(0);
});
cancelAnimationFrame(1);
</script>
</body>
</html>
下面是三种方法的实例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>进度条-setInterval</title>
</head>
<body>
<div id="myDiv" style="background-color: lightblue;width: 0;height: 20px;line-height: 20px;">0%</div>
<button id="btn">run</button>
<script>
var timer;
btn.onclick = function(){
// 取消对应的定时器,注意与clearTimeout不一样
clearInterval(timer);
// 注意是字符串,给parseInt用
myDiv.style.width = '0';
timer = setInterval(function(){
// parseInt解析一个字符串,返回一个整数
if(parseInt(myDiv.style.width) < 500){
myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px';
// 总长500,除以5的数字正好是百分比
myDiv.innerHTML = parseInt(myDiv.style.width)/5 + '%';
}else{
clearInterval(timer);
}
},16);
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>setTimeout-进度条</title>
</head>
<body>
<div id="myDiv" style="background-color: lightblue;width: 0;height: 20px;line-height: 20px;">0%</div>
<button id="btn">run</button>
<script>
var timer;
btn.onclick = function() {
// 注意与clearInterval不一样
clearTimeout(timer);
myDiv.style.width = '0';
// 给function取个名字后面链式用
timer = setTimeout(function fn(){
if(parseInt(myDiv.style.width) < 500) {
myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px';
myDiv.innerHTML = parseInt(myDiv.style.width)/5 + '%';
// 链式setTimeout
timer = setTimeout(fn,16);
} else {
clearTimeout(timer);
}
},16)
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>requestAnimationFrame-进度条</title>
</head>
<body>
<div id="myDiv" style="background-color: lightblue;width: 0;height: 20px;line-height: 20px;">0%</div>
<button id="btn">run</button>
<script>
var timer;
btn.onclick = function(){
// 注意cancelAnimationFrame
cancelAnimationFrame(timer);
myDiv.style.width = '0';
timer = requestAnimationFrame(function fn(){
if(parseInt(myDiv.style.width) < 500) {
myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px';
myDiv.innerHTML = parseInt(myDiv.style.width)/5 + '%';
// requestAnimationFrame只传入一个参数
timer = requestAnimationFrame(fn);
} else {
cancelAnimationFrame(timer);
}
}) // 只传入一个参数
}
</script>
</body>
</html>