Three.js(学习)

在vue项目中使用Three.js的流程

1.首先利用npm安装Q three.js,具体操作代码如下
   npm install three
2.接下来利用npm安装轨道控件插件:
  npm install three-orbit-controls

3.接下来安装加载.obj和.mtl文件的插件:
  npm i --save three-obj-mtl-loader


4.安装渲染器插件:
 npm i --save three-css2drender

安装好以后,在页面中引入three.is并使用,在所调用页面引入的代码为:
1 import * as Three from 'three

要记得引入three.js

  1. 先创建场景       
  2. 创建相机
  3. 设置相机位置
  4. 添加物体  创建几何体
  5. 根据几何体和材质创建物体
  6. 将几何体添加到场景中
  7. 初始化渲染器
  8. 设置渲染器尺寸大小
  9. 将webgl渲染的canvas内容添加到body
  10. 使用渲染器,通过相机将场景渲染进来

 直接上代码:

      //创建场景
      const scene = new THREE.Scene();
      //创建相机
      const camera = new THREE.PerspectiveCamera(75,homebox.clientWidth/homebox.clientHeight,0.1,1000);
      //改变相机的初始位置
      camera.position.set(0,0,10);
      //在相机添加到场景
      scene.add(camera);
      //添加物体 创建几何体
      const cubeGeomtry = new THREE.BoxGeometry(1,1,1);//添加几何体
      const cubeMaterial = new THREE.MeshBasicMaterial({color:0xffbb00})//添加材质
      //根据几何体和材质创建物体 
      const cube = new THREE.Mesh(cubeGeomtry,cubeMaterial);
      //将几何体添加到场景
      scene.add(cube);
      //初始化渲染器
      const renderer = new THREE.WebGLRenderer();
      //设置渲染器的尺寸
      renderer.setSize(window.innerWidth,window.innerHeight);
      //将webgl渲染的canvas内容添加到页面容器中
      homebox.appendChild(renderer.domElement);
      //使用渲染器,通过相机将场景渲染进来
      renderer.render(scene,camera);

 以上代码,只是简单的在浏览器渲染出一个立方体(静止)想要它可以随鼠标拖动,还需进行以下操作:

//导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; 

//创建轨道控制器
     var controls=new OrbitControls(camera,renderer.domElement);

    // 添加一个动画函数
      function Aboutanimate() {
        requestAnimationFrame(Aboutanimate);//请求动画帧  每帧执行一次动画函数
        renderer.render(scene,camera);//渲染
      }

为了方便我们观察物体所在的位置,还需进行以下操作:

      //添加坐标轴辅助器
      const axesHelper = new THREE.AxesHelper(5)//参数代表坐标轴长度
      scene.add(axesHelper)//把坐标轴辅助器添加到场景中

现在我们就可以看到一个立方体,如果只是这样还远远满足不了我们的需求,所以我们要让立方体动起来,下面代码就可以实现:

import gsap from 'gsap';//导入动画库   要记得npm安装一下  npm install gsap
//gsap是补间动画库
//设置补间动画
      let animation= gsap.to(cube.position,{x:5,duration:5,ease:"powerl.inOut",
      repeat:5,  //设置重复次数  无限次重复设置为-1
      yoyo:true, //设置往返运动
      delay:2,   // delay 设置2秒延迟
      onComplete:()=>{
        console.log('动画完成');
      },
      onStart:()=>{
        console.log('动画开始');
      }
    })
      gsap.to(cube.rotation,{x:2*Math.PI,duration:5,ease:"powerl.inOut",repeat:5,yoyo:true})

现在我们就可以看到立方体动起来了,为了方便我们开发调试,我们需要一个可以实时控制的面板,可以用下面代码实现:

 //导入dat.gui
import * as dat from 'dat.gui'  
//移动X轴坐标 
      const gui = new dat.GUI();
      gui.add(cube.position,"x").min(0).max(5).step(0.01).name('移动X轴坐标').onChange((value)=>{
        console.log('值被修改:',value);
      }).onFinishChange((valur)=>{
        console.log("完全停下来");
      });

       //移动Y轴坐标  
      gui.add(cube.position,"y").min(0).max(5).step(0.01).name('移动Y轴坐标').onChange((value)=>{
        console.log('值被修改:',value);
      }).onFinishChange((valur)=>{
        console.log("完全停下来");
      });
      
