You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js窗口缩放3D模型不适配及TypeError错误求助

问题描述
  • 网站Hero区域背景集成3D模型后,基础功能正常,但手动调整窗口尺寸时,3D模型无法适配新的窗口大小。
  • 控制台抛出错误:TypeError: Cannot read properties of undefined (reading 'position'),错误指向Three.js代码第69行。
解决方案

1. 修复控制台错误

错误源于3D模型的异步加载机制:animate函数会在模型加载完成前就执行,此时model变量仍为undefined,直接访问model.position就会触发报错。

修改animate函数,增加模型存在性判断:

function animate() {
  requestAnimationFrame(animate);

  // 仅当模型加载完成后才修改位置
  if (model) {
    model.position.y = -2;
  }
  
  controls.update();
  renderer.render(scene, camera);
}

2. 实现窗口尺寸自适应

需要监听窗口的resize事件,动态更新相机的宽高比与渲染器的尺寸,同时更新相机的投影矩阵以保证画面正确适配:

在JavaScript代码中添加以下监听逻辑:

// 监听窗口尺寸变化
window.addEventListener('resize', () => {
  // 更新相机宽高比
  camera.aspect = window.innerWidth / window.innerHeight;
  // 必须更新投影矩阵才能让宽高比生效
  camera.updateProjectionMatrix();
  // 更新渲染器尺寸以匹配窗口
  renderer.setSize(window.innerWidth, window.innerHeight);
});
修改后的完整JavaScript代码
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

const heroSection = document.querySelector("#hero-section");
heroSection.appendChild(renderer.domElement);

// 导入3D模型
const loader = new GLTFLoader();
let model;
loader.load(
  "./scene.gltf",
  function (gltf) {
    model = gltf.scene;
    scene.add(gltf.scene);
  },
  undefined,
  function (error) {
    console.error(error);
  }
);

// 控制相机移动
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableZoom = false;

const ambientLight = new THREE.AmbientLight(0xffffff);
const light = new THREE.AmbientLight(0x404040);
scene.add(ambientLight, light);

// 设置相机位置
camera.position.set(0, 1, 5);
controls.update();

// 监听窗口尺寸变化
window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

function animate() {
  requestAnimationFrame(animate);

  if (model) {
    model.position.y = -2;
  }
  
  controls.update();
  renderer.render(scene, camera);
}

animate();
补充说明
  • CSS和HTML代码无需修改,现有布局已保证canvas在Hero区域内全屏显示。
  • 若模型加载后位置仍不符合预期,可调整model.position.y的数值,或在模型加载完成的回调中一次性设置位置(避免在animate中重复设置)。

内容的提问来源于stack exchange,提问作者user13069641

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:32:38