Profiler.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import { Style } from './Style.js';
  2. export class Profiler {
  3. constructor() {
  4. this.tabs = {};
  5. this.activeTabId = null;
  6. this.isResizing = false;
  7. this.lastHeight = 350;
  8. Style.init();
  9. this.setupShell();
  10. this.setupResizing();
  11. }
  12. setupShell() {
  13. this.domElement = document.createElement( 'div' );
  14. this.domElement.id = 'profiler-shell';
  15. this.toggleButton = document.createElement( 'button' );
  16. this.toggleButton.id = 'profiler-toggle';
  17. this.toggleButton.innerHTML = `
  18. <span id="toggle-text">
  19. <span id="fps-counter">-</span>
  20. <span class="fps-label">FPS</span>
  21. </span>
  22. <!-- <span class="toggle-separator"></span> -->
  23. <span id="toggle-icon">
  24. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-device-ipad-horizontal-search"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M11.5 20h-6.5a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v5.5" /><path d="M9 17h2" /><path d="M18 18m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" /><path d="M20.2 20.2l1.8 1.8" /></svg>
  25. </span>
  26. `;
  27. this.toggleButton.onclick = () => this.togglePanel();
  28. this.panel = document.createElement( 'div' );
  29. this.panel.id = 'profiler-panel';
  30. const header = document.createElement( 'div' );
  31. header.className = 'profiler-header';
  32. this.tabsContainer = document.createElement( 'div' );
  33. this.tabsContainer.className = 'profiler-tabs';
  34. const controls = document.createElement( 'div' );
  35. controls.className = 'profiler-controls';
  36. this.maximizeBtn = document.createElement( 'button' );
  37. this.maximizeBtn.id = 'maximize-btn';
  38. this.maximizeBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg>';
  39. this.maximizeBtn.onclick = () => this.toggleMaximize();
  40. const hideBtn = document.createElement( 'button' );
  41. hideBtn.id = 'hide-panel-btn';
  42. hideBtn.textContent = '-';
  43. hideBtn.onclick = () => this.togglePanel();
  44. controls.append( this.maximizeBtn, hideBtn );
  45. header.append( this.tabsContainer, controls );
  46. this.contentWrapper = document.createElement( 'div' );
  47. this.contentWrapper.className = 'profiler-content-wrapper';
  48. const resizer = document.createElement( 'div' );
  49. resizer.className = 'panel-resizer';
  50. this.panel.append( resizer, header, this.contentWrapper );
  51. this.domElement.append( this.toggleButton, this.panel );
  52. }
  53. setupResizing() {
  54. const resizer = this.panel.querySelector( '.panel-resizer' );
  55. const onStart = ( e ) => {
  56. this.isResizing = true;
  57. this.panel.classList.add( 'resizing' );
  58. const startY = e.clientY || e.touches[ 0 ].clientY;
  59. const startHeight = this.panel.offsetHeight;
  60. const onMove = ( moveEvent ) => {
  61. if ( ! this.isResizing ) return;
  62. moveEvent.preventDefault();
  63. const currentY = moveEvent.clientY || moveEvent.touches[ 0 ].clientY;
  64. const newHeight = startHeight - ( currentY - startY );
  65. if ( newHeight > 100 && newHeight < window.innerHeight - 50 ) {
  66. this.panel.style.height = `${newHeight}px`;
  67. }
  68. };
  69. const onEnd = () => {
  70. this.isResizing = false;
  71. this.panel.classList.remove( 'resizing' );
  72. document.removeEventListener( 'mousemove', onMove );
  73. document.removeEventListener( 'mouseup', onEnd );
  74. document.removeEventListener( 'touchmove', onMove );
  75. document.removeEventListener( 'touchend', onEnd );
  76. if ( ! this.panel.classList.contains( 'maximized' ) ) {
  77. this.lastHeight = this.panel.offsetHeight;
  78. }
  79. };
  80. document.addEventListener( 'mousemove', onMove );
  81. document.addEventListener( 'mouseup', onEnd );
  82. document.addEventListener( 'touchmove', onMove, { passive: false } );
  83. document.addEventListener( 'touchend', onEnd );
  84. };
  85. resizer.addEventListener( 'mousedown', onStart );
  86. resizer.addEventListener( 'touchstart', onStart );
  87. }
  88. toggleMaximize() {
  89. if ( this.panel.classList.contains( 'maximized' ) ) {
  90. this.panel.classList.remove( 'maximized' );
  91. this.panel.style.height = `${ this.lastHeight }px`;
  92. this.maximizeBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg>';
  93. } else {
  94. this.lastHeight = this.panel.offsetHeight;
  95. this.panel.classList.add( 'maximized' );
  96. this.panel.style.height = '100vh';
  97. this.maximizeBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="8" y="8" width="12" height="12" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path></svg>';
  98. }
  99. }
  100. addTab( tab ) {
  101. this.tabs[ tab.id ] = tab;
  102. tab.button.onclick = () => this.setActiveTab( tab.id );
  103. this.tabsContainer.appendChild( tab.button );
  104. this.contentWrapper.appendChild( tab.content );
  105. }
  106. setActiveTab( id ) {
  107. if ( this.activeTabId ) this.tabs[ this.activeTabId ].setActive( false );
  108. this.activeTabId = id;
  109. this.tabs[ id ].setActive( true );
  110. }
  111. togglePanel() {
  112. this.panel.classList.toggle( 'visible' );
  113. this.toggleButton.classList.toggle( 'hidden' );
  114. }
  115. }
粤ICP备19079148号