Performance monitor

Works on any website. Shows fps, frame time, used memory. Change modes by click

As of 2020-08-04. See the latest version.

  1. // ==UserScript==
  2. // @name Performance monitor
  3. // @description Works on any website. Shows fps, frame time, used memory. Change modes by click
  4. // @name:ru Монитор производительности
  5. // @description:ru Работает на любом сайте. Отображает fps, время кадра, используемую память. Смена режимов по клику
  6. // @version 1.0.1
  7. // @author elivovciwbilkosivitceri
  8. // @namespace https://greatest.deepsurf.us/users/462954
  9. // @include *
  10. // @noframes
  11. // @grant none
  12. // @require https://cdn.jsdelivr.net/npm/stats.js@0.17.0
  13. // @require https://cdn.jsdelivr.net/npm/interactjs@1.9.20
  14. // ==/UserScript==
  15.  
  16. /* jshint esversion: 6 */
  17. /* eslint-disable no-undef */
  18.  
  19. // In the code below I just try to make proper work of the two ready libraries:
  20. // One makes performance monitor, and second makes the monitor movable.
  21. // It was not so easy, and seems it works now, but DON'T try to understand why.
  22. // Most likely, even me already do not know it.
  23.  
  24. (function() {
  25. 'use strict';
  26.  
  27. const stats = new Stats();
  28. const statsParentNode = document.body;
  29. let statsIsHidden = false;
  30. let mouseOverParentNode = true;
  31.  
  32. stats.dom.style.touchAction = 'none';
  33. stats.dom.style.width = '80px';
  34. stats.dom.style.height = '48px';
  35. stats.dom.style.padding = 0;
  36. stats.dom.style.margin = 0;
  37.  
  38. statsParentNode.appendChild(stats.dom);
  39.  
  40. const panelNum = {
  41. current: 0,
  42. max: 2
  43. }
  44.  
  45. const listeners = {
  46. statsDragInteract: {
  47. // call this function on every dragmove event
  48. move(event) {
  49. const target = event.target;
  50.  
  51. // keep the dragged position in the data-x/data-y attributes
  52. const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
  53. const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
  54.  
  55. // translate the element
  56. target.style.transform = 'translate(' + x + 'px, ' + (y < 0 ? 0 : y) + 'px)';
  57. target.style.webkitTransform = target.style.transform;
  58.  
  59. // update the position attributes
  60. target.setAttribute('data-x', x);
  61. target.setAttribute('data-y', y);
  62. },
  63.  
  64. // bugfix...
  65. start(event) {
  66. const target = event.target;
  67. const targetTransform = target.style.transform;
  68. const transformY = (/,( |)*(\d*)/.exec(targetTransform) || [])[2];
  69.  
  70. if (targetTransform && transformY <= 0) {
  71. target.setAttribute('data-y', 0);
  72. }
  73. },
  74.  
  75. // call this function on every dragend event
  76. end(event) {
  77. statsIsHidden = false;
  78.  
  79. if (mouseOverParentNode && --panelNum.current < 0) {
  80. panelNum.current = panelNum.max;
  81. }
  82.  
  83. if (!mouseOverParentNode || statsIsHidden) {
  84. return stats.showPanel(panelNum.current);
  85. }
  86.  
  87. stats.showPanel(panelNum.current - 1);
  88. }
  89. },
  90.  
  91. statsNative: {
  92. node: {
  93. click(event) {
  94. if (statsIsHidden) {
  95. statsIsHidden = false;
  96. return stats.showPanel(panelNum.current);
  97. }
  98.  
  99. if (++panelNum.current > panelNum.max) {
  100. panelNum.current = 0
  101. }
  102.  
  103. stats.showPanel(panelNum.current);
  104. }
  105. },
  106.  
  107. parent: {
  108. mouseenter(event) {
  109. mouseOverParentNode = true;
  110. },
  111. mouseleave(event) {
  112. mouseOverParentNode = false;
  113. }
  114. },
  115.  
  116. canvas: {
  117. contextmenu(event) {
  118. event.preventDefault();
  119.  
  120. statsIsHidden = true;
  121. this.style.display = 'none';
  122. }
  123. }
  124. }
  125. }
  126.  
  127. interact(stats.dom).draggable({
  128. // keep the element within the area of it's parent
  129. modifiers: [
  130. interact.modifiers.restrictRect({
  131. restriction: 'parent'
  132. })
  133. ],
  134.  
  135. listeners: listeners.statsDragInteract
  136. });
  137.  
  138. const panels = Array.from(stats.dom.querySelectorAll('canvas'));
  139. panels.forEach((canvas) => {
  140. canvas.addEventListener('contextmenu', listeners.statsNative.canvas.contextmenu)
  141. });
  142.  
  143. stats.dom.addEventListener('click', listeners.statsNative.node.click);
  144.  
  145. statsParentNode.addEventListener('mouseenter', listeners.statsNative.parent.mouseenter);
  146. statsParentNode.addEventListener('mouseleave', listeners.statsNative.parent.mouseleave);
  147.  
  148. requestAnimationFrame(function loop() {
  149. stats.update();
  150. requestAnimationFrame(loop);
  151. });
  152. })();