three.js : 独立控制图形对象

位置: 首页 > 前端三套件
[发布: 2025.5.14  作者: 马黑  阅读: 21]

以下代码,使用 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>

前一篇: three.js几何体之圆锥缓冲几何体
下一篇: three.js几何体之圆柱缓冲几何体

发表评论:

  
 

评论列表 [1条]

#1 | 飞飞 于 2025-5-14 19:50 发布: 两个立方体可以独立控制运动。。。

Copyright © 2023 All Right Reserved 马黑PHP文章管理整站系统v1.8
联系我们: gxblk@163.com