动画就用专门的动画库来搞啦!
比如animejs这种。
同时调度多个对象,也无需用到并行这么高大上的概念,只要合理的任务调度就可以了,毕竟对 CPU
主核而言,所谓“并行”无非是对运算资源的调度,JS 作为一门图灵完备的语言,模拟这种任务调度自然不在话下。
追加一个使用 raf 实现的调度器:
const scheduler = (() => {
const taskQueue = [];
const { now } = Date;
const { abs } = Math;
const PRECISION = 16; // 计时器精度
let frame = null;
const raf = () => {
frame = requestAnimationFrame(() => {
const moment = now();
const markAsDelete = [];
for(let index in taskQueue){
const [task, time] = taskQueue[index];
// 需要根据实际需求确定合适的回调执行条件
if(abs(time - moment) < PRECISION){
task();
markAsDelete.push(index);
}
}
// 删除执行过的任务
markAsDelete.reverse().forEach(item => {
taskQueue.splice(item, 1);
});
// 递归执行调度
if(!!taskQueue.length){
raf();
} else {
frame = null;
}
});
}
// 启动调度
raf();
return {
// 这里采用的是类似 setTimeout 的接口设计,
// 但实际应用中可以采用其他形式的接口,配合
// raf 中的判断条件,可以形成更加丰富的调度
// 方案,比如注册速度来达到对速度的控制等
register(task, timeout){
const moment = now();
taskQueue.push([task, timeout + moment]);
if(frame === null){
raf();
}
return this;
}
}
})();
根据你的需求可以这样写:
// 每个任务需要用一个函数启动、一个函数停止
const taskArray = [
{
start: 2,
duration: 4,
startFn: () => {},
stopFn: () => {}
}
// ...
];
taskArray.forEach(item => {
const {start, duration, startFn, stopFn} = item;
scheduler.register(startFn, start * 1000)
.register(stopFn, (start + duration) * 1000);
});
但看起来和用 setTimeout
也差不多。。。
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…