/* 尺寸自适应与按需渲染循环 */ /* ---- loop & on-demand rendering ---- */ let curW = 0, curH = 0; function resize() { if (cv.style.display === 'none') return; const w = stage.clientWidth, h = stage.clientHeight; if (!w || !h) return; if (w !== curW || h !== curH) { curW = w; curH = h; rend.setSize(w, h, false); cam.aspect = w / h; cam.updateProjectionMatrix(); requestRender(); } } if (window.ResizeObserver) { new ResizeObserver(() => resize()).observe(stage); } else { window.addEventListener('resize', resize); } document.getElementById('ttl').textContent = NMOT + ' 电机人形机器人手臂'; document.getElementById('ver').textContent = DATA.layout.ver + ' · 迭代 ' + DATA.layout.it + ' · 上臂' + DATA.layout.L1 + ' 前臂' + DATA.layout.L2 + ' mm'; function updStat() { const el = document.getElementById('stat'); const tri = (typeof meshes !== 'undefined' && meshes) ? meshes.reduce((a, m) => a + (m.userData.triCount || 0), 0) : 0; const nScr = (typeof meshes !== 'undefined' && meshes) ? meshes.filter(m => m.userData.screw).length : 0; const nTot = (typeof meshes !== 'undefined' && meshes) ? meshes.length : 0; if (el) el.textContent = '零件 ' + (nTot - nScr) + (nScr ? ' + 螺钉 ' + nScr : '') + ' · 三角面 ' + (tri/1000).toFixed(0) + 'k · ' + '爆炸 ' + Math.round(expl*100) + '%'; } updStat(); /* 按需渲染:needRender 由 requestRender() 置位(所有交互与状态变化都已调用它; 旧版置位后全文件无读取点,等于恒以显示器刷新率空转满帧渲染)。 装配图页画布隐藏时【不清标志】,切回三维页由 tab 处理器 resize()+requestRender() 补渲染。 preserveDrawingBuffer 必须保持 true:不重绘时靠它保住最后一帧画面。 */ function loop() { if (needRender && cv.style.display !== 'none') { needRender = false; resize(); updCam(); rend.render(scene, cam); } requestAnimationFrame(loop); } requestAnimationFrame(loop);