2023-05-05 08:55:43 +02:00

45 lines
1.5 KiB
JavaScript

const round = (x) => Math.round(x * 1000) / 1000;
// this class can be used to create a code highlighter
// it is encapsulated from the editor via the onUpdate callback
// the scheduler is expected to be an instance of Cyclist
export class Highlighter {
constructor(onUpdate) {
this.onUpdate = onUpdate;
}
start(scheduler) {
let highlights = [];
let lastEnd = 0;
this.stop();
const self = this;
let frame = requestAnimationFrame(function updateHighlights() {
try {
const time = scheduler.now();
// force min framerate of 10 fps => fixes crash on tab refocus, where lastEnd could be far away
// see https://github.com/tidalcycles/strudel/issues/108
const begin = Math.max(lastEnd ?? time, time - 1 / 10, -0.01); // negative time seems buggy
const span = [round(begin), round(time + 1 / 60)];
lastEnd = span[1];
highlights = highlights.filter((hap) => hap.whole.end > time); // keep only highlights that are still active
const haps = scheduler.pattern
.queryArc(...span)
.filter((hap) => hap.hasOnset());
highlights = highlights.concat(haps); // add potential new onsets
self.onUpdate(highlights); // highlight all still active + new active haps
} catch (err) {
self.onUpdate([]);
}
frame = requestAnimationFrame(updateHighlights);
});
self.cancel = () => {
cancelAnimationFrame(frame);
};
}
stop() {
if (this.cancel) {
this.cancel();
this.onUpdate([]);
}
}
}