js 动画
# js 动画
# setTimeout
setTimeout() :在指定的毫秒数后调用函数或计算表达式。
# setInterval
setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式。方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。
# setInterval 缺点
setInterval 对自己调用的代码是否报错漠不关心。即使调用的代码报错了,它依然会持续的调用下去
setInterval 无视网络延迟。在使用 ajax 轮询服务器是否有新数据时,必定会有一些人会使用 setInterval,然而无论网络状况如何,它都会去一遍又一遍的发送请求,如果网络状况不良,一个请求发出,还没有返回结果,它会坚持不懈的继续发送请求,最后导致的结果就是请求堆积。
setInterval 并不定时。如果它调用的代码执行的时间小于定时的时间,它会跳过调用,这就导致无法按照你需要的执行次数或无法得到你想要的结果。
原因:每个 setTimeout 产生的任务会直接 push 到任务队列中;而 setInterval 在每次把任务 push 到任务队列前,都要进行一下判断(看上次的任务是否仍在队列中,如果有则不添加,没有则添加)。
解决方案:使用 setTimeout 代替 setInterval。可以给 setTimeout 设置时间后,在最后调用自身
setTimeout 和 setInterval 的源代码是在哪里实现的?
你的答案可能会是 V8(或其他 VM),但很遗憾,这是错的。尽管 “JavaScript Timers” 的应用很广泛,但是 setTimeout 和 setInterval 之类的函数并不是 ECMAScript 规范或任何一种 JavaScript 引擎实现的一部分。Timer 函数是由浏览器实现的,不同浏览器的实现方式会有所不同。同时 Timer 也是由 Node.js 运行时本身实现的。
在浏览器中,主要的计时器函数是 Window 接口的一部分,这个接口还有一些其他函数和对象。该接口使其所有元素在主 JavaScript 作用域内全局可用。这就是为什么你可以直接在浏览器的控制台中执行 setTimeout 的原因。
在 Node 中,计时器是 global 对象的一部分,该对象的行为类似于浏览器的 window 。你可以在 Node 的源代码中找到它的实现。
# requestAnimationFrame
window 对象的一个方法,window.requestAnimationFrame
requestAnimationFrame 既不是宏任务,又不是微任务
动画的实现:
javaScript 中可以通过定时器 setTimeout 来实现,
css3 可以使用 transition 和 animation 来实现,
html5 中的 canvas 也可以实现。
除此之外,html5 还提供一个专门用于请求动画的 API,即 requestAnimationFrame
# 作用
能保证回调函数在屏幕每一次的刷新间隔中只被执行一次
按帧对网页进行重绘。该方法告诉浏览器希望执行动画并请求浏览器在下一次重绘之前调用回调函数来更新动画
由系统来决定回调函数的执行时机,在运行时浏览器会自动优化方法的调用
显示器有固定的刷新频率(60Hz 或 75Hz),也就是说,每秒最多只能重绘 60 次或 75 次,requestAnimationFrame 的基本思想让页面重绘的频率与这个刷新频率保持同步 比如显示器屏幕刷新率为 60Hz,使用 requestAnimationFrame API,那么回调函数就每 1000ms / 60 ≈ 16.7ms 执行一次;如果显示器屏幕的刷新率为 75Hz,那么回调函数就每 1000ms / 75 ≈ 13.3ms 执行一次。
通过 requestAnimationFrame 调用回调函数引起的页面重绘或回流的时间间隔和显示器的刷新时间间隔相同。所以 requestAnimationFrame 不需要像 setTimeout 那样传递时间间隔,而是浏览器通过系统获取并使用显示器刷新频率 比如一个动画,宽度从 0px 加一递增到 100px。无缓动效果的情况下,浏览器重绘一次,宽度就加 1。
# 应用场景 1. 进度条
function loadingBar(ele) {
// 使用闭包保存定时器的编号
let handle;
return () => {
// 每次触发将进度清空
ele.style.width = "0";
// 开始动画前清除上一次的动画定时器
// 否则会开启多个定时器
cancelAnimationFrame(handle);
// 回调函数
let _progress = () => {
let eleWidth = parseInt(ele.style.width);
if (eleWidth < 200) {
ele.style.width = `${eleWidth + 5}px`;
handle = requestAnimationFrame(_progress);
} else {
cancelAnimationFrame(handle);
}
};
handle = requestAnimationFrame(_progress);
};
}
var loadingDom = document.getElementById("loading");
loadingBar(loadingDom)();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 经典面试题:如何渲染几万条数据并不卡住界面
var total = 100000;
var size = 100;
var count = total / size;
var done = 0;
var ul = document.getElementById("list");
function addItems() {
var li = null;
var fg = document.createDocumentFragment();
for (var i = 0; i < size; i++) {
li = document.createElement("li");
li.innerText = "item " + (done * size + i);
fg.appendChild(li);
}
ul.appendChild(fg);
done++;
if (done < count) {
requestAnimationFrame(addItems);
}
}
requestAnimationFrame(addItems);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# js 动画问题
# css 动画和 js 动画的区别
- 复杂度不同
css 动画相对简单,js 动画相对复杂
- 兼容性不同
CSS 动画 有兼容性问题,而 JS 大多时候没有兼容性问题
- 灵活性不同
CSS 在动画控制上不够灵活,JavaScript 动画控制能力很强,可以在动画播放过程中对动画进行控制:开始、暂停、回放、终止、取消都是可以做到的。
- 性能不同
css 动画相对于优一些,css 动画通过 GUI 解析,js 动画需要经过 j s 引擎代码解析,然后再进行 GUI 解析渲染。
- 适用场景不同
对于一些复杂控制的动画,使用 javascript 会比较靠谱。而在实现一些小的交互动效的时候,就多考虑考虑 CSS 吧