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

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库:

  1. 全局新增两个变量:targetY = 25、ease = 0.02
  2. 复选框触发时直接修改targetY的值为50或25
  3. 在animate函数中每帧更新model2.position.y += (targetY - model2.position.y) * ease即可实现平滑移动效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 05:45:05