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
- 先创建场景
- 创建相机
- 设置相机位置
- 添加物体 创建几何体
- 根据几何体和材质创建物体
- 将几何体添加到场景中
- 初始化渲染器
- 设置渲染器尺寸大小
- 将webgl渲染的canvas内容添加到body
- 使用渲染器,通过相机将场景渲染进来
直接上代码:
//创建场景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, //设置重复次数 无限次重复设置为-1yoyo: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>