//移动Z轴坐标  
       gui.add(cube.position,"z").min(0).max(5).step(0.01).name('移动Z轴坐标').onChange((value)=>{
        console.log('值被修改:',value);
      }).onFinishChange((valur)=>{
        console.log("完全停下来");
      });
//控制旋转
      gui.add(cube.rotation,'x').min(0).max(2*Math.PI).step(0.01).name('转动X轴')
      gui.add(cube.rotation,'y').min(0).max(2*Math.PI).step(0.01).name('转动Y轴')
      gui.add(cube.rotation,'z').min(0).max(2*Math.PI).step(0.01).name('转动Z轴')
 
//改变物体颜色
      const params = {
        color:'#ffff00',
        fn:()=>{
          //让立方体运动起来
          gsap.to(cube.position,{x:5,duration:5,yoyo:true,repeat:-1})
        }
      }
      gui.addColor(params,"color").name('物体颜色').onChange((value)=>{
        console.log("值被改变:",value);
        cube.material.color.set(value)
      })
      //设置选项框
      gui.add(cube,'visible').name('是否显示')
    
      
//设置文件夹
      var folder= gui.addFolder('设置立方体')
      folder.add(cube.material,'wireframe')
      //设置按钮点击触发某个事件
      folder.add(params,'fn').name('点击立方体运动')

为了实现响应式,这里添加了以下代码:

 //调用js接口
        //双击控制屏幕进入全屏,退出全屏
        const fullScreenElement = document.fullscreenElement;
        if (!fullScreenElement) {
          renderer.domElement.requestFullscreen()
        } else {
          document.exitFullscreen()
          
        }
        
      })
      //监听画面变化,更新渲染画面
      window.addEventListener('resize',()=>{
        console.log('画面变化了');
        camera.aspect = homebox.clientWidth/homebox.clientHeight;//更新摄像头
        camera.updateProjectionMatrix();//更新摄像机的投影矩阵
        renderer.setSize(window.innerWidth,window.innerHeight);//更新渲染器
        
        renderer.setPixelRatio(homebox.devicePixelRatio);//设置渲染器的像素比
      })

下面是完整代码:

<template>
  <div id='Home'></div>
</template>

