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

Three.js中如何让先执行的init函数获取EventListener传递的图片URL

问题分析

你当前的核心问题是页面加载时直接调用了init(),此时图片还未上传,自然只能拿到空的URL;而上传图片后再次调用init(userImageURL)会重复初始化整个Three.js场景,既冗余又不符合你“init优先执行且能获取更新后URL”的需求。

解决方案

以下两种方案可以解决你的问题,核心思路是避免重复初始化场景,仅在需要时更新纹理:

方案1:首次上传时初始化场景,后续上传仅更新纹理

去掉页面加载时的init()调用,改为首次上传图片时初始化场景,之后上传图片只更新模型纹理:

var userImageURL = '';
var img1_input = document.getElementById('img1-input');
// 声明全局场景变量,方便后续更新操作
let scene, modelTexture;

img1_input.addEventListener('change', function(e) {
    var userImage = e.target.files[0];
    userImageURL = URL.createObjectURL(userImage);
    console.log(userImageURL);
    
    if (!scene) {
        // 首次上传图片,初始化Three.js场景
        init(userImageURL);
    } else {
        // 后续上传,仅更新纹理
        updateModelTexture(userImageURL);
    }
})

function init(userimg1) {
    console.log(userimg1);
    // 初始化Three.js场景、相机、渲染器等核心组件
    scene = new THREE.Scene();
    // ...此处保留你原有的渲染初始化代码
    
    // 创建初始纹理并应用到模型
    modelTexture = new THREE.TextureLoader().load(userimg1, () => {
        console.log('初始纹理加载完成');
    });
    // 将纹理绑定到模型材质(示例)
    // const material = new THREE.MeshBasicMaterial({ map: modelTexture });
    // const mesh = new THREE.Mesh(yourGeometry, material);
    // scene.add(mesh);
}

function updateModelTexture(newURL) {
    console.log(newURL);
    // 加载新纹理并替换旧纹理
    new THREE.TextureLoader().load(newURL, (newTexture) => {
        // 释放旧纹理内存,避免内存泄漏
        modelTexture.dispose();
        modelTexture = newTexture;
        // 更新模型材质的纹理并标记为需要更新
        // mesh.material.map = modelTexture;
        // mesh.material.needsUpdate = true;
    });
}

方案2:提前初始化场景,用默认纹理占位,上传后更新

如果必须在页面加载时就执行init(),可以先使用一张默认空白图作为初始纹理,上传图片后再替换为用户上传的图片:

var userImageURL = '';
var img1_input = document.getElementById('img1-input');
let scene, modelMesh;

// 页面加载时立即初始化场景
init();

img1_input.addEventListener('change', function(e) {
    var userImage = e.target.files[0];
    userImageURL = URL.createObjectURL(userImage);
    console.log(userImageURL);
    // 调用纹理更新方法
    updateModelTexture(userImageURL);
})

function init() {
    console.log('场景初始化完成');
    // 初始化Three.js场景、相机、渲染器等
    scene = new THREE.Scene();
    // ...此处保留你原有的渲染初始化代码
    
    // 使用默认空白图创建初始纹理
    const defaultTexture = new THREE.TextureLoader().load('path/to/blank-image.png');
    const material = new THREE.MeshBasicMaterial({ map: defaultTexture });
    // 假设你已有对应的几何体
    modelMesh = new THREE.Mesh(yourGeometry, material);
    scene.add(modelMesh);
}

function updateModelTexture(newURL) {
    console.log(newURL);
    new THREE.TextureLoader().load(newURL, (newTexture) => {
        // 释放旧纹理内存
        modelMesh.material.map.dispose();
        // 更新纹理并通知Three.js材质已变更
        modelMesh.material.map = newTexture;
        modelMesh.material.needsUpdate = true;
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 14:18:25