diff --git a/build/stats.js b/build/stats.js index 4875f72..75d7c07 100644 --- a/build/stats.js +++ b/build/stats.js @@ -1,179 +1,247 @@ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : - (global.Stats = factory()); + (global = global || self, global.Stats = factory()); }(this, (function () { 'use strict'; -/** - * @author mrdoob / http://mrdoob.com/ - */ - -var Stats = function () { - - var mode = 0; - - var container = document.createElement( 'div' ); - container.style.cssText = 'position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000'; - container.addEventListener( 'click', function ( event ) { - - event.preventDefault(); - showPanel( ++ mode % container.children.length ); - - }, false ); - - // - - function addPanel( panel ) { - - container.appendChild( panel.dom ); - return panel; - - } - - function showPanel( id ) { - - for ( var i = 0; i < container.children.length; i ++ ) { - - container.children[ i ].style.display = i === id ? 'block' : 'none'; - - } - - mode = id; - - } - - // - - var beginTime = ( performance || Date ).now(), prevTime = beginTime, frames = 0; - - var fpsPanel = addPanel( new Stats.Panel( 'FPS', '#0ff', '#002' ) ); - var msPanel = addPanel( new Stats.Panel( 'MS', '#0f0', '#020' ) ); - - if ( self.performance && self.performance.memory ) { - - var memPanel = addPanel( new Stats.Panel( 'MB', '#f08', '#201' ) ); - - } - - showPanel( 0 ); - - return { - - REVISION: 16, - - dom: container, - - addPanel: addPanel, - showPanel: showPanel, - - begin: function () { - - beginTime = ( performance || Date ).now(); - - }, - - end: function () { - - frames ++; - - var time = ( performance || Date ).now(); - - msPanel.update( time - beginTime, 200 ); - - if ( time >= prevTime + 1000 ) { - - fpsPanel.update( ( frames * 1000 ) / ( time - prevTime ), 100 ); - - prevTime = time; - frames = 0; - - if ( memPanel ) { - - var memory = performance.memory; - memPanel.update( memory.usedJSHeapSize / 1048576, memory.jsHeapSizeLimit / 1048576 ); - - } - - } - - return time; - - }, - - update: function () { - - beginTime = this.end(); - - }, - - // Backwards Compatibility - - domElement: container, - setMode: showPanel - + /** + * @author mrdoob / http://mrdoob.com/ + */ + + var Stats = function (option) { + var mode = 0; + if (!option) { + option = {}; + } + Stats.alertThreshold = option.alertThreshold || {}; + var alertThreshold = Stats.alertThreshold; + var fpsThreshold = alertThreshold.fps; + var msThreshold = alertThreshold.ms; + var mbThreshold = alertThreshold.mb; + + fpsThreshold = getThresholdValue(fpsThreshold, 100); + msThreshold = getThresholdValue(msThreshold, 200); + mbThreshold = getThresholdValue( + mbThreshold, + self.performance.memory.jsHeapSizeLimit / 1048576 + ); + + var container = document.createElement("div"); + container.style.cssText = + "position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000"; + container.addEventListener( + "click", + function (event) { + event.preventDefault(); + showPanel(++mode % container.children.length); + }, + false + ); + + // + + function addPanel(panel) { + container.appendChild(panel.dom); + return panel; + } + + function showPanel(id) { + for (var i = 0; i < container.children.length; i++) { + container.children[i].style.display = i === id ? "block" : "none"; + } + + mode = id; + } + + // + + var beginTime = (performance || Date).now(), + prevTime = beginTime, + frames = 0; + + var fpsPanel = addPanel(new Stats.Panel("FPS", "#0ff", "#002", "#f00")); + var msPanel = addPanel(new Stats.Panel("MS", "#0f0", "#020", "#f00")); + + if (self.performance && self.performance.memory) { + var memPanel = addPanel(new Stats.Panel("MB", "#f08", "#201", "#fff")); + } + + showPanel(0); + + return { + REVISION: 16, + + dom: container, + + addPanel: addPanel, + showPanel: showPanel, + + begin: function () { + beginTime = (performance || Date).now(); + }, + + end: function () { + frames++; + + var time = (performance || Date).now(); + + msPanel.update(time - beginTime, 200, msThreshold); + + if (time >= prevTime + 1000) { + fpsPanel.update((frames * 1000) / (time - prevTime), 100, fpsThreshold); + + prevTime = time; + frames = 0; + + if (memPanel) { + var memory = performance.memory; + memPanel.update( + memory.usedJSHeapSize / 1048576, + memory.jsHeapSizeLimit / 1048576, + mbThreshold + ); + } + } + + return time; + }, + + update: function () { + beginTime = this.end(); + }, + + // Backwards Compatibility + + domElement: container, + setMode: showPanel, + }; }; -}; - -Stats.Panel = function ( name, fg, bg ) { - - var min = Infinity, max = 0, round = Math.round; - var PR = round( window.devicePixelRatio || 1 ); - - var WIDTH = 80 * PR, HEIGHT = 48 * PR, - TEXT_X = 3 * PR, TEXT_Y = 2 * PR, - GRAPH_X = 3 * PR, GRAPH_Y = 15 * PR, - GRAPH_WIDTH = 74 * PR, GRAPH_HEIGHT = 30 * PR; - - var canvas = document.createElement( 'canvas' ); - canvas.width = WIDTH; - canvas.height = HEIGHT; - canvas.style.cssText = 'width:80px;height:48px'; - - var context = canvas.getContext( '2d' ); - context.font = 'bold ' + ( 9 * PR ) + 'px Helvetica,Arial,sans-serif'; - context.textBaseline = 'top'; - - context.fillStyle = bg; - context.fillRect( 0, 0, WIDTH, HEIGHT ); - - context.fillStyle = fg; - context.fillText( name, TEXT_X, TEXT_Y ); - context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT ); - - context.fillStyle = bg; - context.globalAlpha = 0.9; - context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT ); - - return { - - dom: canvas, - - update: function ( value, maxValue ) { - - min = Math.min( min, value ); - max = Math.max( max, value ); - - context.fillStyle = bg; - context.globalAlpha = 1; - context.fillRect( 0, 0, WIDTH, GRAPH_Y ); - context.fillStyle = fg; - context.fillText( round( value ) + ' ' + name + ' (' + round( min ) + '-' + round( max ) + ')', TEXT_X, TEXT_Y ); - - context.drawImage( canvas, GRAPH_X + PR, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT ); - - context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT ); - - context.fillStyle = bg; - context.globalAlpha = 0.9; - context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, round( ( 1 - ( value / maxValue ) ) * GRAPH_HEIGHT ) ); - - } - + Stats.Panel = function (name, fg, bg, eg) { + var min = Infinity, + max = 0, + round = Math.round; + + var PR = round(window.devicePixelRatio || 1); + + var WIDTH = 80 * PR, + HEIGHT = 48 * PR, + TEXT_X = 3 * PR, + TEXT_Y = 2 * PR, + GRAPH_X = 3 * PR, + GRAPH_Y = 15 * PR, + GRAPH_WIDTH = 74 * PR, + GRAPH_HEIGHT = 30 * PR; + + var canvas = document.createElement("canvas"); + canvas.width = WIDTH; + canvas.height = HEIGHT; + canvas.style.cssText = "width:80px;height:48px"; + + var context = canvas.getContext("2d"); + context.font = "bold " + 9 * PR + "px Helvetica,Arial,sans-serif"; + context.textBaseline = "top"; + + context.fillStyle = bg; + context.fillRect(0, 0, WIDTH, HEIGHT); + + context.fillStyle = fg; + context.fillText(name, TEXT_X, TEXT_Y); + context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT); + + context.fillStyle = bg; + context.globalAlpha = 0.9; + context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT); + + return { + dom: canvas, + + update: function (value, maxValue, threshold) { + min = Math.min(min, value); + max = Math.max(max, value); + + context.fillStyle = bg; + context.globalAlpha = 1; + context.fillRect(0, 0, WIDTH, GRAPH_Y); + context.fillStyle = fg; + context.fillText( + round(value) + " " + name + " (" + round(min) + "-" + round(max) + ")", + TEXT_X, + TEXT_Y + ); + + if (typeof threshold === "number") { + switch (name) { + case "FPS": { + if (value <= threshold) { + context.fillStyle = eg; + } + break; + } + case "MB": { + if (value >= threshold) { + context.fillStyle = eg; + } + break; + } + case "MS": { + if (value >= threshold) { + context.fillStyle = eg; + } + break; + } + } + } + + context.drawImage( + canvas, + GRAPH_X + PR, + GRAPH_Y, + GRAPH_WIDTH - PR, + GRAPH_HEIGHT, + GRAPH_X, + GRAPH_Y, + GRAPH_WIDTH - PR, + GRAPH_HEIGHT + ); + + context.fillRect(GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT); + + context.fillStyle = bg; + context.globalAlpha = 0.9; + context.fillRect( + GRAPH_X + GRAPH_WIDTH - PR, + GRAPH_Y, + PR, + round((1 - value / maxValue) * GRAPH_HEIGHT) + ); + }, + }; }; -}; + function getThresholdValue(rawThreshold, maxValue) { + if (typeof rawThreshold === "undefined") return undefined; + switch (typeof rawThreshold) { + case "string": { + var threshold = rawThreshold; + if (threshold.includes("%")) { + threshold = Number(rawThreshold.split("%")[0]); + threshold = Math.round((maxValue * threshold) / 100); + } + return Number(threshold); + } + case "number": { + return rawThreshold; + } + case "undefined": { + return undefined; + } + default: { + throw new Error("invalid Error threshold type"); + } + } + } -return Stats; + return Stats; }))); diff --git a/build/stats.min.js b/build/stats.min.js index 3ddf1e5..0c7f4ed 100644 --- a/build/stats.min.js +++ b/build/stats.min.js @@ -1,5 +1,6 @@ -// stats.js - http://github.com/mrdoob/stats.js -(function(f,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"===typeof define&&define.amd?define(e):f.Stats=e()})(this,function(){var f=function(){function e(a){c.appendChild(a.dom);return a}function u(a){for(var d=0;d=g+1E3&&(r.update(1E3*a/(c-g),100),g=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/ -1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){k=this.end()},domElement:c,setMode:u}};f.Panel=function(e,f,l){var c=Infinity,k=0,g=Math.round,a=g(window.devicePixelRatio||1),r=80*a,h=48*a,t=3*a,v=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=h;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,h);b.fillStyle=f;b.fillText(e,t,v); -b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(h,w){c=Math.min(c,h);k=Math.max(k,h);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=f;b.fillText(g(h)+" "+e+" ("+g(c)+"-"+g(k)+")",t,v);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,g((1-h/w)*p))}}};return f}); +(function(g,d){"object"===typeof exports&&"undefined"!==typeof module?module.exports=d():"function"===typeof define&&define.amd?define(d):(g=g||self,g.Stats=d())})(this,function(){function g(b,d){if("undefined"!==typeof b)switch(typeof b){case "string":var e=b;e.includes("%")&&(e=Number(b.split("%")[0]),e=Math.round(d*e/100));return Number(e);case "number":return b;case "undefined":break;default:throw Error("invalid Error threshold type");}}var d=function(b){function p(f){a.appendChild(f.dom);return f} +function e(f){for(var b=0;b=m+1E3&&(z.update(1E3*v/(a-m),100,q),m=a,v=0,h)){var b=performance.memory;h.update(b.usedJSHeapSize/1048576,b.jsHeapSizeLimit/ +1048576,k)}return a},update:function(){l=this.end()},domElement:a,setMode:e}};d.Panel=function(b,d,e,g){var q=Infinity,r=0,k=Math.round,a=k(window.devicePixelRatio||1),l=80*a,m=48*a,v=3*a,p=2*a,n=3*a,h=15*a,f=74*a,u=30*a,w=document.createElement("canvas");w.width=l;w.height=m;w.style.cssText="width:80px;height:48px";var c=w.getContext("2d");c.font="bold "+9*a+"px Helvetica,Arial,sans-serif";c.textBaseline="top";c.fillStyle=e;c.fillRect(0,0,l,m);c.fillStyle=d;c.fillText(b,v,p);c.fillRect(n,h,f,u); +c.fillStyle=e;c.globalAlpha=.9;c.fillRect(n,h,f,u);return{dom:w,update:function(t,m,x){q=Math.min(q,t);r=Math.max(r,t);c.fillStyle=e;c.globalAlpha=1;c.fillRect(0,0,l,h);c.fillStyle=d;c.fillText(k(t)+" "+b+" ("+k(q)+"-"+k(r)+")",v,p);if("number"===typeof x)switch(b){case "FPS":t<=x&&(c.fillStyle=g);break;case "MB":t>=x&&(c.fillStyle=g);break;case "MS":t>=x&&(c.fillStyle=g)}c.drawImage(w,n+a,h,f-a,u,n,h,f-a,u);c.fillRect(n+f-a,h,a,u);c.fillStyle=e;c.globalAlpha=.9;c.fillRect(n+f-a,h,a,k((1-t/m)*u))}}}; +return d}); diff --git a/build/stats.module.js b/build/stats.module.js index 8a3edfd..00cd652 100644 --- a/build/stats.module.js +++ b/build/stats.module.js @@ -2,170 +2,238 @@ * @author mrdoob / http://mrdoob.com/ */ -var Stats = function () { - - var mode = 0; - - var container = document.createElement( 'div' ); - container.style.cssText = 'position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000'; - container.addEventListener( 'click', function ( event ) { - - event.preventDefault(); - showPanel( ++ mode % container.children.length ); - - }, false ); - - // - - function addPanel( panel ) { - - container.appendChild( panel.dom ); - return panel; - - } - - function showPanel( id ) { - - for ( var i = 0; i < container.children.length; i ++ ) { - - container.children[ i ].style.display = i === id ? 'block' : 'none'; - - } - - mode = id; - - } - - // - - var beginTime = ( performance || Date ).now(), prevTime = beginTime, frames = 0; - - var fpsPanel = addPanel( new Stats.Panel( 'FPS', '#0ff', '#002' ) ); - var msPanel = addPanel( new Stats.Panel( 'MS', '#0f0', '#020' ) ); - - if ( self.performance && self.performance.memory ) { - - var memPanel = addPanel( new Stats.Panel( 'MB', '#f08', '#201' ) ); - - } - - showPanel( 0 ); - - return { - - REVISION: 16, - - dom: container, - - addPanel: addPanel, - showPanel: showPanel, - - begin: function () { - - beginTime = ( performance || Date ).now(); - - }, - - end: function () { - - frames ++; - - var time = ( performance || Date ).now(); - - msPanel.update( time - beginTime, 200 ); - - if ( time >= prevTime + 1000 ) { - - fpsPanel.update( ( frames * 1000 ) / ( time - prevTime ), 100 ); - - prevTime = time; - frames = 0; - - if ( memPanel ) { - - var memory = performance.memory; - memPanel.update( memory.usedJSHeapSize / 1048576, memory.jsHeapSizeLimit / 1048576 ); - - } - - } - - return time; - - }, - - update: function () { - - beginTime = this.end(); - - }, - - // Backwards Compatibility - - domElement: container, - setMode: showPanel - - }; - +var Stats = function (option) { + var mode = 0; + if (!option) { + option = {}; + } + Stats.alertThreshold = option.alertThreshold || {}; + var alertThreshold = Stats.alertThreshold; + var fpsThreshold = alertThreshold.fps; + var msThreshold = alertThreshold.ms; + var mbThreshold = alertThreshold.mb; + + fpsThreshold = getThresholdValue(fpsThreshold, 100); + msThreshold = getThresholdValue(msThreshold, 200); + mbThreshold = getThresholdValue( + mbThreshold, + self.performance.memory.jsHeapSizeLimit / 1048576 + ); + + var container = document.createElement("div"); + container.style.cssText = + "position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000"; + container.addEventListener( + "click", + function (event) { + event.preventDefault(); + showPanel(++mode % container.children.length); + }, + false + ); + + // + + function addPanel(panel) { + container.appendChild(panel.dom); + return panel; + } + + function showPanel(id) { + for (var i = 0; i < container.children.length; i++) { + container.children[i].style.display = i === id ? "block" : "none"; + } + + mode = id; + } + + // + + var beginTime = (performance || Date).now(), + prevTime = beginTime, + frames = 0; + + var fpsPanel = addPanel(new Stats.Panel("FPS", "#0ff", "#002", "#f00")); + var msPanel = addPanel(new Stats.Panel("MS", "#0f0", "#020", "#f00")); + + if (self.performance && self.performance.memory) { + var memPanel = addPanel(new Stats.Panel("MB", "#f08", "#201", "#fff")); + } + + showPanel(0); + + return { + REVISION: 16, + + dom: container, + + addPanel: addPanel, + showPanel: showPanel, + + begin: function () { + beginTime = (performance || Date).now(); + }, + + end: function () { + frames++; + + var time = (performance || Date).now(); + + msPanel.update(time - beginTime, 200, msThreshold); + + if (time >= prevTime + 1000) { + fpsPanel.update((frames * 1000) / (time - prevTime), 100, fpsThreshold); + + prevTime = time; + frames = 0; + + if (memPanel) { + var memory = performance.memory; + memPanel.update( + memory.usedJSHeapSize / 1048576, + memory.jsHeapSizeLimit / 1048576, + mbThreshold + ); + } + } + + return time; + }, + + update: function () { + beginTime = this.end(); + }, + + // Backwards Compatibility + + domElement: container, + setMode: showPanel, + }; }; -Stats.Panel = function ( name, fg, bg ) { - - var min = Infinity, max = 0, round = Math.round; - var PR = round( window.devicePixelRatio || 1 ); - - var WIDTH = 80 * PR, HEIGHT = 48 * PR, - TEXT_X = 3 * PR, TEXT_Y = 2 * PR, - GRAPH_X = 3 * PR, GRAPH_Y = 15 * PR, - GRAPH_WIDTH = 74 * PR, GRAPH_HEIGHT = 30 * PR; - - var canvas = document.createElement( 'canvas' ); - canvas.width = WIDTH; - canvas.height = HEIGHT; - canvas.style.cssText = 'width:80px;height:48px'; - - var context = canvas.getContext( '2d' ); - context.font = 'bold ' + ( 9 * PR ) + 'px Helvetica,Arial,sans-serif'; - context.textBaseline = 'top'; - - context.fillStyle = bg; - context.fillRect( 0, 0, WIDTH, HEIGHT ); - - context.fillStyle = fg; - context.fillText( name, TEXT_X, TEXT_Y ); - context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT ); - - context.fillStyle = bg; - context.globalAlpha = 0.9; - context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT ); - - return { - - dom: canvas, - - update: function ( value, maxValue ) { - - min = Math.min( min, value ); - max = Math.max( max, value ); - - context.fillStyle = bg; - context.globalAlpha = 1; - context.fillRect( 0, 0, WIDTH, GRAPH_Y ); - context.fillStyle = fg; - context.fillText( round( value ) + ' ' + name + ' (' + round( min ) + '-' + round( max ) + ')', TEXT_X, TEXT_Y ); - - context.drawImage( canvas, GRAPH_X + PR, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT ); - - context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT ); - - context.fillStyle = bg; - context.globalAlpha = 0.9; - context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, round( ( 1 - ( value / maxValue ) ) * GRAPH_HEIGHT ) ); - - } - - }; - +Stats.Panel = function (name, fg, bg, eg) { + var min = Infinity, + max = 0, + round = Math.round; + + var PR = round(window.devicePixelRatio || 1); + + var WIDTH = 80 * PR, + HEIGHT = 48 * PR, + TEXT_X = 3 * PR, + TEXT_Y = 2 * PR, + GRAPH_X = 3 * PR, + GRAPH_Y = 15 * PR, + GRAPH_WIDTH = 74 * PR, + GRAPH_HEIGHT = 30 * PR; + + var canvas = document.createElement("canvas"); + canvas.width = WIDTH; + canvas.height = HEIGHT; + canvas.style.cssText = "width:80px;height:48px"; + + var context = canvas.getContext("2d"); + context.font = "bold " + 9 * PR + "px Helvetica,Arial,sans-serif"; + context.textBaseline = "top"; + + context.fillStyle = bg; + context.fillRect(0, 0, WIDTH, HEIGHT); + + context.fillStyle = fg; + context.fillText(name, TEXT_X, TEXT_Y); + context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT); + + context.fillStyle = bg; + context.globalAlpha = 0.9; + context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT); + + return { + dom: canvas, + + update: function (value, maxValue, threshold) { + min = Math.min(min, value); + max = Math.max(max, value); + + context.fillStyle = bg; + context.globalAlpha = 1; + context.fillRect(0, 0, WIDTH, GRAPH_Y); + context.fillStyle = fg; + context.fillText( + round(value) + " " + name + " (" + round(min) + "-" + round(max) + ")", + TEXT_X, + TEXT_Y + ); + + if (typeof threshold === "number") { + switch (name) { + case "FPS": { + if (value <= threshold) { + context.fillStyle = eg; + } + break; + } + case "MB": { + if (value >= threshold) { + context.fillStyle = eg; + } + break; + } + case "MS": { + if (value >= threshold) { + context.fillStyle = eg; + } + break; + } + } + } + + context.drawImage( + canvas, + GRAPH_X + PR, + GRAPH_Y, + GRAPH_WIDTH - PR, + GRAPH_HEIGHT, + GRAPH_X, + GRAPH_Y, + GRAPH_WIDTH - PR, + GRAPH_HEIGHT + ); + + context.fillRect(GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT); + + context.fillStyle = bg; + context.globalAlpha = 0.9; + context.fillRect( + GRAPH_X + GRAPH_WIDTH - PR, + GRAPH_Y, + PR, + round((1 - value / maxValue) * GRAPH_HEIGHT) + ); + }, + }; }; +function getThresholdValue(rawThreshold, maxValue) { + if (typeof rawThreshold === "undefined") return undefined; + switch (typeof rawThreshold) { + case "string": { + var threshold = rawThreshold; + if (threshold.includes("%")) { + threshold = Number(rawThreshold.split("%")[0]); + threshold = Math.round((maxValue * threshold) / 100); + } + return Number(threshold); + } + case "number": { + return rawThreshold; + } + case "undefined": { + return undefined; + } + default: { + throw new Error("invalid Error threshold type"); + } + } +} + export default Stats; diff --git a/examples/basic.html b/examples/basic.html index 3284859..99d2028 100644 --- a/examples/basic.html +++ b/examples/basic.html @@ -1,58 +1,55 @@ - - stats.js - basic example - - - - - - - + + stats.js - basic example + + + + + + + diff --git a/examples/custom.html b/examples/custom.html index bd42179..be73b55 100644 --- a/examples/custom.html +++ b/examples/custom.html @@ -1,65 +1,62 @@ - - stats.js - custom panel example - - - - - - - + + stats.js - custom panel example + + + + + + + diff --git a/examples/stress.html b/examples/stress.html index e2af7d2..942f23f 100644 --- a/examples/stress.html +++ b/examples/stress.html @@ -1,47 +1,46 @@ - - stats.js - stress test - - - - - - - + + stats.js - stress test + + + + + + + diff --git a/package-lock.json b/package-lock.json index ce8c102..f91dddd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,178 +1,242 @@ { "name": "stats.js", "version": "0.17.0", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "ansi-styles": { + "packages": { + "": { + "name": "stats.js", + "version": "0.17.0", + "license": "MIT", + "devDependencies": { + "google-closure-compiler": "20200224.0.0", + "rollup": "^2.3.2" + } + }, + "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "requires": { + "dependencies": { "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "chalk": { + "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "requires": { + "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "clone": { + "node_modules/clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8" + } }, - "clone-buffer": { + "node_modules/clone-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.10" + } }, - "clone-stats": { + "node_modules/clone-stats": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", "dev": true }, - "cloneable-readable": { + "node_modules/cloneable-readable": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", "dev": true, - "requires": { + "dependencies": { "inherits": "^2.0.1", "process-nextick-args": "^2.0.0", "readable-stream": "^2.3.5" } }, - "color-convert": { + "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "requires": { + "dependencies": { "color-name": "1.1.3" } }, - "color-name": { + "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "core-util-is": { + "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "escape-string-regexp": { + "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "fsevents": { + "node_modules/fsevents": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "deprecated": "\"Please update to latest v2.3 or v2.2\"", "dev": true, - "optional": true + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, - "google-closure-compiler": { + "node_modules/google-closure-compiler": { "version": "20200224.0.0", "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20200224.0.0.tgz", "integrity": "sha512-V81dRYygdHbZtOtU16VX26xAdJBB1UZyfSg3OTzdNl3l/xEIx1D/L7TYUqjeTXsxcy+JruJ/UfUlIJAOaMRTog==", "dev": true, - "requires": { + "dependencies": { "chalk": "2.x", "google-closure-compiler-java": "^20200224.0.0", "google-closure-compiler-js": "^20200224.0.0", - "google-closure-compiler-linux": "^20200224.0.0", - "google-closure-compiler-osx": "^20200224.0.0", - "google-closure-compiler-windows": "^20200224.0.0", "minimist": "1.x", "vinyl": "2.x", "vinyl-sourcemaps-apply": "^0.2.0" + }, + "bin": { + "google-closure-compiler": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "google-closure-compiler-linux": "^20200224.0.0", + "google-closure-compiler-osx": "^20200224.0.0", + "google-closure-compiler-windows": "^20200224.0.0" } }, - "google-closure-compiler-java": { + "node_modules/google-closure-compiler-java": { "version": "20200224.0.0", "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20200224.0.0.tgz", "integrity": "sha512-palFcDoScauZjWIsGDzMK6h+IctcRb55I3wJX8Ko/DTSz72xwadRdKm0lGt8OoYL7SKEO+IjgD7s8XrAGpLnlQ==", "dev": true }, - "google-closure-compiler-js": { + "node_modules/google-closure-compiler-js": { "version": "20200224.0.0", "resolved": "https://registry.npmjs.org/google-closure-compiler-js/-/google-closure-compiler-js-20200224.0.0.tgz", "integrity": "sha512-70VKN0kbnTRtu2dqxDjWZQGfEQIHj7b7oUUCsYPO5oEXCDfgxNc13oYUJXvrTONLRWlHCNl/I8FNrVOwZ3gY/g==", "dev": true }, - "google-closure-compiler-linux": { + "node_modules/google-closure-compiler-linux": { "version": "20200224.0.0", "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20200224.0.0.tgz", "integrity": "sha512-/BaE889EPrXWOKJVolA9++e99xBDMzeFBf7zF7nBB8PUmU5DlvtsoLL82xnT6nbZC1ktHaETlVx+vYGju8zKBQ==", + "cpu": [ + "x64", + "x86" + ], "dev": true, - "optional": true + "optional": true, + "os": [ + "linux" + ] }, - "google-closure-compiler-osx": { + "node_modules/google-closure-compiler-osx": { "version": "20200224.0.0", "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20200224.0.0.tgz", "integrity": "sha512-WXVNW9nPUqjvCe38mUIlBGEPVPCTKLtdaXC+q+kQdonkJFHNrpdyYWa746Y8cNP/byQyDNpPsqcKseZTLh17sQ==", + "cpu": [ + "x64", + "x86" + ], "dev": true, - "optional": true + "optional": true, + "os": [ + "darwin" + ] }, - "google-closure-compiler-windows": { + "node_modules/google-closure-compiler-windows": { "version": "20200224.0.0", "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20200224.0.0.tgz", "integrity": "sha512-l6w2D8r9+GC9CQTAYEMAuNI996Zb6YV5qG7+FR0gCoL6h6S3Mc7mi87bafgwaicsVcmmHE/9kCBuW4ZyTMs5Fg==", + "cpu": [ + "x64", + "x86" + ], "dev": true, - "optional": true + "optional": true, + "os": [ + "win32" + ] }, - "has-flag": { + "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "inherits": { + "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "isarray": { + "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "minimist": { + "node_modules/minimist": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, - "process-nextick-args": { + "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "readable-stream": { + "node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, - "requires": { + "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", @@ -182,83 +246,101 @@ "util-deprecate": "~1.0.1" } }, - "remove-trailing-separator": { + "node_modules/remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", "dev": true }, - "replace-ext": { + "node_modules/replace-ext": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.10" + } }, - "rollup": { + "node_modules/rollup": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.3.3.tgz", "integrity": "sha512-uJ9VNWk80mb4wDCSfd1AyHoSc9TrWbkZtnO6wbsMTp9muSWkT26Dvc99MX1yGCOTvUN1Skw/KpFzKdUDuZKTXA==", "dev": true, - "requires": { + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { "fsevents": "~2.1.2" } }, - "safe-buffer": { + "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "source-map": { + "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "string_decoder": { + "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, - "requires": { + "dependencies": { "safe-buffer": "~5.1.0" } }, - "supports-color": { + "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "requires": { + "dependencies": { "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "util-deprecate": { + "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "vinyl": { + "node_modules/vinyl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", "dev": true, - "requires": { + "dependencies": { "clone": "^2.1.1", "clone-buffer": "^1.0.0", "clone-stats": "^1.0.0", "cloneable-readable": "^1.0.0", "remove-trailing-separator": "^1.0.1", "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" } }, - "vinyl-sourcemaps-apply": { + "node_modules/vinyl-sourcemaps-apply": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", "dev": true, - "requires": { + "dependencies": { "source-map": "^0.5.1" } } diff --git a/src/Stats.js b/src/Stats.js index 310746f..66a017a 100644 --- a/src/Stats.js +++ b/src/Stats.js @@ -2,170 +2,238 @@ * @author mrdoob / http://mrdoob.com/ */ -var Stats = function () { - - var mode = 0; - - var container = document.createElement( 'div' ); - container.style.cssText = 'position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000'; - container.addEventListener( 'click', function ( event ) { - - event.preventDefault(); - showPanel( ++ mode % container.children.length ); - - }, false ); - - // - - function addPanel( panel ) { - - container.appendChild( panel.dom ); - return panel; - - } - - function showPanel( id ) { - - for ( var i = 0; i < container.children.length; i ++ ) { - - container.children[ i ].style.display = i === id ? 'block' : 'none'; - - } - - mode = id; - - } - - // - - var beginTime = ( performance || Date ).now(), prevTime = beginTime, frames = 0; - - var fpsPanel = addPanel( new Stats.Panel( 'FPS', '#0ff', '#002' ) ); - var msPanel = addPanel( new Stats.Panel( 'MS', '#0f0', '#020' ) ); - - if ( self.performance && self.performance.memory ) { - - var memPanel = addPanel( new Stats.Panel( 'MB', '#f08', '#201' ) ); - - } - - showPanel( 0 ); - - return { - - REVISION: 16, - - dom: container, - - addPanel: addPanel, - showPanel: showPanel, - - begin: function () { - - beginTime = ( performance || Date ).now(); - - }, - - end: function () { - - frames ++; - - var time = ( performance || Date ).now(); - - msPanel.update( time - beginTime, 200 ); - - if ( time >= prevTime + 1000 ) { - - fpsPanel.update( ( frames * 1000 ) / ( time - prevTime ), 100 ); - - prevTime = time; - frames = 0; - - if ( memPanel ) { - - var memory = performance.memory; - memPanel.update( memory.usedJSHeapSize / 1048576, memory.jsHeapSizeLimit / 1048576 ); - - } - - } - - return time; - - }, - - update: function () { - - beginTime = this.end(); - - }, - - // Backwards Compatibility - - domElement: container, - setMode: showPanel - - }; - +var Stats = function (option) { + var mode = 0; + if (!option) { + option = {}; + } + Stats.alertThreshold = option.alertThreshold || {}; + var alertThreshold = Stats.alertThreshold; + var fpsThreshold = alertThreshold.fps; + var msThreshold = alertThreshold.ms; + var mbThreshold = alertThreshold.mb; + + fpsThreshold = getThresholdValue(fpsThreshold, 100); + msThreshold = getThresholdValue(msThreshold, 200); + mbThreshold = getThresholdValue( + mbThreshold, + self.performance.memory.jsHeapSizeLimit / 1048576 + ); + + var container = document.createElement("div"); + container.style.cssText = + "position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000"; + container.addEventListener( + "click", + function (event) { + event.preventDefault(); + showPanel(++mode % container.children.length); + }, + false + ); + + // + + function addPanel(panel) { + container.appendChild(panel.dom); + return panel; + } + + function showPanel(id) { + for (var i = 0; i < container.children.length; i++) { + container.children[i].style.display = i === id ? "block" : "none"; + } + + mode = id; + } + + // + + var beginTime = (performance || Date).now(), + prevTime = beginTime, + frames = 0; + + var fpsPanel = addPanel(new Stats.Panel("FPS", "#0ff", "#002", "#f00")); + var msPanel = addPanel(new Stats.Panel("MS", "#0f0", "#020", "#f00")); + + if (self.performance && self.performance.memory) { + var memPanel = addPanel(new Stats.Panel("MB", "#f08", "#201", "#fff")); + } + + showPanel(0); + + return { + REVISION: 16, + + dom: container, + + addPanel: addPanel, + showPanel: showPanel, + + begin: function () { + beginTime = (performance || Date).now(); + }, + + end: function () { + frames++; + + var time = (performance || Date).now(); + + msPanel.update(time - beginTime, 200, msThreshold); + + if (time >= prevTime + 1000) { + fpsPanel.update((frames * 1000) / (time - prevTime), 100, fpsThreshold); + + prevTime = time; + frames = 0; + + if (memPanel) { + var memory = performance.memory; + memPanel.update( + memory.usedJSHeapSize / 1048576, + memory.jsHeapSizeLimit / 1048576, + mbThreshold + ); + } + } + + return time; + }, + + update: function () { + beginTime = this.end(); + }, + + // Backwards Compatibility + + domElement: container, + setMode: showPanel, + }; }; -Stats.Panel = function ( name, fg, bg ) { - - var min = Infinity, max = 0, round = Math.round; - var PR = round( window.devicePixelRatio || 1 ); - - var WIDTH = 80 * PR, HEIGHT = 48 * PR, - TEXT_X = 3 * PR, TEXT_Y = 2 * PR, - GRAPH_X = 3 * PR, GRAPH_Y = 15 * PR, - GRAPH_WIDTH = 74 * PR, GRAPH_HEIGHT = 30 * PR; - - var canvas = document.createElement( 'canvas' ); - canvas.width = WIDTH; - canvas.height = HEIGHT; - canvas.style.cssText = 'width:80px;height:48px'; - - var context = canvas.getContext( '2d' ); - context.font = 'bold ' + ( 9 * PR ) + 'px Helvetica,Arial,sans-serif'; - context.textBaseline = 'top'; - - context.fillStyle = bg; - context.fillRect( 0, 0, WIDTH, HEIGHT ); - - context.fillStyle = fg; - context.fillText( name, TEXT_X, TEXT_Y ); - context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT ); - - context.fillStyle = bg; - context.globalAlpha = 0.9; - context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT ); - - return { - - dom: canvas, - - update: function ( value, maxValue ) { - - min = Math.min( min, value ); - max = Math.max( max, value ); - - context.fillStyle = bg; - context.globalAlpha = 1; - context.fillRect( 0, 0, WIDTH, GRAPH_Y ); - context.fillStyle = fg; - context.fillText( round( value ) + ' ' + name + ' (' + round( min ) + '-' + round( max ) + ')', TEXT_X, TEXT_Y ); - - context.drawImage( canvas, GRAPH_X + PR, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT ); - - context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT ); - - context.fillStyle = bg; - context.globalAlpha = 0.9; - context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, round( ( 1 - ( value / maxValue ) ) * GRAPH_HEIGHT ) ); - - } - - }; - +Stats.Panel = function (name, fg, bg, eg) { + var min = Infinity, + max = 0, + round = Math.round; + + var PR = round(window.devicePixelRatio || 1); + + var WIDTH = 80 * PR, + HEIGHT = 48 * PR, + TEXT_X = 3 * PR, + TEXT_Y = 2 * PR, + GRAPH_X = 3 * PR, + GRAPH_Y = 15 * PR, + GRAPH_WIDTH = 74 * PR, + GRAPH_HEIGHT = 30 * PR; + + var canvas = document.createElement("canvas"); + canvas.width = WIDTH; + canvas.height = HEIGHT; + canvas.style.cssText = "width:80px;height:48px"; + + var context = canvas.getContext("2d"); + context.font = "bold " + 9 * PR + "px Helvetica,Arial,sans-serif"; + context.textBaseline = "top"; + + context.fillStyle = bg; + context.fillRect(0, 0, WIDTH, HEIGHT); + + context.fillStyle = fg; + context.fillText(name, TEXT_X, TEXT_Y); + context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT); + + context.fillStyle = bg; + context.globalAlpha = 0.9; + context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT); + + return { + dom: canvas, + + update: function (value, maxValue, threshold) { + min = Math.min(min, value); + max = Math.max(max, value); + + context.fillStyle = bg; + context.globalAlpha = 1; + context.fillRect(0, 0, WIDTH, GRAPH_Y); + context.fillStyle = fg; + context.fillText( + round(value) + " " + name + " (" + round(min) + "-" + round(max) + ")", + TEXT_X, + TEXT_Y + ); + + if (typeof threshold === "number") { + switch (name) { + case "FPS": { + if (value <= threshold) { + context.fillStyle = eg; + } + break; + } + case "MB": { + if (value >= threshold) { + context.fillStyle = eg; + } + break; + } + case "MS": { + if (value >= threshold) { + context.fillStyle = eg; + } + break; + } + } + } + + context.drawImage( + canvas, + GRAPH_X + PR, + GRAPH_Y, + GRAPH_WIDTH - PR, + GRAPH_HEIGHT, + GRAPH_X, + GRAPH_Y, + GRAPH_WIDTH - PR, + GRAPH_HEIGHT + ); + + context.fillRect(GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT); + + context.fillStyle = bg; + context.globalAlpha = 0.9; + context.fillRect( + GRAPH_X + GRAPH_WIDTH - PR, + GRAPH_Y, + PR, + round((1 - value / maxValue) * GRAPH_HEIGHT) + ); + }, + }; }; export { Stats as default }; + +function getThresholdValue(rawThreshold, maxValue) { + if (typeof rawThreshold === "undefined") return undefined; + switch (typeof rawThreshold) { + case "string": { + var threshold = rawThreshold; + if (threshold.includes("%")) { + threshold = Number(rawThreshold.split("%")[0]); + threshold = Math.round((maxValue * threshold) / 100); + } + return Number(threshold); + } + case "number": { + return rawThreshold; + } + case "undefined": { + return undefined; + } + default: { + throw new Error("invalid Error threshold type"); + } + } +}