ThreeJs功能演示——多少体操纵导入导出
1、内部创建多少体导出编辑能力1)支持内部创建的面、正方体、球体
内部创建物体时,如果是三维物体,要创建聚集形状geometry,和对应的材质material。再一起创建一个三维物体。
// 存储创建的几何体列表
const geometries = [];
createPlane()
createCube()
createSphere()
addGUIForGeometry(geometries)
// 几何体创建函数
function createPlane() {
const geometry = new THREE.PlaneGeometry(1,1);
const material = new THREE.MeshBasicMaterial({color:0xffff00, side:THREE.DoubleSide})
const plane = new THREE.Mesh(geometry, material)
plane.name = "Plane";
plane.position.set(-1, -1, -1)
scene.add(plane)
geometries.push(plane)
return plane;
}
// 创建正方体
function createCube() {
const geometry = new THREE.BoxGeometry(1, 1, 1 );
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
const cube = new THREE.Mesh( geometry, material );
cube.name = 'Cube';
scene.add( cube );
geometries.push(cube);
return cube;
}
// 创建球体
function createSphere() {
const geometry = new THREE.SphereGeometry( 1, 32, 32 );
const material = new THREE.MeshBasicMaterial( {color: 0x0000ff} );
const sphere = new THREE.Mesh( geometry, material );
sphere.name = 'Sphere';
sphere.position.set(2,2,2)
scene.add( sphere );
geometries.push(sphere);
return sphere;
} 2)支持多少体的位置、角度、比例调解
通过GUI控制器调解创建物体的位置、角度、放大比例信息。
// GUI控制器
function addGUIForGeometry(geometryArr) {
const gui = new GUI();
gui.add({x:0}, 'x', -10, 10).name('Position X').onChange((value)=>{
for (let element of geometryArr) {
console.log(element.position)
element.position.set(value, element.position.y, element.position.z)
}
animate()
});
gui.add({scale:1}, 'scale', 0.1, 10).name('Scale').onChange((value)=>{
for (let element of geometryArr) {
element.scale.set(value, value, value)
}
animate()
});
gui.add({rotateX:0}, "rotateX",-Math.PI, Math.PI).name("Rotate X").onChange((value)=>{
for (let element of geometryArr) {
element.rotation.set(value, element.rotation.y, element.rotation.z)
}
animate()
})
gui.open();
} 3)支持多少体批量导出、重新导入
将3D物体的位置、形状、角度、放大序列化到json文件,支持导出。
导入时,根据物体的类型分别创建3D模型
// 导入几何体
function importGeometries() {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.json';
input.addEventListener('change', (event) => {
const file = event.target.files;
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
const geometriesData = JSON.parse(e.target.result);
geometriesData.forEach(data => {
let geometry;
let material;
switch (data.type) {
case 'Mesh':
switch (data.name) {
case 'Plane':
geometry = new THREE.PlaneGeometry(data.geometryData.vertices, data.geometryData.indices);
material = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide });
break;
case 'Cube':
geometry = new THREE.BoxGeometry(data.geometryData.vertices, data.geometryData.indices);
material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
break;
case 'Sphere':
geometry = new THREE.SphereGeometry(data.geometryData.vertices, data.geometryData.indices);
material = new THREE.MeshBasicMaterial({ color: 0x0000ff });
break;
}
const mesh = new THREE.Mesh(geometry, material);
mesh.name = data.name;
mesh.position.fromArray(data.position);
mesh.rotation.fromArray(data.rotation);
mesh.scale.fromArray(data.scale);
scene.add(mesh);
geometries.push(mesh);
break;
}
});
};
reader.readAsText(file);
}
});
input.click();
} 2、整体代码
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Three.js 多少体操纵示例</title> <style> body { margin: 0; overflow: hidden; } #camera-info { position: absolute; top: 10px; left: 10px; background-color: rgba(0, 0, 0, 0.5); color: white; padding: 10px; font-family: Arial, sans-serif; } </style></head><body><div id="camera-info"></div><script type="importmap"> { "imports": { "three": "./three.js-master/build/three.module.js", "three/addons/": "./three.js-master/examples/jsm/" } }</script><script type="module"> import * as THREE from "three" import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; // 1) 创建画布 const scene = new THREE.Scene(); scene.background = new THREE.Color( 0xa0a0a0 ); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 2) 设置 camera 位置,朝向角度 const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(0, 0, 20); // 设置相机位置 camera.lookAt(scene.position); // 让相机朝向场景中心 // 设置控制轨道 const controls = new OrbitControls( camera, renderer.domElement ); controls.target.set( 0, 0.1, 0 ); controls.update(); controls.minDistance = 0.5; controls.maxDistance = 1000; controls.maxPolarAngle = 0.5 * Math.PI; // 5) 支持动态显示摄像头位置、角度、缩放信息 const cameraInfo = document.getElementById('camera-info'); function updateCameraInfo() { cameraInfo.innerHTML = ` 摄像头信息:<br> 位置: (${camera.position.x.toFixed(2)}, ${camera.position.y.toFixed(2)}, ${camera.position.z.toFixed(2)})<br> 角度: (${camera.rotation.x.toFixed(2)}, ${camera.rotation.y.toFixed(2)}, ${camera.rotation.z.toFixed(2)})<br> 缩放: ${camera.zoom.toFixed(2)} `; } updateCameraInfo(); // 渲染循环 function animate() { requestAnimationFrame(animate); updateCameraInfo(); renderer.render(scene, camera); } animate(); // 存储创建的几何体列表
const geometries = [];
createPlane()
createCube()
createSphere()
addGUIForGeometry(geometries)
// 几何体创建函数
function createPlane() {
const geometry = new THREE.PlaneGeometry(1,1);
const material = new THREE.MeshBasicMaterial({color:0xffff00, side:THREE.DoubleSide})
const plane = new THREE.Mesh(geometry, material)
plane.name = "Plane";
plane.position.set(-1, -1, -1)
scene.add(plane)
geometries.push(plane)
return plane;
}
// 创建正方体
function createCube() {
const geometry = new THREE.BoxGeometry(1, 1, 1 );
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
const cube = new THREE.Mesh( geometry, material );
cube.name = 'Cube';
scene.add( cube );
geometries.push(cube);
return cube;
}
// 创建球体
function createSphere() {
const geometry = new THREE.SphereGeometry( 1, 32, 32 );
const material = new THREE.MeshBasicMaterial( {color: 0x0000ff} );
const sphere = new THREE.Mesh( geometry, material );
sphere.name = 'Sphere';
sphere.position.set(2,2,2)
scene.add( sphere );
geometries.push(sphere);
return sphere;
} // GUI控制器
function addGUIForGeometry(geometryArr) {
const gui = new GUI();
gui.add({x:0}, 'x', -10, 10).name('Position X').onChange((value)=>{
for (let element of geometryArr) {
console.log(element.position)
element.position.set(value, element.position.y, element.position.z)
}
animate()
});
gui.add({scale:1}, 'scale', 0.1, 10).name('Scale').onChange((value)=>{
for (let element of geometryArr) {
element.scale.set(value, value, value)
}
animate()
});
gui.add({rotateX:0}, "rotateX",-Math.PI, Math.PI).name("Rotate X").onChange((value)=>{
for (let element of geometryArr) {
element.rotation.set(value, element.rotation.y, element.rotation.z)
}
animate()
})
gui.open();
} function handleKeyDown(event) { switch (event.key) { case 'e': exportToJSON(geometries) break; case 'r': clearGeometries(geometries) break; case 'i': importGeometries(geometries) break; } } document.addEventListener('keydown', handleKeyDown); function exportToJSON(geometryList) { const geometriesData = geometryList.map(geometry => { return { name: geometry.name, position: geometry.position.toArray(), rotation: geometry.rotation.toArray(), scale: geometry.scale.toArray(), // 根据多少体类型添加更多特定信息 type: geometry.type, geometryData: geometry.geometry.toJSON() }; }); const blob = new Blob(, { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'geometries.json'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } // 清除多少体 function clearGeometries(geoArr) { geometries.forEach(geometry => scene.remove(geometry)); geometries.length = 0; } // 导入几何体
function importGeometries() {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.json';
input.addEventListener('change', (event) => {
const file = event.target.files;
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
const geometriesData = JSON.parse(e.target.result);
geometriesData.forEach(data => {
let geometry;
let material;
switch (data.type) {
case 'Mesh':
switch (data.name) {
case 'Plane':
geometry = new THREE.PlaneGeometry(data.geometryData.vertices, data.geometryData.indices);
material = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide });
break;
case 'Cube':
geometry = new THREE.BoxGeometry(data.geometryData.vertices, data.geometryData.indices);
material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
break;
case 'Sphere':
geometry = new THREE.SphereGeometry(data.geometryData.vertices, data.geometryData.indices);
material = new THREE.MeshBasicMaterial({ color: 0x0000ff });
break;
}
const mesh = new THREE.Mesh(geometry, material);
mesh.name = data.name;
mesh.position.fromArray(data.position);
mesh.rotation.fromArray(data.rotation);
mesh.scale.fromArray(data.scale);
scene.add(mesh);
geometries.push(mesh);
break;
}
});
};
reader.readAsText(file);
}
});
input.click();
}</script></body></html>
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]