Performance monitor

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

Ajankohdalta 12.3.2021. Katso uusin versio.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name            Performance monitor
// @description     Works on any website. Shows fps, frame time, used memory. Change modes by click
// @name:ru         Монитор производительности
// @description:ru  Работает на любом сайте. Отображает fps, время кадра, используемую память. Смена режимов по клику
// @version         1.1.1
// @author          Konf
// @namespace       https://greasyfork.org/users/424058
// @include         *
// @grant           none
// @noframes
// @require         https://cdn.jsdelivr.net/npm/[email protected]
// @require         https://cdn.jsdelivr.net/npm/[email protected]
// ==/UserScript==

/**
 * Hi! The last update was broken and the script could duplicate in your scripts manager
 * Please, reinstall it: https://greasyfork.org/scripts/408058
 * and make sure you have been installed only one copy of the script, to avoid errors
 * 
 * Привет! Последнее обновление было плохое и скрипт мог дублироваться в твоём менеджере скриптов
 * Пожалуйста, переустанови его: https://greasyfork.org/scripts/408058
 * и убедись что у тебя установлена только одна копия скрипта, чтобы избежать ошибок
 */

/* jshint esversion: 6 */
/* eslint-disable no-undef */

/**
 * In the code below I just try to make proper work of the two ready libraries:
 * One makes performance monitor, and second makes the monitor movable
 * It was not so easy, and seems it works now, but DON'T try to understand why
 * Most likely, even me already do not know it
 */

(function() {
  'use strict';

  const stats = new Stats();
  const statsParentNode = document.body;
  let statsIsHidden = false;
  let mouseOverParentNode = true;

  stats.dom.style.touchAction = 'none';
  stats.dom.style.width = '80px';
  stats.dom.style.height = '48px';
  stats.dom.style.padding = 0;
  stats.dom.style.margin = 0;

  statsParentNode.appendChild(stats.dom);

  const panelNum = {
    current: 0,
    max: 2
  };

  const listeners = {
    statsDragInteract: {
      // call this function on every dragmove event
      move(event) {
        const target = event.target;

        // keep the dragged position in the data-x/data-y attributes
        const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
        const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;

        // translate the element
        target.style.transform = 'translate(' + x + 'px, ' + (y < 0 ? 0 : y) + 'px)';
        target.style.webkitTransform = target.style.transform;

        // update the position attributes
        target.setAttribute('data-x', x);
        target.setAttribute('data-y', y);
      },

      // bugfix...
      start(event) {
        const target = event.target;
        const targetTransform = target.style.transform;
        const transformY = (/,( |)*(\d*)/.exec(targetTransform) || [])[2];

        if (targetTransform && transformY <= 0) {
          target.setAttribute('data-y', 0);
        }
      },

      // call this function on every dragend event
      end(event) {
        statsIsHidden = false;

        if (mouseOverParentNode && --panelNum.current < 0) {
          panelNum.current = panelNum.max;
        }

        if (!mouseOverParentNode || statsIsHidden) {
          return stats.showPanel(panelNum.current);
        }

        stats.showPanel(panelNum.current - 1);
      }
    },

    statsNative: {
      node: {
        click(event) {
          if (statsIsHidden) {
            statsIsHidden = false;
            return stats.showPanel(panelNum.current);
          }

          if (++panelNum.current > panelNum.max) {
            panelNum.current = 0;
          }

          stats.showPanel(panelNum.current);
        }
      },

      parent: {
        mouseenter(event) {
          mouseOverParentNode = true;
        },
        mouseleave(event) {
          mouseOverParentNode = false;
        }
      },

      canvas: {
        contextmenu(event) {
          event.preventDefault();

          statsIsHidden = true;
          this.style.display = 'none';
        }
      }
    }
  };

  interact(stats.dom).draggable({
    // keep the element within the area of it's parent
    modifiers: [
      interact.modifiers.restrictRect({
        restriction: 'parent'
      })
    ],

    listeners: listeners.statsDragInteract
  });

  const panels = Array.from(stats.dom.querySelectorAll('canvas'));
  panels.forEach((canvas) => {
    canvas.addEventListener('contextmenu', listeners.statsNative.canvas.contextmenu);
  });

  stats.dom.addEventListener('click', listeners.statsNative.node.click);

  statsParentNode.addEventListener('mouseenter', listeners.statsNative.parent.mouseenter);
  statsParentNode.addEventListener('mouseleave', listeners.statsNative.parent.mouseleave);

  requestAnimationFrame(function loop() {
    stats.update();
    requestAnimationFrame(loop);
  });
})();