Three.js 绑定复选框事件实现TWEEN控制3D模型移动问题求助
问题排查结果
你的代码主要存在3个核心问题导致复选框事件不生效:
zoom函数从未被调用,复选框的change事件监听没有成功绑定到页面元素上model2是init函数的局部变量,zoom函数中无法访问,执行时会抛出变量未定义的错误- 重复调用了
animate函数,会导致渲染逻辑重复执行
修正步骤
1. 调整变量作用域
将model1、model2、model3的声明移到全局作用域,和scene、camera等变量放在同一层级
2. 执行zoom函数绑定事件
在全局调用init()之后执行zoom(),完成复选框事件绑定
3. 删除冗余调用
删掉Promise.all回调里的animate()调用,避免重复执行渲染逻辑
修正后完整代码
<script> let scene, camera, renderer, controls; // 把模型变量提到全局 let model1, model2, model3; function loadModel(url) { return new Promise(resolve => { new THREE.GLTFLoader().load(url, resolve); }); } function init() { scene = new THREE.Scene(); scene.background = new THREE.Color(0xBDBDBD); camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 5000); camera.rotation.y = 45 / 180 * Math.PI; camera.position.x = 40; camera.position.y = 0; camera.position.z = 40; hlight = new THREE.AmbientLight(0x404040, 1); scene.add(hlight); directionalLight = new THREE.DirectionalLight(0x333333, 1); directionalLight.position.set(2, 1, 0); directionalLight.castShadow = true; scene.add(directionalLight); renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); controls = new THREE.OrbitControls(camera, renderer.domElement); let p1 = loadModel('./combination/BOX1/box1.gltf').then(result => { model1 = result.scene.children[0]; }); let p2 = loadModel('./combination/BOX2/box2.gltf').then(result => { model2 = result.scene.children[0]; }); let p3 = loadModel('./combination/BOX3/box3.gltf').then(result => { model3 = result.scene.children[0]; }); Promise.all([p1, p2, p3]).then(() => { model1.position.set(0, 5, 0); model2.position.set(0, 25, 0); model3.position.set(-1.05, 20, 0.58); scene.add(model1); scene.add(model2); scene.add(model3); }); } function zoom() { var move = document.getElementById('controllr'); move.addEventListener('change', (e) => { // 每次触发新动画前先停止上一个未完成的动画,避免冲突 TWEEN.removeAll(); if (e.currentTarget.checked) { new TWEEN.Tween(model2.position).to({ x: 0, y: 50, z: 0 }, 4000).start(); } else { new TWEEN.Tween(model2.position).to({ x: 0, y: 25, z: 0 }, 4000).start(); } }); } function animate(time) { TWEEN.update(time); renderer.render(scene, camera); requestAnimationFrame(animate); } init(); // 调用zoom绑定事件 zoom(); animate(); </script>
不用TWEEN的替代实现方案
你可以直接在animate函数里手动实现位置缓动,不需要引入额外的TWEEN库:
- 全局新增两个变量:
targetY = 25、ease = 0.02 - 复选框触发时直接修改
targetY的值为50或25 - 在animate函数中每帧更新
model2.position.y += (targetY - model2.position.y) * ease即可实现平滑移动效果
内容的提问来源于stack exchange,提问作者Tham Tantisunthorn
相关产品推荐
相关产品推荐

