UNPKG

3.68 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3 typeof define === 'function' && define.amd ? define(factory) :
4 (global.microFps = factory());
5}(this, (function () { 'use strict';
6
7var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
8
9/**
10 * @typedef {function(FpsInfo)} fpsCallback
11 * @callback fpsCallback
12 * @param {FpsInfo} fps Fps info object
13 */
14
15/**
16* @typedef {Object} FpsInfo
17* @property {number} fps The calculated frames per second
18* @property {number} jitter The absolute difference since the last calculated fps
19* @property {number} elapsed Milliseconds ellapsed since the last computation
20* @property {number} frames Number of frames since the last computation
21* @property {number} trigger Next computation will happen at this amount of frames
22*/
23
24/**
25 * FPS Meter - Returns a function that is used to compute the framerate without the overhead of updating the DOM every frame.
26 * @param {fpsCallback} callback Callback fired every time the FPS is computed
27 * @param {number} [refreshRate=1] Refresh rate which the fps is computed and the callback is fired (0 to compute every frame, not recommended)
28 * @return {function} Returns a function that should be called on every the loop tick
29 * @author Victor B - www.vitim.us - github.com/victornpb/fpsMeter
30 */
31function microFps(callback) {
32 var refreshRate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
33
34 if (typeof callback !== 'function') throw new Error('Callback is not a function');
35 if (typeof refreshRate !== 'number' || isNaN(refreshRate) || refreshRate < 0 || refreshRate === Infinity) throw new Error('refreshRate should be a positive number! e.g. 2 (fps)');
36
37 /** number of frames since last computation */
38 var frames = -1;
39 /** compute fps at this amount of frames (it will try to match the refresh rate) */
40 var trigger = 0;
41
42 /** previous timestamp */
43 var lastTimestamp = undefined;
44
45 /** last computed fps value */
46 var lastFps = 0;
47 /** computed jitter */
48 var jitter = 0;
49
50 // use performance.now() or fallback to Date.now() only check on initialization
51 var millis = (typeof performance === 'undefined' ? 'undefined' : _typeof(performance)) === 'object' && 'now' in performance ? performance.now.bind(performance) : Date.now.bind(Date);
52
53 return function fpsMeterTick() {
54 if (frames >= trigger) {
55
56 var now = millis();
57 if (lastTimestamp === undefined) lastTimestamp = now;
58 var elapsed = now - lastTimestamp;
59
60 if (elapsed > 0) {
61 // calculate fps
62 var fps = frames > 0 ? 1000 / (elapsed / frames) : 0;
63
64 // calculate jitter
65 jitter = Math.abs(lastFps - fps);
66
67 if (refreshRate > 0) {
68 // converge the trigger value exponentialy to match the current refresh rate.
69 trigger = trigger * 0.5 + fps / refreshRate * 0.5;
70 if (trigger < 0) trigger = 0;
71 } else {
72 trigger = 0;
73 }
74
75 var info = {
76 fps: fps,
77 jitter: jitter,
78 elapsed: elapsed,
79 frames: frames,
80 trigger: trigger
81 };
82
83 // reset variables for the next measurement
84 lastTimestamp = now;
85 lastFps = fps;
86 frames = 0;
87
88 callback(info);
89 } else {
90 // 2 frames on the same milliseconds, ramp the trigger up
91 trigger *= 2;
92 }
93 }
94 frames++;
95 };
96}
97
98return microFps;
99
100})));