<script>
//引入three.js
import * as THREE from 'three'; 
//导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; 
//导入动画库
import gsap from 'gsap';
//导入dat.gui
import * as dat from 'dat.gui';  
export default {
  data() {
    return {
      
    }
  },
  mounted() {
   this.init()
   
    
    
  },
  methods: {
    init(){
      //获取dom元素
      let homebox = document.getElementById('Home');

      //创建场景
      const scene = new THREE.Scene();

      //创建相机
      const camera = new THREE.PerspectiveCamera(75,homebox.clientWidth/homebox.clientHeight,0.1,1000);

      //改变相机的初始位置
      camera.position.set(0,0,10);

      //在相机添加到场景
      scene.add(camera);

      //添加物体 创建几何体
      const cubeGeomtry = new THREE.BoxGeometry(1,1,1);//添加几何体
      const cubeMaterial = new THREE.MeshBasicMaterial({color:0xffbb00})//添加材质

      //根据几何体和材质创建物体 
      const cube = new THREE.Mesh(cubeGeomtry,cubeMaterial);

      //将几何体添加到场景
      scene.add(cube);

      //移动X轴坐标 
      const gui = new dat.GUI();
      gui.add(cube.position,"x").min(0).max(5).step(0.01).name('移动X轴坐标').onChange((value)=>{
        console.log('值被修改:',value);
      }).onFinishChange((valur)=>{
        console.log("完全停下来");
      });

       //移动Y轴坐标  
      gui.add(cube.position,"y").min(0).max(5).step(0.01).name('移动Y轴坐标').onChange((value)=>{
        console.log('值被修改:',value);
      }).onFinishChange((valur)=>{
        console.log("完全停下来");
      });
      

       //移动Z轴坐标  
       gui.add(cube.position,"z").min(0).max(5).step(0.01).name('移动Z轴坐标').onChange((value)=>{
        console.log('值被修改:',value);
      }).onFinishChange((valur)=>{
        console.log("完全停下来");
      });


      //控制旋转
      gui.add(cube.rotation,'x').min(0).max(2*Math.PI).step(0.01).name('转动X轴')
      gui.add(cube.rotation,'y').min(0).max(2*Math.PI).step(0.01).name('转动Y轴')
      gui.add(cube.rotation,'z').min(0).max(2*Math.PI).step(0.01).name('转动Z轴')
 

      //改变物体颜色
      const params = {
        color:'#ffff00',
        fn:()=>{
          //让立方体运动起来
          gsap.to(cube.position,{x:5,duration:5,yoyo:true,repeat:-1})
        }
      }
      gui.addColor(params,"color").name('物体颜色').onChange((value)=>{
        console.log("值被改变:",value);
        cube.material.color.set(value)
      })
      //设置选项框
      gui.add(cube,'visible').name('是否显示')

      
      //设置文件夹
      var folder= gui.addFolder('设置立方体')
      folder.add(cube.material,'wireframe')
      //设置按钮点击触发某个事件
      folder.add(params,'fn').name('点击立方体运动')

      //初始化渲染器
      const renderer = new THREE.WebGLRenderer();

      //设置渲染器的尺寸
      renderer.setSize(window.innerWidth,window.innerHeight);

      //将webgl渲染的canvas内容添加到页面容器中
      homebox.appendChild(renderer.domElement);

      //使用渲染器,通过相机将场景渲染进来
      // renderer.render(scene,camera);
      Aboutanimate()

      //创建轨道控制器
      var controls=new OrbitControls(camera,renderer.domElement);

      //添加坐标轴辅助器
       const axesHelper = new THREE.AxesHelper(5)//参数代表坐标轴长度
       scene.add(axesHelper)//把坐标轴辅助器添加到场景中

      
      //这里可以不要 
       //设置补间动画
    //  let animation= gsap.to(cube.position,{x:5,duration:5,ease:"powerl.inOut",
    //  repeat:5,  //设置重复次数  无限次重复设置为-1
    //  yoyo:true, //设置往返运动
    //  delay:2,   // delay 设置2秒延迟
    //  onComplete:()=>{
    //    console.log('动画完成');
    //  },
    //  onStart:()=>{
    //    console.log('动画开始');
    //  }
    //  })
    //    gsap.to(cube.rotation,{x:2*Math.PI,duration:5,ease:"powerl.inOut",repeat:5,yoyo:true})




     //双击触发事件  监听鼠标双击
     window.addEventListener("dblclick",()=>{
        // console.log(animation);
        // if (animation.isActive()) {
        //   //暂停动画
        //   animation.pause()
        // } else {
        //   //恢复动画
        //   animation.resume()
        // }

        //调用js接口
        //双击控制屏幕进入全屏,退出全屏
        const fullScreenElement = document.fullscreenElement;
        if (!fullScreenElement) {
          renderer.domElement.requestFullscreen()
        } else {
          document.exitFullscreen()
          
        }
        
      })
      //监听画面变化,更新渲染画面
      window.addEventListener('resize',()=>{
        console.log('画面变化了');
        camera.aspect = homebox.clientWidth/homebox.clientHeight;//更新摄像头
        camera.updateProjectionMatrix();//更新摄像机的投影矩阵
        renderer.setSize(window.innerWidth,window.innerHeight);//更新渲染器
        
        renderer.setPixelRatio(homebox.devicePixelRatio);//设置渲染器的像素比
      })
      
      // 动画函数
      function Aboutanimate() {
        requestAnimationFrame(Aboutanimate);//请求动画帧  每帧执行一次动画函数
        renderer.render(scene,camera);//渲染
      
       }

    }
  },
}
</script>

<style scoped lang='scss'>
#Home {
  width: 100vh;
  height: 100vh;
}
</style>

猜你喜欢

转载自blog.csdn.net/w418856/article/details/130399267