From 0f6504a46bd527a3a3620a2c501b0102ba93b717 Mon Sep 17 00:00:00 2001 From: hehh Date: Thu, 4 Dec 2025 18:27:47 +0800 Subject: [PATCH] =?UTF-8?q?perf(me.html):=20=E4=BC=98=E5=8C=96DOM=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E4=BB=A5=E6=8F=90=E5=8D=87=E9=A1=B5=E9=9D=A2=E6=80=A7?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入DOM_CACHE对象缓存频繁访问的DOM元素 - 修改safeUpdateText和safeClass函数以接受DOM元素而非ID - 替换所有document.getElementById调用为DOM_CACHE中的缓存引用 - 减少重复DOM查询,提高渲染和交互性能 --- me.html | 92 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/me.html b/me.html index d3b5cd1..42a67e3 100644 --- a/me.html +++ b/me.html @@ -406,15 +406,39 @@ APP_STATE.namasteStableFrames = 0; + // 缓存频繁访问的DOM元素以提高性能 + const DOM_CACHE = { + // 加载屏幕相关元素 + startScreen: document.getElementById('start-screen'), + loaderMsg: document.getElementById('loader-msg'), + permHint: document.getElementById('perm-guide'), + + // 叙事层相关元素 + narrativeLayer: document.getElementById('narrative-layer'), + nTitle: document.getElementById('n-title'), + nSub: document.getElementById('n-sub'), + + // UI层相关元素 + uiLayer: document.getElementById('ui-layer'), + sysStatus: document.getElementById('sys-status'), + themeDisplay: document.getElementById('theme-display'), + langDisplay: document.getElementById('lang-display'), + mainHint: document.getElementById('main-hint'), + subHint: document.getElementById('sub-hint'), + exitBtn: document.getElementById('exit-btn'), + + // 其他元素 + canvasContainer: document.getElementById('canvas-container'), + inputVideo: document.getElementById('input-video') + }; + // 安全DOM操作,防止报错 - function safeUpdateText(id, text) { - const el = document.getElementById(id); - if (el) el.innerText = text; + function safeUpdateText(element, text) { + if (element) element.innerText = text; } - function safeClass(id, method, className) { - const el = document.getElementById(id); - if (el) el.classList[method](className); + function safeClass(element, method, className) { + if (element) element.classList[method](className); } /** @@ -451,8 +475,8 @@ // 应用主题 document.documentElement.setAttribute('data-theme', ENV.theme); - safeUpdateText('theme-display', `THEME: ${ENV.lang.toUpperCase() === 'en' ? ENV.theme.toUpperCase() : ENV.theme === 'day' ? '白天' : '黑夜'}`); - safeUpdateText('lang-display', ENV.lang.toUpperCase() === 'CN' ? '中文' : 'English'); + safeUpdateText(DOM_CACHE.themeDisplay, `THEME: ${ENV.lang.toUpperCase() === 'en' ? ENV.theme.toUpperCase() : ENV.theme === 'day' ? '白天' : '黑夜'}`); + safeUpdateText(DOM_CACHE.langDisplay, ENV.lang.toUpperCase() === 'CN' ? '中文' : 'English'); /** * ============================================================================ @@ -508,17 +532,17 @@ clearInterval(loadTimer); return; } - safeUpdateText('loader-msg', CONTENT.load[loadIdx > maxIdx ? maxIdx : loadIdx]); + safeUpdateText(DOM_CACHE.loaderMsg, CONTENT.load[loadIdx > maxIdx ? maxIdx : loadIdx]); loadIdx++; }, 600); // 权限超时提示 setTimeout(() => { - if (!APP_STATE.isLoaded) safeClass('perm-hint', 'add', 'show'); + if (!APP_STATE.isLoaded) safeClass(DOM_CACHE.permHint, 'add', 'show'); }, 5000); - safeUpdateText('main-hint', CONTENT.hints.main); - safeUpdateText('sub-hint', CONTENT.hints.sub); + safeUpdateText(DOM_CACHE.mainHint, CONTENT.hints.main); + safeUpdateText(DOM_CACHE.subHint, CONTENT.hints.sub); /** * ============================================================================ @@ -548,7 +572,7 @@ renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); renderer.setClearColor(0x000000, 0); - document.getElementById('canvas-container').appendChild(renderer.domElement); + DOM_CACHE.canvasContainer.appendChild(renderer.domElement); const composer = new THREE.EffectComposer(renderer); composer.addPass(new THREE.RenderPass(scene, camera)); @@ -789,10 +813,10 @@ APP_STATE.mode = 'UNLOCKED'; // UI - safeClass('main-hint', 'add', 'hidden'); // 隐藏主提示 (CSS需支持或直接display) - document.getElementById('main-hint').style.display = 'none'; - document.getElementById('sub-hint').style.display = 'none'; - safeClass('exit-btn', 'add', 'visible'); + safeClass(DOM_CACHE.mainHint, 'add', 'hidden'); // 隐藏主提示 (CSS需支持或直接display) + DOM_CACHE.mainHint.style.display = 'none'; + DOM_CACHE.subHint.style.display = 'none'; + safeClass(DOM_CACHE.exitBtn, 'add', 'visible'); // 粒子爆炸效果 explode(100); @@ -804,13 +828,13 @@ APP_STATE.mode = 'LOCKED'; APP_STATE.exitCooldownUntil = Date.now() + 2000; - document.getElementById('main-hint').style.display = 'block'; - document.getElementById('sub-hint').style.display = 'block'; - safeClass('exit-btn', 'remove', 'visible'); - safeClass('narrative-layer', 'remove', 'show-text'); + DOM_CACHE.mainHint.style.display = 'block'; + DOM_CACHE.subHint.style.display = 'block'; + safeClass(DOM_CACHE.exitBtn, 'remove', 'visible'); + safeClass(DOM_CACHE.narrativeLayer, 'remove', 'show-text'); APP_STATE.unlockProgress = 0; - safeUpdateText('main-hint', CONTENT.hints.main); + safeUpdateText(DOM_CACHE.mainHint, CONTENT.hints.main); clearTimeout(narrativeTimer); explode(50); } @@ -825,9 +849,9 @@ function startNarrative() { let idx = 0; - const nTitle = document.getElementById('n-title'); - const nSub = document.getElementById('n-sub'); - const layer = document.getElementById('narrative-layer'); + const nTitle = DOM_CACHE.nTitle; + const nSub = DOM_CACHE.nSub; + const layer = DOM_CACHE.narrativeLayer; // 必须检查元素是否存在 if (!nTitle || !nSub || !layer) return; @@ -873,18 +897,18 @@ // Loader logic if (!APP_STATE.isLoaded) { APP_STATE.isLoaded = true; - const loader = document.getElementById('start-screen'); + const loader = DOM_CACHE.startScreen; loader.style.opacity = 0; - document.getElementById('ui-layer').style.opacity = 1; + DOM_CACHE.uiLayer.style.opacity = 1; setTimeout(() => loader.style.display = 'none', 1000); } const landmarks = results.multiHandLandmarks; - const sysStatus = document.getElementById('sys-status'); + const sysStatus = DOM_CACHE.sysStatus; if (landmarks && landmarks.length > 0) { APP_STATE.handCount = landmarks.length; - safeUpdateText('sys-status', `LINKED (${APP_STATE.handCount})`); + safeUpdateText(sysStatus, `LINKED (${APP_STATE.handCount})`); if (sysStatus) sysStatus.style.color = ENV.theme === 'day' ? '#0044cc' : '#00ff00'; // 坐标处理 (镜像) @@ -922,20 +946,20 @@ } const targetFrames = 20; const pct = Math.min(100, Math.round(APP_STATE.namasteStableFrames / targetFrames * 100)); - if (pct > 0) safeUpdateText('main-hint', `${CONTENT.hints.unlocking} ${pct}%`); + if (pct > 0) safeUpdateText(DOM_CACHE.mainHint, `${CONTENT.hints.unlocking} ${pct}%`); if (APP_STATE.namasteStableFrames >= targetFrames) enterArchive(); - if (!ok && APP_STATE.namasteStableFrames === 0) safeUpdateText('main-hint', CONTENT.hints.main); + if (!ok && APP_STATE.namasteStableFrames === 0) safeUpdateText(DOM_CACHE.mainHint, CONTENT.hints.main); } } else { APP_STATE.handCount = 0; - safeUpdateText('sys-status', 'SEARCHING...'); + safeUpdateText(sysStatus, 'SEARCHING...'); if (sysStatus) sysStatus.style.color = 'inherit'; APP_STATE.unlockProgress = 0; - safeUpdateText('main-hint', CONTENT.hints.main); + safeUpdateText(DOM_CACHE.mainHint, CONTENT.hints.main); } }); - const videoElement = document.getElementById('input-video'); + const videoElement = DOM_CACHE.inputVideo; const cameraUtils = new Camera(videoElement, { onFrame: async () => { await hands.send({image: videoElement});