Halo
发布于 2024-01-29 / 77 阅读 / 0 评论 / 0 点赞

three.js物体沿曲线运动

<!DOCTYPE html>
<html lang="en">

<body>
	<div id="webgl_3d"></div>
</body>
<script type="importmap">
			{
				"imports": {
					"three": "../js/three.module.js"
				}
			}
		</script>

<script type="module">

	import * as THREE from 'three';
	import { GLTFLoader } from '../js/loaders/GLTFLoader.js';
	import { OrbitControls } from '../js/controls/OrbitControls.js';

	let container, controls;
	let camera, scene, renderer;
	let objPos = {};

	init();
	animate();

	function init() {

		container = document.getElementById('webgl_3d');
		document.body.appendChild(container);

		scene = new THREE.Scene();
		scene.background = new THREE.Color(0xbbbbbb);

		var ambientLight = new THREE.AmbientLight(0xffffff);
		scene.add(ambientLight);

		var directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
		directionalLight.position.set(1, 1, 1).normalize();
		scene.add(directionalLight);

		const loader = new GLTFLoader();
		loader.load('../models/gltf/path.glb', function (gltf) {
			let object = gltf.scene;
			object.name = 'animation';
			// object.visible = false;
			scene.add(object);

			loader.load('../models/gltf/box.glb', function (gltf) {
				let object = gltf.scene;
				object.name = 'box';
				scene.add(object);

				play('box', 'animation', 'path');
			});
		});



		renderer = new THREE.WebGLRenderer();
		renderer.setPixelRatio(window.devicePixelRatio);
		renderer.setSize(window.innerWidth, window.innerHeight);
		renderer.outputEncoding = THREE.sRGBEncoding;
		container.appendChild(renderer.domElement);

		camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 10);
		camera.position.z = 2;

		controls = new OrbitControls(camera, renderer.domElement);

		window.addEventListener('resize', resize);
	}

	function play(targetName, pathName, pointName, totalSec = 10) {
		const target = scene.getObjectByName(targetName);
		objPos[targetName] = [0, 0, 0];

		const obj = scene.getObjectByName(pathName);
		const path = obj.getObjectByName(pointName);
		let points = path.geometry.attributes.position.array;

		let qty = points.length / 3;
		let interMs = totalSec * 1000 / qty;
		let index = 0;
		let intervalID = setInterval(function () {
			objPos[targetName] = [points[index], points[index + 1], points[index + 2]];
			if (index <= 0) {
				console.log('start play ', targetName, 'on ', pathName);
			} else if (index >= 3 * qty) {
				clearInterval(intervalID);
				delete objPos[targetName];
				console.log('end play', targetName, 'on ', pathName);
			}
			index += 3;
		}, interMs);
	}

	function resize() {
		camera.aspect = window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
		renderer.setSize(window.innerWidth, window.innerHeight);

	}

	function animate() {
		renderer.render(scene, camera);
		for (let name in objPos) {
			const target = scene.getObjectByName(name);
			let points = objPos[name];
			target.position.x = points[0];
			target.position.y = points[1];
			target.position.z = points[2];
		}
		requestAnimationFrame(animate);
	}

</script>

</html>

评论