vue3中引入Threejs,加载gltf模型,引入gsap(2.0版本叫tweenmax),实现相机运动动画
第一步:创建vue3.0的项目,使用npm引入threejs的安装包,编辑文章的时候使用的threejs是0.129.0版本的.
1.npm install three --save
2,引入gsap,2.0版本的叫tweenmax,升级为3.0版本后叫gsap,用法稍微做了点改变,
建议使用新版的gsap,
npm安装 npm install gsap
链接: gsap官网.
链接: tweenmax中文网.
// threejs部分
import * as THREE from "three/build/three.module.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; //控制器
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; // gltf加载器
import gsap from "gsap";
import { CSSRulePlugin } from "gsap/CSSRulePlugin";
gsap.registerPlugin(CSSRulePlugin); // 引入css插件,完成某些css动画
2.配置threejs的环境
setup () {
const Scene = new THREE.Scene();
const Camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
5000
);
const Renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true, //开启alpha
});
// 控制器
const Controls = new OrbitControls(Camera, Renderer.domElement);
//gltfLoader
const Gltfloader = new GLTFLoader();
// 注意:此处为threejs的DOM,需要将threejs的场景渲染进去
const threeDom = ref(null);
3.设置相机的角度与朝向,同时设置轨道控制器的朝向
// 首页进入相机的视角,这个视角可以在三维模型中建立一个摄像机获取摄像机的坐标,如C4D,非常准确.
const cameraPosition = {
x: -180,
y: 430,
z: 333,
};
const cameraLookat = {
x: 0,
y: 0,
z: 0,
};
// 声明一个方法传入参数可以在不同的地方调用相机
const cameraReset = (position, lookAt, time = 1) => {
gsap.to(Camera.position, {
x: position.x,
y: position.y,
z: position.z,
duration: time,
ease: "power4.out",
// onComplete: function () {
// 这是相机运动完成的回调,可以执行其他的方法.
// }
});
gsap.to(Camera.lookAt, {
x: lookAt.x,
y: lookAt.y,
z: lookAt.z,
duration: time,
ease: "power4.out",
});
gsap.to(Controls.target, {
x: lookAt.x,
y: lookAt.y,
z: lookAt.z,
duration: time,
ease: "power4.out",
});
};
4.初始化threejs场景;并设置相机,灯光,控制器,renderer的设置
const initThreeScene = () => {
// 点光源
const point = new THREE.PointLight(0xffffff, 1);
point.position.set(10, 600, -40); // 点光源位置
// Scene.position.set(0, 15, 0); // 场景位置
// Scene.add(point); // 点光源添加到场景中
// 环境光
const ambient = new THREE.AmbientLight(0x444444, 1);
Scene.add(ambient);
// 辅助坐标系
// const axesHelper = new THREE.AxesHelper(500);
// Scene.add(axesHelper);
// 修改相机,场景的参数
Camera.position.set(-180, 430, 333);
Camera.lookAt(0, 0, 0);
Controls.target = new THREE.Vector3(0, 0, 0);
// 使动画循环使用时阻尼或自转 意思是否有惯性
Controls.enableDamping = true;
// 动态阻尼系数 就是鼠标拖拽旋转灵敏度
Controls.dampingFactor = 0.04;
// 是否可以旋转
Controls.enableRotate = false;
// 是否可以缩放与速度
Controls.enableZoom = false;
// 设置相机距离原点的最远距离
Controls.minDistance = 1;
// 设置相机距离原点的最远距离
Controls.maxDistance = 2000;
// 是否开启右键拖拽
Controls.enablePan = false;
//render的相关设置
Renderer.setPixelRatio(window.devicePixelRatio);
Renderer.setSize(window.innerWidth, window.innerHeight);
Renderer.inputEncoding = true;
Renderer.outputEncoding = THREE.sRGBEncoding;
Renderer.setClearColor(0xd0d0d0, 1);
// 将renderer渲染进DOM里面
threeDom.value.appendChild(Renderer.domElement);
};
// 设置页面自适应
const onWindowResize = () => {
Camera.aspect = window.innerWidth / window.innerHeight;
Camera.updateProjectionMatrix();
Renderer.setSize(window.innerWidth, window.innerHeight);
};
window.addEventListener("resize", onWindowResize, false);
// 完成以上步骤基本的场景已经配置完成
5.加载gltf/glb格式的模型,经过对比各种格式(如obj,fbx),推荐大家使用gltf/glb格式的;
优点:
第一体积小,相对于obj格式的可以减少一半的体积;相对于fbx体积也会更小
第二不用烘焙贴图,C4D的自带材质球很多threejs都是支持的;
第三就是可以继续压缩达到更小的体积,在相同的网速下压缩后的glb格式的模型可以更快下载;
Gltfloader.load("model/road.glb", (gltf) => {
Scene.add(gltf.scene);
// 模型加载完,进行相机的初始化,传入设置的参数,模型加载为异步
cameraReset(cameraPosition, cameraLookat);
}, function (xhr) {
// 控制台查看加载进度xhr
console.log(Math.floor(xhr.loaded / xhr.total * 100))
});
6 声明render函数进行循环渲染
const Render = () => {
requestAnimationFrame(Render);
Controls.update(); // 轨道控制器的更新
Renderer.clear(); // 清除画布
Renderer.render(Scene, Camera);
};
7.在onMounted中调用方法初始化threejs场景,在onUnmounted 中释放内存,移除事件监听
onMounted(() => {
initThreeScene();
Render();
});
onUnmounted(() => {
Scene.traverse((e) => {
if (e.BufferGeometry) e.BufferGeometry.dispose()
if (e.material) {
if (Array.isArray(e.material)) {
e.material.forEach((m) => {
m.dispose()
})
} else {
e.material.dispose()
}
}
if (e.isMesh) {
e.remove();
}
})
Scene.remove();
Renderer.dispose();
Renderer.content = null;
window.removeEventListener("resize", onWindowResize, false);
});
// setup中将threejs的dom返回
return {
threeDom,
};
8,最后在顶部引入refthreejsdom
<div ref="threeDom"></div>
总结:vue3的引入方法基本上就是这样,不要把threejs的scene,camera,renderer等内部函数写入vue的响应式数据(如有错误请留言,我会及时修改)
最后附上VUE3引入的threejs做的项目,模型大概12兆左右.
附上链接: 智能控制器的3D场景