Tone.js/Tone/core/Draw.js
tambien ed71d8141b amd to es6 import/export
no longer using AMD (require.js) style imports, and beginning to move to es6 "import/export" statements everywhere.
2019-01-27 13:05:20 -05:00

111 lines
2.8 KiB
JavaScript

import Tone from "../core/Tone";
import "../core/Timeline";
/**
* @class Tone.Draw is useful for synchronizing visuals and audio events.
* Callbacks from Tone.Transport or any of the Tone.Event classes
* always happen _before_ the scheduled time and are not synchronized
* to the animation frame so they are not good for triggering tightly
* synchronized visuals and sound. Tone.Draw makes it easy to schedule
* callbacks using the AudioContext time and uses requestAnimationFrame.
*
* @singleton
* @extends {Tone}
* @example
* Tone.Transport.schedule(function(time){
* //use the time argument to schedule a callback with Tone.Draw
* Tone.Draw.schedule(function(){
* //do drawing or DOM manipulation here
* }, time)
* }, "+0.5")
*/
Tone.Draw = function(){
Tone.call(this);
/**
* All of the events.
* @type {Tone.Timeline}
* @private
*/
this._events = new Tone.Timeline();
/**
* The duration after which events are not invoked.
* @type {Number}
* @default 0.25
*/
this.expiration = 0.25;
/**
* The amount of time before the scheduled time
* that the callback can be invoked. Default is
* half the time of an animation frame (0.008 seconds).
* @type {Number}
* @default 0.008
*/
this.anticipation = 0.008;
/**
* The draw loop
* @type {Function}
* @private
*/
this._boundDrawLoop = this._drawLoop.bind(this);
};
Tone.extend(Tone.Draw);
/**
* Schedule a function at the given time to be invoked
* on the nearest animation frame.
* @param {Function} callback Callback is invoked at the given time.
* @param {Time} time The time relative to the AudioContext time
* to invoke the callback.
* @return {Tone.Draw} this
*/
Tone.Draw.prototype.schedule = function(callback, time){
this._events.add({
callback : callback,
time : this.toSeconds(time)
});
//start the draw loop on the first event
if (this._events.length === 1){
requestAnimationFrame(this._boundDrawLoop);
}
return this;
};
/**
* Cancel events scheduled after the given time
* @param {Time=} after Time after which scheduled events will
* be removed from the scheduling timeline.
* @return {Tone.Draw} this
*/
Tone.Draw.prototype.cancel = function(after){
this._events.cancel(this.toSeconds(after));
return this;
};
/**
* The draw loop
* @private
*/
Tone.Draw.prototype._drawLoop = function(){
var now = Tone.context.currentTime;
while (this._events.length && this._events.peek().time - this.anticipation <= now){
var event = this._events.shift();
if (now - event.time <= this.expiration){
event.callback();
}
}
if (this._events.length > 0){
requestAnimationFrame(this._boundDrawLoop);
}
};
//make a singleton
Tone.Draw = new Tone.Draw();
export default Tone.Draw;