一、安装所需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();
},
}
}
文章评论