@clementroche/raf
Version:
This package implements a ticker using only one requestAnimationFrame
158 lines (136 loc) • 3.85 kB
JavaScript
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
// https://github.com/mrdoob/three.js/blob/master/src/core/Clock.js
var Clock = /*#__PURE__*/function () {
function Clock(autoStart) {
_classCallCheck(this, Clock);
this.autoStart = autoStart !== undefined ? autoStart : true;
this.startTime = 0;
this.oldTime = 0;
this.elapsedTime = 0;
this.running = false;
}
_createClass(Clock, [{
key: "start",
value: function start() {
this.startTime = (typeof performance === 'undefined' ? Date : performance).now(); // see #10732
this.oldTime = this.startTime;
this.elapsedTime = 0;
this.running = true;
}
}, {
key: "stop",
value: function stop() {
this.getElapsedTime();
this.running = false;
this.autoStart = false;
}
}, {
key: "getElapsedTime",
value: function getElapsedTime() {
this.getDelta();
return this.elapsedTime;
}
}, {
key: "getDelta",
value: function getDelta() {
var diff = 0;
if (this.autoStart && !this.running) {
this.start();
return 0;
}
if (this.running) {
var newTime = (typeof performance === 'undefined' ? Date : performance).now();
diff = (newTime - this.oldTime) / 1000;
this.oldTime = newTime;
this.elapsedTime += diff;
}
return diff;
}
}]);
return Clock;
}();
var Raf = /*#__PURE__*/function () {
function Raf() {
var fps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 60;
_classCallCheck(this, Raf);
this.rafs = {};
this.clock = new Clock();
this.fps = fps;
this.latest = 0;
this.delta = 0;
this.optimumDeltaTime = this.frameDuration / 1000;
this.loop();
}
_createClass(Raf, [{
key: "dispatch",
value: function dispatch() {
// clock
var deltaTime = this.clock.getDelta();
var time = this.clock.getElapsedTime();
var lagSmoothing = deltaTime / (1000 / 60 / 1000); // callbacks
Object.values(this.rafs).sort(function (a, b) {
return a.priority - b.priority;
}).forEach(function (raf) {
raf.callback({
time: time,
deltaTime: deltaTime,
lagSmoothing: lagSmoothing
});
});
}
}, {
key: "loop",
value: function loop() {
var now = performance.now();
this.delta = now - this.latest;
if (this.delta > this.frameDuration) {
this.dispatch();
}
this.latest = now - this.delta % this.frameDuration;
requestAnimationFrame(this.loop.bind(this));
}
}, {
key: "add",
value: function add(id, callback) {
var priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
if (this.rafs[id]) {
return;
}
this.rafs[id] = {
id: id,
callback: callback,
priority: priority
};
}
}, {
key: "remove",
value: function remove(id) {
delete this.rafs[id];
}
}, {
key: "frameDuration",
get: function get() {
return 1000 / this.fps;
}
}]);
return Raf;
}();
export default Raf;