请马上登录,朋友们都在花潮里等着你哦:)
您需要 登录 才可以下载或查看,没有账号?立即注册
x
以下代码,使用 cubes 数组变量保存立方体对象,每一个对象记为 { id: id, name: 'name', step: step },其中,id 指向所创建的立方体,name 指向立方体的名称,step 指向立方体运动歩幅。然后通过 three.js 射线类判断被点击的图形对象,若和 cubes 存储的 name 相一致,则驱动该图形对象的运动歩幅,从而达到每一个图形对象均可独立控制的目的。
<script type="module">
import * as THREE from 'https://esm.sh/three'; // 导入three.js模块
// 初始化场景、相机、渲染器
const scene = new THREE.Scene;
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
let cubes = [], intersects = []; // 立方体合集、几何体合集
// 正方体几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
geometry.rotateX(Math.PI / 3);
geometry.rotateY(Math.PI / 2);
// 创建两种标准材质 : 一种各面随机色,另一种金色
const material1 = Array.from({length: 6}, () => new THREE.MeshStandardMaterial({ color: 0xffffff * Math.random() }));
const material2 = new THREE.MeshStandardMaterial({ color: 0xffd700 });
const cube1 = new THREE.Mesh(geometry, material1);
const cube2 = new THREE.Mesh(geometry, material2);
cube1.position.y += 1;
cube2.position.y += -1;
cube1.name = 'cube1';
cube2.name = 'cube2';
cubes.push({ id: cube1, name: 'cube1', step: 0.01 }, { id: cube2, name: 'cube2', step: 0.01 });
scene.add(cube1, cube2);
// 环境光
const AmbientLight = new THREE.AmbientLight('yellow')
scene.add(AmbientLight)
// 自然光
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x000000, 1)
hemiLight.position.set(0, 100, 0)
scene.add(hemiLight)
// 以下借助three射线类判断图形和设备指针的位置关系
let raycaster = new THREE.Raycaster(); // 实例化射线拾取模型
const pointer = new THREE.Vector2(); // 实例化二维向量点结构
// 判断函数 :检测指针是否在three绘制的图形上
const isMess = (event) => {
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
intersects = raycaster.intersectObjects([cube1, cube2], true); // 参数true表示为不拾取图形对象的子对象
return intersects.length > 0;
}
// 动画 :根据 step 变量值驱动对象运动或不运动
const animate = () => {
cubes.forEach(cube => cube.id.rotation.y += cube.step);
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
// 页面单击事件 :点击到立方体对象控制其 step 变量的值
document.onclick = (e) => {
if (!isMess(e)) return;
const name = intersects[0].object.name; // 被点击的几何体名称
cubes.forEach(cube => {
// 立方体名称若等于几何体名称
if (cube.name === name) {
cube.step = cube.step === 0 ? 0.01 : 0;
}
});
};
// 鼠标指针移入立方体对象时显示手形图标
document.onmousemove = (e) => {
document.body.style.cursor = isMess(e) ? 'pointer' : 'default';
};
window.onresize = () => renderer.setSize(window.innerWidth, window.innerHeight); // 适应窗口变化
animate(); // 执行动画函数
</script>
<!-- 预览页面CSS -->
<style> body { margin: 0; background: linear-gradient(#eee, #333); } </style>
|