Performance monitor

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

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