vue2 threejs基础知识

安装 three

npm install three --save-dev

安装 控制动画的插件

npm install gsap

gsap文档

安装GUI调节属性

npm install --save dat.gui

纹理素材下载地址

例子1 自转和公转 时间动画 缓冲几何图形

<template>
   <div id="container"></div>
</template>
<script>
   //引入three包  最新版
    import * as THREE from 'three'
    //鼠标控制器  需要threejs高版本
    import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";  
    //时间动画
    import gsap from "gsap";
    //引入dat.gui
    import * as dat from 'dat.gui'
   
    export default {
        data() {
          return {
            scene:null,//场景
            camera:null,//相机
            renderer:null,//渲染器  
            container:null,
            clock:new THREE.Clock(),//设置时钟
            mesh:null, //材质
            animate1:null,
            samll:null,
          };
        },
        mounted() {
          this.init() //初始的方法都放在init  
          //  window.addEventListener('dblclick',()=>{ //监听鼠标双击事件
          //     if(this.animate1.isActive()){ //判断是否运动  
          //       this.animate1.pause()  //暂停
          //     }else{
          //       this.animate1.resume()  //恢复
          //     }
               
          //  })
          //双击屏幕控制画布全屏 退出全屏
          window.addEventListener('dblclick',()=>{
              const fullScreenElement=document.fullscreenElement;
              if(!fullScreenElement){
                 this.renderer.domElement.requestFullscreen() //画布对象全屏
              }else{
                 document.exitFullscreen()  //退出全屏
              }
          })
         },
        methods: {  
          setScene(){
             this.container = document.getElementById('container');//获取dom元素
             //创建渲染器   //消除锯齿{antialias: true} 透明背景alpha: true
             this.renderer = new THREE.WebGLRenderer({antialias: true});
             this.renderer.setClearColor(0x000000,1);//设置背景颜色
             //this.renderer.setSize( window.innerWidth, window.innerHeight ); //全屏区域
             this.renderer.setSize(this.container.clientWidth,this.container.clientHeight);//设置渲染区域尺寸
              //开启场景中的阴影贴图
             this.renderer.shadowMap.enabled=true;
             // document.body.appendChild( this.renderer.domElement );
             this.container.appendChild(this.renderer.domElement);//body元素中插入canvas对象
             
             //创建场景
             this.scene = new THREE.Scene();
          },
          setCamera(){
              //创建相机
                //this.camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 10000 );
                this.camera=new THREE.PerspectiveCamera(45,this.container.clientWidth/this.container.clientHeight,0.1,10000);
                this.camera.position.set( 100, 20, 150 );
                this.camera.lookAt( 0, 6, 0 );
              //  this.camera.lookAt(this.scene.position);//设置相机方向(指向的场景对象)
          },
          setControls(){
                 //创建controls对象 控制器  摄像机 渲染到那个元素上
                let controls=new OrbitControls(this.camera,this.renderer.domElement)
              
                //监听控制器的鼠标事件,执行渲染内容
                controls.addEventListener('change',()=>{
                  this.renderer.render(this.scene,this.camera);
                })
                  //监听窗口的变化
                  window.addEventListener('resize',()=>this.onWindowResize());
          },
              //监听窗口的大小变化  还有相机的比例
           onWindowResize(){
                // this.camera.aspect=window.innerWidth/window.innerHeight;
                 this.camera.aspect=this.container.clientWidth/this.container.clientHeight;
                this.camera.updateProjectionMatrix();
               // this.renderer.setSize(window.innerWidth,window.innerHeight)  
                this.renderer.setSize(this.container.clientWidth,this.container.clientHeight)
            },
            //设置材质
          setFromPoints(){
                this.mercury = new THREE.Group()//建立一个组 一个自转
              
                this.mercuryParent =new THREE.Group()//建立一个组 一个公转
                this.scene.add(this.mercuryParent)

                const geometry = new THREE.BoxGeometry( 5, 5, 5 );
                const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
                this.mesh = new THREE.Mesh( geometry, material );
                // console.log(mesh) //通过打印可以调取里面的方法来控制物体的变化
               
                //缩放
                this.mesh.scale.set(3,2,1)
                //旋转  Math.PI等于180度
                this.mesh.rotation.set(Math.PI /45,0,0)

                this.mercury.position.x -= 30   //初始位置
                this.mercury.add(this.mesh)//添加到组里
					
					      this.mercuryParent.add(this.mercury)
            },
        //设置缓冲几何体
        setbuffmater(){
            // const geometry=new THREE.BufferGeometry();
            // //设置顶点数组  每三个值作为一个顶点  一维数组
            // const vertices=new Float32Array([
            //       -1.0,-1.0,1.0,
            //       1.0,-1.0,1.0,
            //       1.0,1.0,1.0,
            //       1.0,1.0,1.0,
            //       -1.0,1.0,1.0,
            //       -1.0,-1.0,1.0,
            // ]);
            // //把点传到属性上,设置位置点,  需要告诉它每三个组成一个顶点坐标
            // geometry.setAttribute('position',new THREE.BufferAttribute(vertices,3))
            // const material = new THREE.MeshBasicMaterial( {color: 0xff0000} );
            // const mesh = new THREE.Mesh( geometry, material );
            // this.scene.add(mesh)

            //创建几何体
            for(let i=0;i<50;i++){
               //每一个三角形,需要3个顶点,每个顶点需要3个值
               const geometry=new THREE.BufferGeometry();
               const positionArray=new Float32Array(9); //浮点类型数组  需要告诉它有9个值
               for(let j=0;j<9;j++){  //随机生成一个三角形顶点坐标 -5到5
                  positionArray[j]=Math.random()*10-5
               }
               geometry.setAttribute('position',new THREE.BufferAttribute(positionArray,3))
               //设置颜色随机
               let color=new THREE.Color(Math.random(),Math.random(),Math.random())
               //设置透明度transparent:true,opacity:0.5
               const material = new THREE.MeshBasicMaterial( {color:color,transparent:true,opacity:0.5} );
               const mesh = new THREE.Mesh( geometry, material );
               this.scene.add(mesh)
            }
   
        },
        //金属材质 MeshBasicMaterial 不受光照的影响
        basicmater(){
          //导入纹理 导入图片
          const textureLoader=new THREE.TextureLoader()
          //加载纹理
          const doorColorTexture=  textureLoader.load(require('../assets/img/5.png'))
          //加载黑白图片  黑表示隐藏  白色表示显示
          const doorAplhaTexture=textureLoader.load(require('../assets/img/4.png'))
          //环境这档贴图  黑色表示加深 暗光 白色表示白光
          const doorAoTexture=textureLoader.load(require('../assets/img/6.png'))
          //设置纹理属性 
          // doorColorTexture.offset.x= 0.5  //偏移 值的范围是0~1
          // doorColorTexture.offset.y= 0.5 
          // doorColorTexture.offset.set(0.5,0.5)
           //设置旋转原点
          // doorColorTexture.center.set(0.5,0.5)   //(0.5,0.5) 对应纹理的正中心  默认是(0,0) 左下角
         // 纹理旋转
          //doorColorTexture.rotation=Math.PI/4  //旋转45度
          //设置纹理的重复
          // doorColorTexture.repeat.set(2,3) //水平重复2次  垂直重复3次
          //设置纹理重复的模式
         // doorColorTexture.wrapS=THREE.RepeatWrapping;  //x轴 RepeatWrapping平铺重复
          //doorColorTexture.wrapT=THREE.MirroredRepeatWrapping; //y轴 镜像重复MirroredRepeatWrapping
          
          //texture纹理显示设置 很小像素的贴图比如16像素
          // const doorColorTexture=  textureLoader.load(require('../assets/img/3.png'))
          // doorColorTexture.minFilter=THREE.NearestFilter;
          // doorColorTexture.magFilter=THREE.NearestFilter;

           const cubeGeometry=new THREE.BoxBufferGeometry(10,10,10);
           const basicMaterial=new THREE.MeshBasicMaterial({
             //color:'#ffff00', //颜色
             map:doorColorTexture , //纹理
             alphaMap:doorAplhaTexture,  //加载透明纹理  就是黑白色图片 和opacity只设置一个就可以
             transparent:true,  //添加这个才生效透明纹理
             aoMap:doorAoTexture,  //环境遮挡贴图
             //aoMapIntensity:0.5,  //暗的强度 取值0~1
             //opacity:0.3, //透明度
            // side:THREE.DoubleSide, //两面
           })
           //也可以单独设置
           //basicMaterial.side=THREE.DoubleSide
           const cube=new THREE.Mesh(cubeGeometry,basicMaterial)
           //给cube添加第二组uv  可以加第二层环境遮挡贴图  cubeGeometry.attributes.uv之前本身的UV贴图拿过来继续用
           cubeGeometry.setAttribute('uv2',new THREE.BufferAttribute(cubeGeometry.attributes.uv.array,2))
           cube.position.x = 20

           this.scene.add(cube)
           
        },
        //灯光材质 标准的物理材质  平时基本用这种 MeshStandardMaterial 没有灯光就是黑色的  
        standmater(){


          

          let Event={}
           //单张纹理图的加载
          Event.onLoad=()=>{
             console.log('图片加载完成')
          }
          Event.onProgress=(url,num,total)=>{
             console.log('图片加载完成:',url)
             console.log('图片加载进度:',num)
             console.log('图片总数:',total)
             console.log('加载进度的百分比:',(num/total*100).toFixed(2)+'%')
          }
          Event.onError=(e)=>{
             console.log('图片加载出现错误')
             console.log(e)
          }
         

          //设置加载管理器
          const loadingManager=new THREE.LoadingManager(Event.onLoad, Event.onProgress,Event.onError) 
          
            //导入纹理 导入图片
          const textureLoader=new THREE.TextureLoader(loadingManager)
           //加载纹理
           const doorColorTexture=  textureLoader.load(require('../assets/img/5.png'),
               // Event.onLoad, Event.onProgress,Event.onError
           )

          //加载黑白图片  黑表示隐藏  白色表示显示
          const doorAplhaTexture=textureLoader.load(require('../assets/img/4.png'))
          //环境这档贴图  黑色表示加深 暗光 白色表示白光
          const doorAoTexture=textureLoader.load(require('../assets/img/6.png'))
          //导入置换贴图  黑色的隐藏 白色的凸出来显示
          const doorHeightTexture=textureLoader.load(require('../assets/img/9.png'))
          //导入粗糙贴图 黑色粗糙 白色光滑
          const roughnessTexture=textureLoader.load(require('../assets/img/11.png'))
          //导入金属贴图  黑色完全不是金属 白色是金属
          const metalnessTexture=textureLoader.load(require('../assets/img/7.png'))
           //导入法线贴图 
           const normalTexture=textureLoader.load(require('../assets/img/12.png'))
           //需要配置顶点
           const cubeGeometry=new THREE.BoxBufferGeometry(10,10,10,100,100,100);
           const basicMaterial=new THREE.MeshStandardMaterial({
             //color:'#ffff00', //颜色
             map:doorColorTexture , //纹理
             alphaMap:doorAplhaTexture,  //加载透明纹理  就是黑白色图片 和opacity只设置一个就可以
             transparent:true,  //添加这个才生效透明纹理
             aoMap:doorAoTexture,  //环境遮挡贴图
             displacementMap:doorHeightTexture,
             displacementScale:1,  //需要设置这个凸出   BoxBufferGeometry后面三位数值需要加顶点才生效
             roughness:1,//设置粗糙度 取值0~1  0是光滑 1是非常粗糙
             roughessMap:roughnessTexture, //粗糙贴图 roughness是乘关系
             metalness:1, //金属度 取值0~1  1完全是金属
             metalnessMap:metalnessTexture,   //金属贴图
             normalMap:normalTexture   //法线贴图
           })
       
           const cube=new THREE.Mesh(cubeGeometry,basicMaterial)
         
           cube.position.x = 40

           this.scene.add(cube)
        },
        //设置cube纹理加载器  环境贴图加载器
        cubetrue(){
         
          const cubeTextureLoader=new THREE.CubeTextureLoader()
          //前、后、上、下、左、右的顺序放图片
           const envMapTexture= cubeTextureLoader.load([
             require('../assets/img/heather_ft.jpg'),
             require('../assets/img/heather_bk.jpg'),
             require('../assets/img/heather_up.jpg'),
             require('../assets/img/heather_dn.jpg'),
             require('../assets/img/heather_rt.jpg'),
             require('../assets/img/heather_lf.jpg'),
           ])
          const sphereGeometry=new THREE.SphereBufferGeometry(4,20,20);
          const material =new THREE.MeshStandardMaterial({
             metalness:0.7, //金属度 取值0~1  1完全是金属
             roughness:0.1, //设置粗糙度 取值0~1  0是光滑 1是非常粗糙  
             envMap:envMapTexture  //环境贴图
          })
          const sphere=new THREE.Mesh(sphereGeometry,material)
          sphere.position.y =20
          //给场景添加背景图
          this.scene.background=envMapTexture
         // this.scene.environment=envMapTexture  //给场景所有的物体添加默认的环境贴图
          this.scene.add(sphere)
        },
        //灯光 
       light(){
             //环境光  没有方向
             const light=new THREE.AmbientLight(0xffffff,0.5); //环境光 灯光强度0~1
             this.scene.add(light)
             //直线光  比如太阳光  DirectionalLight  不知道为啥投射阴影失效 是不是版本的问题
             //SpotLight 聚光灯
            //  const directionalLight=new THREE.SpotLight(0xffffff,0.5);
            //  directionalLight.position.set(20,40,20)  //设置位置  
            //  //开启光照投射阴影
            //  directionalLight.castShadow=true
            //  //设置阴影贴图模糊度
            //  directionalLight.shadow.radius=10;
            //  //设置阴影贴图的分辨率
            //  directionalLight.shadow.mapSize.set(2048,2048);
            //  //聚光灯打在这个球上面
            //  directionalLight.target=this.sphere
            //  //更改聚光灯的角度 最大角度Math.PI/2
            //  directionalLight.angle=Math.PI/6
            //  //光源的衰减值 0是不衰减
            //  directionalLight.distance=0;
            //  //半影衰减
            //  directionalLight.penumbra=0; //取值是0~1
             
            //  this.scene.add(directionalLight)
            //  const gui=new dat.GUI()
            //   //有动画的时候不生效  修改位置
            //   gui.add(directionalLight,'penumbra')
            //       .min(0)   //最小值
            //       .max(1)  //最大值
            //       .step(0.1) // 每次移动的数量
              //点光源
            //   const pointLight=new THREE.PointLight(0xff0000,1)  
            //   pointLight.position.set(40,10,10)
            //    //开启光照投射阴影
            //   pointLight.castShadow=true
            //   //设置阴影贴图模糊度
            //   pointLight.shadow.radius=10;
            //   //光照的距离到哪里为0
            //   pointLight.distance=100;
            //  //设置阴影贴图的分辨率
            //   pointLight.shadow.mapSize.set(2048,2048);
            //   this.scene.add(pointLight)   
       }, 
       //设置光源在小球上面重叠
       smallBall(){
          this.samll=new THREE.Mesh(
             new THREE.SphereBufferGeometry(1,20,20),
             new THREE.MeshBasicMaterial({color:0xff0000})
          )
          this.samll.position.set(20,20,20)
           //点光源
           const pointLight=new THREE.PointLight(0xff0000,1,100) 
            //开启光照投射阴影
             pointLight.castShadow=true
           this.samll.add(pointLight)
          this.scene.add(this.samll)
       },

       //光照阴影  灯光与阴影
       spherGemet(){
         //1,材质要满足能够对关照有反应
         //   最常用-标准网格材质(MeshStandardMaterial)
         //   更消耗性能-物理网格材质(MeshPhysicalMaterial)-MeshStandardMaterial的扩展,
         //   提供了更高级的基于物理的渲染属性:
         //2,设置渲染器开启阴影的计算  renderer.shadowMap.enabled=true
         //3,设置光照投射阴影  directionalLight.castShadow=true
         //4,设置物体投射阴影  sphere.castShadow=true
         //5,设置物体接收阴影  plane.receiveShadow=true
         
          const sphereGeometry=new THREE.SphereBufferGeometry(4,20,20)
          const material=new THREE.MeshStandardMaterial()
          this.sphere=new THREE.Mesh(sphereGeometry,material)
          this.sphere.position.z=20
          //设置物体投射阴影 
          this.sphere.castShadow=true
          this.scene.add(this.sphere)
          //创建平面
          const planeGeomentry=new THREE.PlaneBufferGeometry(1000,1000)
          const plane=new THREE.Mesh(planeGeomentry,material)
          plane.position.set(0,-4,0)
          plane.rotation.x = -Math.PI/2
          //设置物体接收阴影
          plane.receiveShadow=true
          this.scene.add(plane)
       },
            //设置公转函数
			 revolution () {
			
            this.mercuryParent.rotation.y += 0.0016

        },
        //设置自转  旋转
        selfRotation(){

            this.mercury.rotation.y += 0.08

        },
        //时间动画
        gsaptime(){
             
         this.animate1=  gsap.to(this.mesh.position,{
              x:500,  
              duration:5, //持续时间
              repeat:-1,  //重复几次 无限循环-1
              ease:'power1.inOet', // ease更改速率
              yoyo:true, //往返运动
              delay:2,  //延迟2秒
              onComplete:()=>{  //onComplete回调函数
                console.log('动画完成')
              },onStart:()=>{
                console.log('动画开始')
              }
          })
            //旋转
            gsap.to(this.mesh.rotation,{x:2*Math.PI,duration:5})
        },
        //GUI
        gui(){
          const gui=new dat.GUI()
          //有动画的时候不生效  修改位置
          gui.add(this.mesh.position,'x')
              .min(0)   //最小值
              .max(1000)  //最大值
              .step(0.1) // 每次移动的数量
              .name('移动x轴') //命名
              .onChange((value)=>{
                 console.log('值被修改:',value)
              })
              .onFinishChange((value)=>{
                console.log('完全停下来:',value)
              })
          //修改物体颜色
          const params={
             color:'#ffff00',
             fn:()=>{
                //让立方体运动起来
                gsap.to(this.mesh.position,{x:500,duration:2,yoyo:true,repeat:-1})
             }
            }
          gui.addColor(params,'color').onChange((value)=>{
              console.log('值被修改',value)
              //设置材质的颜色
              this.mesh.material.color.set(value)
          })
          gui.add(this.mesh,'visible').name('是否显示')
          //点击触发某个事件
          gui.add(params,'fn').name('立方体运动')
          //文件夹
          const folder= gui.addFolder('设置立方体')
          //设置材质线框
          folder.add(this.mesh.material,'wireframe')

        },
         //初始化
         init() {
              this.setScene() //设置场景
				
              this.setCamera() //设置相机
                    
              this.setControls() //设置可旋转控制

              this.setFromPoints()  //材质

              this.setbuffmater()  //材质

              this.basicmater()  //金属材质

              this.standmater()  //灯光材质

              this.cubetrue() //纹理加载器

              this.spherGemet()  //光照阴影

              this.light()  //灯光

              this.smallBall()  //发光的小球
              
              //this.gsaptime()  //动画

              this.gui()   //gui

              this.animate(); // 循环动画
        },
         
        // 循环场景 、相机、 位置更新
        animate() {
            //获取时钟运行的总时长
           let time=this.clock.getElapsedTime();
           //实现圆周运动  Math.cos(x) x 的余弦值。返回的是 -1.0 到 1.0 之间的数
           this.samll.position.x=Math.sin(time)*30
           this.samll.position.z=Math.cos(time)*30
           //设置小球上下运动
           this.samll.position.y=20+Math.sin(time*10)
           // 获取间隔时长
          //  let deltaTime=this.clock.getDelta();
          //   console.log(deltaTime)
            requestAnimationFrame( this.animate);
            // this.revolution()
				  	// this.selfRotation()
            this.renderer.render( this.scene, this.camera);
         },
        }
      }
</script>

<style>
  #container {
    height: 1000px;
  }
  body{
    margin: 0;
    padding: 0;
  }
</style>

效果图1
vue2 threejs基础知识_第1张图片

你可能感兴趣的:(javascript,开发语言,ecmascript)