H5使用ThreeJs展示3D模型(gltf格式)案例

8 篇文章 0 订阅
4 篇文章 0 订阅

一、安装所需js

npm install three
npm i @tweenjs/tween.js@^18

二、引入和定义全局变量

// 引入three.js
import * as THREE from 'three';
// 引入扩展库GLTFLoader.js
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import * as TWEEN from 'tween.js';
var model, camera, scene, renderer, controls

三、主要内容

页面元素

<template>
	<div class="index-body">
		<div ref="container" style="width: 100%;height: 100%;overflow: hidden;"></div>
	</div>
</template>

js内容

export default {
	data() {
		return {
			spriteScaleUp: true,//精灵图动画执行放大还是缩小
		}
	},
	mounted() {
		this.$nextTick(() => {
			this.renderInitializeModelFn()
		});
	},
	methods: {
		//渲染模型
		renderInitializeModelFn(){
			let that = this
			// 创建一个场景
			scene = new THREE.Scene();
			// 创建一个相机
			camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
			// 设置相机的位置
			camera.position.set(200, 80, 0);
			// 设置相机的观察点
			camera.lookAt(new THREE.Vector3(0, 0, 0));
			// 创建渲染器
			renderer = new THREE.WebGLRenderer({
				antialias: true,     //抗锯齿
			});
			renderer.setPixelRatio(window.devicePixelRatio);
			renderer.setSize(window.innerWidth, window.innerHeight);
			this.$refs.container.appendChild(renderer.domElement);
			// 添加光源
			const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
			scene.add(ambientLight);
		
			const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
			directionalLight.position.set(0, 1, 1);
			scene.add(directionalLight);
		
			// 创建GLTF加载器对象
			const loader = new GLTFLoader();
			loader.load( '3D模型路径(尽量为网络路径)', function ( gltf ) {
				console.log('控制台查看加载gltf文件返回的对象结构',gltf);
				// console.log('gltf对象场景属性',gltf.scene);
				// 返回的场景对象gltf.scene插入到threejs场景中
				// scene.add( gltf.scene );
				model = gltf.scene;
				console.log("加载完成!")
				console.log(model, "模型内容")
				// 创建一个空的Object3D对象作为中心点
				const center = new THREE.Object3D();
				// 将模型添加到中心点对象上
				center.add(model);
				// 在中心点对象上调整模型的位置
				model.position.set(35, 0, -25); // 设置模型的相对位置
				// 将中心点对象添加到场景中
				scene.add(center);
			}, (e) => {
				console.log(e, "进度");
			}, function (e) {
				console.log(e);
			})
			
			// 创建纹理加载器添加精灵图
			let sprite = new THREE.Sprite(new THREE.SpriteMaterial({
				map: new THREE.TextureLoader().load("精灵图路径"),
				sizeAttenuation:false // false的话 不随着相机拉远而变小
			}))
			sprite.position.set(0,0,0)//精灵图在模型中的位置
			sprite.scale.set(0.12, 0.12, 1)//精灵图大小
			sprite.name = "jinglingtu"
			// 将精灵添加到场景中
			scene.add(sprite)
			//给精灵图添加脉冲效果
			this.spriteAnimateFn(sprite);
		
			// 点击事件处理函数
			const onClick = (event) => {
				console.log(event)
				// 获取点击位置的屏幕坐标
				const mouse = new THREE.Vector2();
				mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
				mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
		
				// 通过射线检测点击位置是否与精灵图相交
				const raycaster = new THREE.Raycaster();
				raycaster.setFromCamera(mouse, camera);
				let intersects = raycaster.intersectObject(item);
				if (intersects.length > 0) {
					console.log("点击精灵")
					this.changeCameraPosition()
				}
			};
		
			// 监听点击事件
			this.$refs.container.addEventListener('click', onClick, false);
		
			// 设置光源投射阴影
			directionalLight.castShadow = true;
			directionalLight.shadow.mapSize.width = 1024;
			directionalLight.shadow.mapSize.height = 1024;
			directionalLight.shadow.camera.near = 0.1;
			directionalLight.shadow.camera.far = 100;
			renderer.shadowMap.enabled = true;
		
			// 添加交互控制器
			controls = new OrbitControls(camera, renderer.domElement);
			//开启阻尼效果
			controls.enableDamping = true
			controls.dampingFactor = 0.2
			
			//启动相机旋转
			controls.enableRotate = true
			// 位移的速度,其默认值为1。
			controls.panSpeed = 3
			// 旋转的速度,其默认值为1。
			controls.rotateSpeed = 3
			//启用或禁用摄像机平移,默认为true。
			controls.enablePan = false
			//启动相机缩放
			controls.enableZoom = true
			// 设置相机距离目标点的最小和最大距离
			controls.minDistance = 65;
			controls.maxDistance = 200;
			// 设置相机在 y 轴上的最低和最高可视角度
			// controls.minPolarAngle = Math.PI / 4;
			controls.maxPolarAngle = Math.PI / 2.2;
			// 设置相机在 x 轴上的最低和最高可视角度
			// controls.minAzimuthAngle = -Math.PI / 4;
			// controls.maxAzimuthAngle = Math.PI / 4;
			controls.update();
		
			// 渲染场景
			function animate() {
				requestAnimationFrame(animate);
				TWEEN.update();
				renderer.render(scene, camera);
			}
			animate();
		},
		//精灵图动画
		spriteAnimateFn (sprite) {
			// 更新精灵图的缩放
			if (this.spriteScaleUp) {
				sprite.scale.x += 0.003;
				sprite.scale.y += 0.003;
			} else {
				sprite.scale.x -= 0.003;
				sprite.scale.y -= 0.003;
			}
			// 调整缩放方向
			if (sprite.scale.x >= 0.14) {
				this.spriteScaleUp = false
			} else if (sprite.scale.x <= 0.12) {
				this.spriteScaleUp = true
			}
			// 更新精灵图
			sprite.updateMatrix()
			// 循环调用 animate 函数
			setTimeout(() => {
				this.spriteAnimateFn(sprite);
			}, 100);
		},
		//更新相机位置
		changeCameraPosition() {
			//解除滑动限制
			controls.minDistance = 0;
			controls.maxPolarAngle = Math.PI / 1;
			controls.enableRotate = false
			controls.enableZoom = false
			controls.update();
			// 相机从当前位置camera.position飞行三维场景中某个世界坐标附近
			new TWEEN.Tween({
				// 相机开始坐标
				x: camera.position.x,
				y: camera.position.y,
				z: camera.position.z,
				// 相机开始指向的目标观察点
				tx: 0,
				ty: 0,
				tz: 0,
			})
			.to({
				// 相机结束坐标
				x: 0,
				y: 0,
				z: 0,
				// 相机结束指向的目标观察点
				tx: 0,
				ty: 0,
				tz: 0,
			}, 1000)
			.onUpdate(function (e) {
				// 动态改变相机位置
				camera.position.set(this.x, this.y, this.z);
				// 模型中心点
				controls.target.set(this.tx, this.ty, this.tz);
				controls.update();//内部会执行.lookAt()
			})
			.start();
		},
	}
}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值