Threejs 加载模型、旋转、弹框操作

参考文档

Three.js电子书《Three.js零基础入门教程》_郭隆邦

Three.js – JavaScript 3D Library

Three.js之灯光_disasters的博客-CSDN博客_threejs 灯光

『Three.js』辅助坐标轴_德育处主任Pro的博客-CSDN博客

Three.js学习笔记-OrbitControls.js让摄像机围绕目标旋转_fewbadboy的博客-CSDN博客_orbitcontrols 旋转

dom-to-image - npm

安装three.js

npm install three -d

引入three.js并加载所需插件

import * as THREE from 'three';

import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

three.js的三大基本要素

渲染器

renderer = new THREE.WebGLRenderer(); //实例化渲染器
renderer.setSize(window.innerWidth, window.innerHeight); //设置宽和高
document.body.appendChild(renderer.domElement); // 添加到dom

场景

scene = new THREE.Scene(); // 实例化场景

相机

camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000000); //实例化相机
camera.position.set(200, 100, 100); //相机的位置
camera.lookAt(new THREE.Vector3(0, 0, 0));//相机看向的位置

到这里打开浏览器应该会发现一个黑色的canvas标签。

requestAnimationFrame

animate() { // 很多操作都要在这里更新才能有效果

	requestAnimationFrame(this.animate);


},

加载模型,播放动画

const loader = new GLTFLoader();

// 有的模型需要解压才能加载
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('/draco/');
loader.setDRACOLoader(dracoLoader);


loader.load('文件路径', (gltf) => {


	//将模型添加至场景
	scene.add(gltf.scene) // 根据访问的文件类型不同,可能需要.scene,也可能直接访问gltf,自己尝试一下就好了


	//直接添加模型后会把模型的一个角对准坐标轴的原点,获取模型的大小除2计算后设置位置,让坐标轴原点刚好在模型的正中心,方便后续操作
	var box = new THREE.Box3().setFromObject(gltf.scene);
	gltf.scene.position.set(mean(box.max.x, box.min.x), mean(box.max.y, box.min.y), mean(box.max.z, box.min.z));

	function mean(v1, v2) {
		return -(Math.abs(v1 - v2) / 2);
	}
    
    // 播放模型的动画,一个模型中可携带多个动画
    mixer = new THREE.AnimationMixer(gltf.scene);// 初始化混合器,这里的传参参考scene.add
    var AnimationAction = mixer.clipAction(gltf.animations[0]); // 传入一个动画
    AnimationAction.play(); // 播放
})

DRACOLoader加载器有的模型需要,有的不需要。页面报

 这个错误时就需要加上。

OrbitControls控制器

可以通过鼠标或者滚轮放大缩小移动模型。

controls = new OrbitControls(camera, renderer.domElement); // 初始化
controls.maxPolarAngle = Math.PI / 2; // 设置垂直旋转的最大角度
controls.minPolarAngle = 0;  // 设置垂直旋转的最小角度
// 这两个设置目前达到的效果是不能看模型的底面
controls.autoRotate = true; // 镜头自动旋转

灯光

在没有添加灯光是会有一个默认的灯光使我们也能看到模型,在我们添加灯光后消失。

(补充:1.最好不要用纯白色的灯光,会使模型看不到细节,2.最好可以从多个不同方向打光,可以使模型更加立体)

scene.add(new THREE.AmbientLight(0xffffff)); // 白色的全局光,使模型不是那么黑白分明

var directionalLight = new THREE.DirectionalLight(0xffffff, 1); // 初始化平行光,模拟太阳
directionalLight.position.set(100, 104, 200);  // 设置位置
scene.add(directionalLight); // 添加到场景

点击模型弹出文字信息

安装dom-to-image并引入

npm install dom-to-image

import domtoimage from 'dom-to-image';
    //获取鼠标坐标 处理点击某个模型的事件
let mouse = new THREE.Vector2(); // 初始化一个2D坐标用于存储鼠标位置
let raycaster = new THREE.Raycaster(); // 初始化光线追踪
function onmodelclick(event) {


   // 获取鼠标点击位置
	mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
	mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

	raycaster.setFromCamera(mouse, camera);
	const intersects = raycaster.intersectObjects(scene.children); // 获取点击到的模型的数组,从近到远排列

	console.log(intersects);


	var worldPosition = new THREE.Vector3(); // 初始化一个3D坐标,用来记录模型的世界坐标

	if (intersects.length) {
		intersects[0].object.getWorldPosition(worldPosition); // 将点中的3D模型坐标记录到worldPosition中

        // 将dom节点转换为base64编码的图片
        domtoimage.toPng(document.getElementById("节点ID"))
				.then((dataUrl) => {

					var texture = new THREE.TextureLoader().load(dataUrl);

					var spriteMaterial = new THREE.SpriteMaterial({
						map: texture,//设置精灵纹理贴图
					});
					sprite = new THREE.Sprite(spriteMaterial); // 精灵模型,不管从哪个角度看都可以一直面对你
					scene.add(sprite);

                    sprite.position.set(worldPosition.x, worldPosition.y + 3, worldPosition.z); // 根据刚才获取的世界坐标设置精灵模型位置,高度加了3,是为了使精灵模型显示在点击模型的上方

				})
				.catch(function (error) {
					console.error('oops, something went wrong!', error);
				});
	}

	
}
window.addEventListener("click", onmodelclick); // 监听点击事件

辅助工具

坐标轴

var axes = new THREE.AxesHelper(20);
scene.add(axes);

平行光位置

const helper = new THREE.DirectionalLightHelper(directionalLight, 5);
scene.add(helper);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓_枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值