Performance monitor

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

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