目标
- 点击模型的某个区域时,弹出图片选择框。
- 用户选择新图片后,替换该区域的纹理。
实现步骤
1. 创建基础场景
设置 Three.js 的场景、相机、渲染器和光源。
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
// 创建场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 5);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加光源
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(10, 10, 10).normalize();
scene.add(light);
// 动画循环
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
2. 加载模型并分配初始材质
使用 GLTFLoader
加载模型,并为每个区域分配初始材质。
let model;
const loader = new GLTFLoader();
loader.load('path/to/your-model.glb', (gltf) => {
model = gltf.scene;
scene.add(model);
// 遍历模型子对象并分配初始材质
model.traverse((child) => {
if (child instanceof THREE.Mesh) {
const textureLoader = new THREE.TextureLoader();
const initialTexture = textureLoader.load('path/to/default-texture.jpg');
child.material = new THREE.MeshStandardMaterial({ map: initialTexture });
child.userData.originalMaterial = child.material; // 保存原始材质
child.userData.region = child.name || 'Unknown'; // 设置区域标识
}
});
});
3. 实现点击检测
使用 THREE.Raycaster
检测鼠标点击的模型区域。
// 创建 Raycaster 和鼠标位置变量
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
// 监听鼠标点击事件
window.addEventListener('click', (event) => {
// 将鼠标位置归一化到 -1 到 1 的范围
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// 更新射线投射器
raycaster.setFromCamera(mouse, camera);
// 检测与模型的交点
const intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0) {
const clickedObject = intersects[0].object;
// 确保点击的是模型的某个部分
if (clickedObject instanceof THREE.Mesh) {
openTextureSelector(clickedObject); // 弹出纹理选择框
}
}
});
4. 弹出图片选择框
创建一个简单的图片选择框,允许用户选择新的纹理图片。
function openTextureSelector(mesh) {
const textureSelector = document.createElement('div');
textureSelector.style.position = 'fixed';
textureSelector.style.top = '50px';
textureSelector.style.left = '50px';
textureSelector.style.backgroundColor = 'white';
textureSelector.style.padding = '10px';
textureSelector.style.zIndex = '1000';
const title = document.createElement('h3');
title.textContent = `选择新纹理(当前区域:${mesh.userData.region})`;
textureSelector.appendChild(title);
const imageList = ['texture1.jpg', 'texture2.jpg', 'texture3.jpg']; // 替换为你的纹理图片路径
imageList.forEach((imagePath) => {
const img = document.createElement('img');
img.src = imagePath;
img.style.width = '100px';
img.style.height = '100px';
img.style.margin = '5px';
img.style.cursor = 'pointer';
img.onclick = () => {
applyTexture(mesh, imagePath); // 应用选中的纹理
document.body.removeChild(textureSelector); // 关闭选择框
};
textureSelector.appendChild(img);
});
document.body.appendChild(textureSelector);
}
5. 应用新纹理
编写函数将用户选择的图片作为纹理应用到模型的对应区域。
function applyTexture(mesh, texturePath) {
const textureLoader = new THREE.TextureLoader();
const newTexture = textureLoader.load(texturePath);
// 更新材质的纹理
mesh.material.map = newTexture;
mesh.material.needsUpdate = true; // 确保材质更新
}
完整流程总结
-
加载模型:
使用GLTFLoader
加载模型,并为每个区域分配初始材质。通过userData.region
标识不同的区域。 -
点击检测:
使用THREE.Raycaster
检测鼠标点击的模型区域。 -
弹出图片选择框:
当用户点击模型时,弹出一个图片选择框,显示可用的纹理图片。 -
应用新纹理:
用户选择图片后,将其作为纹理应用到对应的模型区域。
关键点解析
-
如何确定点击的模型和区域?
- 使用
THREE.Raycaster
获取被点击的对象。 - 通过
mesh.userData.region
或mesh.name
来标识不同的区域。
- 使用
-
如何应用新纹理?
- 修改材质的
map
属性,并确保调用material.needsUpdate = true
。
- 修改材质的
-
用户体验优化:
- 在图片选择框中显示当前区域名称。
- 可以为图片选择框添加关闭按钮或限制图片数量。
前端工程师、程序员
标签:
threejs
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!