Three.js在Vue3||Vue2中的使用

542 阅读3分钟

Three.js使用基本结构

踩坑

最开始我的代码的是在Vue2中写,创建相机、场景或者其他的一些构建3D空间需要的一些参数直接在data中初始化了,Vue2这边这样子写没有任何问题。但是!在Vue3中就出事了,具体什么错忘了,反正代码跑不起来。在看了一些博客后说:需要把场景这些变量作为全局变量,如果写在data中的话在使用时浅拷贝。 我下面贴出来的代码采用的是前者,而且在整个创建3D场景的过程中所有变量的定义尽量都定义为全局变量。

初始化变量
   //  仅供参考
   var animatemodel = null;
   var scene = null;
   var camera = null;
   var width = window.innerWidth; // 窗口宽度
   var height = window.innerHeight * 0.7 // 窗口高度
   var renderer = null;
   var orbitControls = null;
   var pointLight = null;
   var directionalLight = null; // 直线光
   var hemiLight = null;
   var ambientLight = null;   //环境光
   var sceneDomElement = null;
   var mesh = null;
   var objects = [];
   var heidModels = [];
   // 模型动画相关
   let clock = new THREE.Clock(); // 用于clock.getDelta()
   let mixer;
   var planes;
   let curve = null;
   let progress = 0; // 物体运动时在运动路径的初始位置,范围0~1
   const velocity = 0.0001; // 影响运动速率的一个值,范围0~1,需要和渲染频率结合计算才能得到真正的速率
   var composer = null
   var outlinePass = null
   var renderPass = null
创建场景

scene = new THREE.Scene()

创建相机
var k = width / height; // 窗口宽高比
var s = 1100; // 三维场景显示范围控制系数,系数越大,显示的范围越大  
camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1900);
camera.position.set(x坐标,y坐标,z坐标); // 设置相机位置  这里的参数根据自己需求去定义
camera.lookAt(scene.position); // 设置相机方向(指向的场景对象)
创建渲染器
sceneDomElement = document.getElementById("ThreeModel")  // 获取标签元素,要插入哪个就获取哪个
var width = window.innerWidth; // 窗口宽度
var height = window.innerHeight * 0.6 // 窗口高度
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
orbitControls = new OrbitControls(camera, renderer.domElement);  //OrbitControls是THREEJS中最常用的一个控制器,可以帮助我们实现以目标为焦点的旋转缩放,同时平移相机观察场景的操作
orbitControls.zoomSpeed = 2   //设置盒模型深度 不过我这边没用起
orbitControls.minZoom = 0.5;   // 设置最小缩放比
orbitControls.maxZoom = 3      // 设置最大缩放比
orbitControls.enablePan = false    // 是否可以拖动模型
renderer.setSize(width, height); // 设置渲染区域尺寸
renderer.setClearColor(0xEEEEEE, 0.0);//或者renderer.setClearAlpha(0.0);它的意思是每次绘制清除缓冲区后的颜色通道设置,简单就是设置每次绘制的背景颜色
sceneDomElement.appendChild(renderer.domElement); // body元素中插入canvas对象
环境光
pointLight = new THREE.PointLight(0xffffff);  // 设置点光源
directionalLight = new THREE.DirectionalLight(0xffffff, light.directionalLight);  // 平行光  个人感觉效果不是很明显
ambientLight = new THREE.AmbientLight(0xffffff);   // 环境光
pointLight.distance = 0  // 点光源距离
pointLight.castShadow = true;   // 是否开启点光源阴影效果
pointLight.position.set(new THREE.Vector3(400, 200, 300))   // 设置点光源初始位置
pointLight.intensity = light.pointLight   // 点光源强度 取值:1,2,3...
scene.add(pointLight); //点光源添加到场景中
scene.add(ambientLight);   
scene.add(directionalLight);
构建模型
const loader = new FBXLoader();
loader.load("模型路径", object => {   // 模型这边我用的是.fbx格式  其他格式暂时没有试过去引入
    //根据需要去显然模型文件中的内容
    //直接log object也可以查看模型文件的一些参数内容
    //如果需要将整个模型都加入场景可以使用  scene.add(object)
    object.map(itm => {
        for (var i = 0; i < initModel.length; i++) {
            if (itm.name == initModel[i]) {
                scene.add(itm)
             }
         }
    })
})
render()

这边的代码是持续执行的,不建议在这里处理过于复杂的逻辑

var vector = camera.position.clone();  // 复制一个相机坐标
pointLight.position.set(vector.x, vector.y, vector.z); //点光源位置 实现点光源位置跟随视角一起变化
directionalLight.position.set(vector.x, vector.y, vector.z);  // 坐标赋值
orbitControls.update();
requestAnimationFrame(this.render);
renderer.render(scene, camera); //执行渲染操作,指定场景、相机作为参数
动画玩法
1.
animate() {
    requestAnimationFrame(this.animate);
    const delta = clock.getDelta();
    if (mixer) mixer.update(delta);
    renderer.render(scene, camera);
},
2. 继上面的构建模型
const _this = this
loader.load("模型动画文件", objects => {
    mixer = new THREE.AnimationMixer(object);
    const action = mixer.clipAction(object.animations[0]);
    action.setLoop(THREE.LoopOnce)
    action.clampWhenFinished = true
    action.enable = true
    /*设置动画只播放一次*/
    action.play();
    scene.add(object);
    animatemodel = object;
    _this.animate()
    mixer.addEventListener('finished', function (e) {
        // 监听到播放结束事件操作
    })
})
小技巧
// 设置模型颜色 这个设置会把模型原本图层覆盖掉,建议在设置颜色之前先存一下初始图层
// 在这个基础上 理论上可以实现呼吸灯效果
const old = 模型对象.material
模型对象.material = new THREE.MeshPhysicalMaterial({
    color: "颜色",  // #fffff
    metalness: 0.5,
    opacity: 0.5,  // 透明度
    roughness: 0.8,
})