
本文详解 Three.js 中窗口重置尺寸时的正确处理流程,重点解决因 updateProjectionMatrix() 调用顺序不当导致的最大化窗口后画面拉伸、渲染异常等问题。
本文详解 three.js 中窗口重置尺寸时的正确处理流程,重点解决因 `updateprojectionmatrix()` 调用顺序不当导致的最大化窗口后画面拉伸、渲染异常等问题。
在 Three.js 应用中,响应浏览器窗口尺寸变化(如拖拽调整、点击最大化/最小化)是保证 3D 场景视觉一致性的关键环节。你提供的代码逻辑基本正确,但存在一个关键执行顺序缺陷:camera.updateProjectionMatrix() 必须在 camera.aspect 更新之后调用,否则新宽高比不会被纳入投影矩阵计算,导致渲染画面发生水平或垂直拉伸——尤其在 Windows 系统点击最大化按钮时,浏览器可能触发一次“突变式”尺寸更新(而非平滑拖拽),该问题会更加明显。
✅ 正确的 resize 处理顺序如下:
window.addEventListener('resize', () => {
sizes.width = window.innerWidth;
sizes.height = window.innerHeight;
// ✅ 先更新 aspect 比值
camera.aspect = sizes.width / sizes.height;
// ✅ 再更新投影矩阵,使其基于最新 aspect 重建
camera.updateProjectionMatrix();
// ✅ 同步更新渲染器尺寸(注意:setSize 第二个参数为 height,非 autoScale)
renderer.setSize(sizes.width, sizes.height);
});⚠️ 注意事项:
使用约定式提交(Conventional Commits)生成标准化的 Git 提交信息。适用于以下场景: (1) 暂存更改时需要提交信息; (2) 审查 diff 时希望获得结构化摘要; (3) 编写 PR 描述或变更日志(changelog)条目; (4) 用户明确要求“为本次更改编写提交信息”。 该功能会分析已暂存/未暂存的 diff,并生成按类型(type)划分范围的提交信息。
-
camera.updateProjectionMatrix()不会自动读取camera.aspect的当前值——它仅根据 当前已设置的aspect、fov、near、far等参数重新计算内部投影矩阵。因此,若先调用该方法,再修改aspect,则本次更新将失效。 -
renderer.setSize(width, height, false)中第三个参数false(默认为true)可禁用渲染器自动缩放 canvas(推荐显式设为false,避免 CSS 缩放干扰像素精度)。 - 对于高 DPI 屏幕(如 Retina),建议结合
window.devicePixelRatio进行像素比适配:
const dpr = window.devicePixelRatio || 1; renderer.setPixelRatio(dpr); renderer.setSize(sizes.width, sizes.height, false);
最后,确保动画循环使用标准 requestAnimationFrame,且无阻塞逻辑:
const loop = () => {
renderer.render(scene, camera);
requestAnimationFrame(loop); // 推荐使用全局 requestAnimationFrame,无需 window. 前缀
};
loop();? 总结:Three.js 窗口响应的核心原则是——状态更新(aspect)→ 矩阵重建(updateProjectionMatrix)→ 渲染同步(setSize)。只要严格遵循此顺序,无论是手动拖拽、双击标题栏、还是点击最大化按钮,场景均能稳定保持原始纵横比与清晰度。

















