// ==UserScript== // @name 帧率检测器 - FPS Monitor // @namespace http://tampermonkey.net/ // @version 1.1 // @description 实时检测网页帧率(FPS) - 每秒更新一次 // @author Your Name // @match *://*/* // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; // 等待页面加载完成 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } function init() { // 创建悬浮窗容器 const floatingWindow = document.createElement('div'); floatingWindow.id = 'fps-monitor-root'; floatingWindow.style.cssText = ` position: fixed; top: 20px; right: 20px; z-index: 999999; width: 260px; background: linear-gradient(135deg, #1a1e2c 0%, #141824 100%); border-radius: 16px; padding: 15px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; box-shadow: 0 8px 20px rgba(0,0,0,0.3); border: 1px solid rgba(255,255,255,0.1); color: white; cursor: move; `; // 简单的 HTML 结构 floatingWindow.innerHTML = `
⚡ FPS 检测器 检测中
--
Frames Per Second
📊 平均帧率 -- fps
⬇️ 最低帧率 -- fps
⬆️ 最高帧率 -- fps
📈 采样次数 0
`; document.body.appendChild(floatingWindow); // 拖拽功能 let isDragging = false; let dragStartX, dragStartY, startLeft, startTop; floatingWindow.addEventListener('mousedown', (e) => { if (e.target.tagName === 'BUTTON') return; isDragging = true; dragStartX = e.clientX; dragStartY = e.clientY; startLeft = floatingWindow.offsetLeft; startTop = floatingWindow.offsetTop; floatingWindow.style.cursor = 'grabbing'; e.preventDefault(); }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; let newLeft = startLeft + (e.clientX - dragStartX); let newTop = startTop + (e.clientY - dragStartY); newLeft = Math.max(0, Math.min(window.innerWidth - floatingWindow.offsetWidth, newLeft)); newTop = Math.max(0, Math.min(window.innerHeight - floatingWindow.offsetHeight, newTop)); floatingWindow.style.left = newLeft + 'px'; floatingWindow.style.top = newTop + 'px'; floatingWindow.style.right = 'auto'; }); document.addEventListener('mouseup', () => { isDragging = false; floatingWindow.style.cursor = 'move'; }); // FPS 检测逻辑 - 每秒更新一次 let lastTime = performance.now(); let frameCount = 0; let currentFps = 0; let fpsHistory = []; let totalFps = 0; let minFps = Infinity; let maxFps = -Infinity; let sampleCount = 0; let animationId = null; const fpsValueEl = document.getElementById('fpsValue'); const avgValueEl = document.getElementById('avgValue'); const minValueEl = document.getElementById('minValue'); const maxValueEl = document.getElementById('maxValue'); const sampleCountEl = document.getElementById('sampleCount'); const fpsStatusEl = document.getElementById('fpsStatus'); const resetBtn = document.getElementById('resetFpsBtn'); function updateDisplay(fps) { // 更新当前FPS显示 const roundedFps = Math.round(fps); fpsValueEl.textContent = roundedFps; // 更新状态文字和颜色 if (fps >= 55) { fpsValueEl.style.color = '#4ade80'; fpsStatusEl.textContent = '✅ 流畅'; fpsStatusEl.style.background = 'rgba(74,222,128,0.2)'; } else if (fps >= 30) { fpsValueEl.style.color = '#fbbf24'; fpsStatusEl.textContent = '⚠️ 一般'; fpsStatusEl.style.background = 'rgba(251,191,36,0.2)'; } else { fpsValueEl.style.color = '#f87171'; fpsStatusEl.textContent = '❌ 卡顿'; fpsStatusEl.style.background = 'rgba(248,113,113,0.2)'; } } function updateStats() { if (sampleCount === 0) { avgValueEl.textContent = '-- fps'; minValueEl.textContent = '-- fps'; maxValueEl.textContent = '-- fps'; return; } const avg = totalFps / sampleCount; avgValueEl.textContent = avg.toFixed(1) + ' fps'; minValueEl.textContent = Math.round(minFps) + ' fps'; maxValueEl.textContent = Math.round(maxFps) + ' fps'; sampleCountEl.textContent = sampleCount; } function recordFps(fps) { if (fps <= 0 || !isFinite(fps)) return; totalFps += fps; if (fps < minFps) minFps = fps; if (fps > maxFps) maxFps = fps; sampleCount++; fpsHistory.push(fps); if (fpsHistory.length > 200) fpsHistory.shift(); updateStats(); } function resetStats() { totalFps = 0; minFps = Infinity; maxFps = -Infinity; sampleCount = 0; fpsHistory = []; updateStats(); fpsStatusEl.textContent = '重置完成'; setTimeout(() => { if (currentFps >= 55) fpsStatusEl.textContent = '✅ 流畅'; else if (currentFps >= 30) fpsStatusEl.textContent = '⚠️ 一般'; else if (currentFps > 0) fpsStatusEl.textContent = '❌ 卡顿'; else fpsStatusEl.textContent = '检测中'; }, 1000); } // 帧率统计函数 - 每秒执行一次 function tick(now) { frameCount++; const delta = now - lastTime; // 每秒钟计算一次帧率 if (delta >= 1000) { // 计算这一秒内的平均帧率 currentFps = (frameCount * 1000) / delta; currentFps = Math.min(144, Math.max(0, currentFps)); // 更新显示 updateDisplay(currentFps); // 记录到统计数据 if (currentFps > 0 && isFinite(currentFps)) { recordFps(currentFps); } // 重置计数器 frameCount = 0; lastTime = now; } animationId = requestAnimationFrame(tick); } function startMonitoring() { if (animationId) cancelAnimationFrame(animationId); lastTime = performance.now(); frameCount = 0; animationId = requestAnimationFrame(tick); } resetBtn.addEventListener('click', resetStats); // 页面可见性变化处理 document.addEventListener('visibilitychange', () => { if (!document.hidden) { lastTime = performance.now(); frameCount = 0; } }); startMonitoring(); // 清理函数 window.addEventListener('beforeunload', () => { if (animationId) cancelAnimationFrame(animationId); }); console.log('FPS 检测器已启动 - 每秒更新一次'); } })();