Three.js画布动态Resize时消失问题求助
问题分析与解决方案
我找到了问题的核心原因:页面首次加载时,winit函数先调用了wrapResize(),此时renderer还未被初始化。当你取消注释wrapResize2里的Three.js resize代码时,执行renderer.setSize()会直接抛出"renderer is undefined"的错误,导致后续的init()、cubeInit()等代码完全中断执行——这意味着canvas元素从来没有被添加到DOM中,立方体自然也就看不到了。
具体修复步骤
1. 给Three.js resize代码添加存在性检查
在wrapResize2函数中,只有当renderer已经被创建时,才执行调整画布和相机的代码,避免首次加载时的报错:
wrapResize2 = function(wW,wH,cW,cH) { if ((wH < cH) || (fullScreen==1)) { wrap.style.width = wW + 'px'; wrap.style.height = wH + 'px'; back.style.width = wW + 'px'; back.style.height = wH + 'px'; front.style.width = wW + 'px'; front.style.height = wH + 'px'; // 检查renderer是否已初始化 if (renderer) { renderer.setSize(wW,wH); camera.aspect = wW/wH; camera.updateProjectionMatrix(); } sriJsW = wW; sriJsH = wH; } else { wrap.style.height = cH + 'px'; wrap.style.width = cW + 'px'; back.style.height = cH + 'px'; back.style.width = cW + 'px'; front.style.height = cH + 'px'; front.style.width = cW + 'px'; // 检查renderer是否已初始化 if (renderer) { renderer.setSize(cW,cH); camera.aspect = cW/cH; camera.updateProjectionMatrix(); } sriJsH = cH; sriJsW = cW; } },
2. 优化初始化逻辑,清理旧资源
每次执行init()前,先移除旧的canvas元素并释放Three.js资源,避免重复创建导致DOM冗余和内存泄漏:
init = function () { // 清理旧的renderer和canvas if (renderer) { sriJs.removeChild(renderer.domElement); renderer.dispose(); // 释放WebGL资源 } camera = new THREE.PerspectiveCamera(45, sriJsW/sriJsH, 1, 20000); camera.position.z = 250; scene = new THREE.Scene(); renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true}); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(sriJsW,sriJsH); sriJs.appendChild(renderer.domElement); },
3. 优化屏幕旋转事件处理
orientationchange事件不需要重新执行完整的初始化流程,只需要调整布局大小即可,修改事件绑定:
// 替换原来的orientationchange绑定 window.addEventListener('orientationchange', wrapResize, false);
修复逻辑说明
- 存在性检查确保首次加载时不会执行未初始化的renderer代码,避免报错中断流程;
- 清理旧资源避免DOM中堆积多个canvas元素,同时释放WebGL资源防止内存泄漏;
- 简化屏幕旋转的处理逻辑,只做必要的尺寸调整,提升性能。
内容的提问来源于stack exchange,提问作者Mikey Muss
相关产品推荐
相关产品推荐

