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

通过下拉菜单动态加载3D模型至容器的JS实现问题

问题分析与修复方案

核心问题点

  • 变量作用域错误:通过javascript:伪协议定义的var model是局部变量,无法被全局的Three.js脚本访问;且URL字符串未加引号,存在语法错误。
  • 硬编码占位符未替换:loadOBJ函数中直接使用字符串'$model',而非引用实际变量。
  • CSS选择器缺失类前缀:样式中dropbtn、dropdown等选择器未加.,导致样式完全不生效。
  • 模型切换未清理旧实例:切换模型时未移除场景中的旧模型,会导致内存泄漏和渲染异常。

修复后的完整代码

<style>
/* 修复CSS选择器,添加类前缀 */
.dropbtn {
    background-color: #04AA6D;
    color: white;
    padding: 16px;
    font-size: 16px;
    border: none;
}
.dropdown {
    position: relative;
    display: inline-block;
}
.dropdown-content {
    display: none;
    position: absolute;
    background-color: #f1f1f1;
    min-width: 160px;
    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
    z-index: 1;
}
.dropdown-content a {
    color: black;
    padding: 12px 16px;
    text-decoration: none;
    display: block;
}
.dropdown-content a:hover {background-color: #ddd;}
.dropdown:hover .dropdown-content {display: block;}
.dropdown:hover .dropbtn {background-color: #3e8e41;}
</style>
<body>
<div class="dropdown">
    <button class="dropbtn">Model</button>
    <div class="dropdown-content">
        <!-- 绑定点击事件,调用全局切换函数,传递URL -->
        <a href="javascript:switchModel('https://s3-us-west-2.amazonaws.com/s.cdpn.io/127738/banana.obj')">Banana Model</a>
        <a href="javascript:switchModel('https://s3-us-west-2.amazonaws.com/s.cdpn.io/127738/another-model.obj')">Another Model</a>
    </div>
</div>
<canvas id="scene"></canvas>

<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/84/three.min.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/127738/OBJLoader.js'></script>
<script>
var renderer, scene, camera, currentModel;
var ww = window.innerWidth, wh = window.innerHeight;

function init(){
    renderer = new THREE.WebGLRenderer({canvas : document.getElementById('scene')});
    renderer.setSize(ww,wh);
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(50,ww/wh, 0.1, 10000 );
    camera.position.set(0,0,500);
    scene.add(camera);

    // 添加光源
    const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
    directionalLight.position.set( 0, 0, 350 );
    directionalLight.lookAt(new THREE.Vector3(0,0,0));
    scene.add( directionalLight );

    // 初始化加载默认模型
    loadOBJ('https://s3-us-west-2.amazonaws.com/s.cdpn.io/127738/banana.obj');
}

// 封装加载模型函数,接收URL参数
function loadOBJ(modelUrl){
    const manager = new THREE.LoadingManager();
    const loader = new THREE.OBJLoader( manager );
    loader.load(modelUrl, addModelInScene);
}

// 添加模型到场景,并处理旧模型清理
function addModelInScene(object){
    // 移除旧模型并释放内存
    if(currentModel){
        scene.remove(currentModel);
        currentModel.traverse(child => {
            if(child instanceof THREE.Mesh){
                child.geometry.dispose();
                child.material.dispose();
            }
        });
    }
    currentModel = object;
    // 模型位置与旋转设置
    currentModel.rotation.x = Math.PI/2;
    currentModel.position.y = -200;
    currentModel.position.z = 50;
    // 处理模型材质
    object.traverse( function ( child ) {
        if(child instanceof THREE.Mesh){
            child.material.color = new THREE.Color(0X00FF00);
            child.geometry.computeVertexNormals();
        }
    });
    scene.add(currentModel);
    // 启动渲染(避免重复调用)
    if(!render.isRunning){
        render();
    }
}

// 全局切换模型函数,供下拉菜单调用
function switchModel(modelUrl){
    loadOBJ(modelUrl);
}

let render = function () {
    render.isRunning = true;
    requestAnimationFrame(render);
    if(currentModel){
        currentModel.rotation.z += .01;
    }
    renderer.render(scene, camera);
};

init();
</script>
</body>

关键修改说明

  1. 修复变量作用域:定义全局函数switchModel,下拉菜单通过该函数直接传递模型URL,避免局部变量无法访问的问题。
  2. 动态加载模型:loadOBJ函数改为接收URL参数,替换原硬编码的占位符,实现模型动态切换。
  3. 修复CSS样式:为所有类选择器添加.前缀,确保下拉菜单样式正常显示。
  4. 清理旧模型:切换模型时移除场景中的旧模型,并释放几何体和材质内存,防止内存泄漏。
  5. 优化渲染逻辑:渲染函数中判断模型是否存在,避免空指针错误;标记渲染状态,防止重复启动渲染循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 02:25:48