73 lines
1.7 KiB
TypeScript
Raw Normal View History

2018-03-29 09:18:10 +00:00
// Computation time allowed per frame, in milliseconds.
// On a 100 Hz monitor this would ideally be 10 ms.
// On a 200 Hz monitor it should be 5 ms.
// However, the renderer also needs a bit of time,
// so setting the value a little lower guarantees smooth transitions.
2018-03-14 03:28:31 +00:00
const timeCapacity = 6.5
2018-03-29 09:18:10 +00:00
// MutationQueue queues up DOM mutations to batch execute them before a frame is rendered.
// It checks the time used to process these mutations and if the time is over the
// defined time capacity, it will pause and continue the mutations in the next frame.
2018-06-03 02:11:19 +00:00
export default class MutationQueue {
2019-11-18 02:04:13 +00:00
private mutations: Array<() => void>
private onClearCallBacks: Array<() => void>
2018-03-14 02:08:50 +00:00
constructor() {
this.mutations = []
2018-04-02 14:07:52 +00:00
this.onClearCallBacks = []
2018-03-14 02:08:50 +00:00
}
2019-11-18 02:04:13 +00:00
public queue(mutation: () => void) {
2018-03-14 02:08:50 +00:00
this.mutations.push(mutation)
if(this.mutations.length === 1) {
window.requestAnimationFrame(() => this.mutateAll())
}
}
2019-11-18 02:04:13 +00:00
public wait(callBack: () => void) {
if(this.mutations.length === 0) {
callBack()
return
}
this.onClearCallBacks.push(callBack)
}
public length() {
return this.mutations.length
}
private mutateAll() {
2019-11-17 09:25:14 +00:00
const start = performance.now()
2018-03-14 02:08:50 +00:00
for(let i = 0; i < this.mutations.length; i++) {
2018-03-14 03:28:31 +00:00
if(performance.now() - start > timeCapacity) {
2018-03-14 02:08:50 +00:00
this.mutations = this.mutations.slice(i)
window.requestAnimationFrame(() => this.mutateAll())
return
}
2018-03-16 18:39:48 +00:00
try {
this.mutations[i]()
} catch(err) {
console.error(err)
}
2018-03-14 02:08:50 +00:00
}
this.clear()
}
2019-11-18 02:04:13 +00:00
private clear() {
2018-03-14 02:08:50 +00:00
this.mutations.length = 0
2018-04-02 14:07:52 +00:00
if(this.onClearCallBacks.length > 0) {
2019-11-17 09:25:14 +00:00
for(const callback of this.onClearCallBacks) {
2018-04-02 14:07:52 +00:00
callback()
}
this.onClearCallBacks.length = 0
2018-03-14 02:08:50 +00:00
}
}
2019-11-17 09:44:30 +00:00
}