美文网首页
vue-three 基础模板

vue-three 基础模板

作者: name_howe | 来源:发表于2021-12-01 15:11 被阅读0次
    <template>
      <div>
        <div id="three"></div>
      </div>
    </template>
    
    <script>
    import * as THREE from "three";
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
    import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
    export default {
      data() {
        return {
          scene: {}, // 场景
          camera: {}, // 摄像机
          renderer: {}, // 渲染器
          parts: [], // 几何图形储存器
          mixer: null, // 动画
          clock: {}
        };
      },
      mounted(){
        this.threes();
        this.resize(); // 自适应
        this.mousedown(); // 鼠标点击事件
        this.mod();
      },
      methods: {
        // 浏览器窗口发生变化时 自适应
        resize(){
          window.addEventListener('resize', () => {
    
            // 初始化摄像机
            this.camera.aspect = window.innerWidth/window.innerHeight;
    
            // 摄像机矩阵效果
            this.camera.updateProjectionMatrix();
    
            // 初始化渲染器
            this.renderer.setSize(window.innerWidth, window.innerHeight);
    
          })
        },
    
        threes() {
          // 创建场景
          this.scene = new THREE.Scene();
    
          // 创建摄像机 // 参数含义: 视角、窗口投影长宽比、摄像机从哪里开始渲染、距离摄像机多远截至渲染
          this.camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
    
          // 创建three渲染器 参数: 去锯齿
          this.renderer = new THREE.WebGLRenderer({ antialias: true });
    
          // 设置渲染器场景背景颜色
          this.renderer.setClearColor(0x000000, .2)
    
          // 开启阴影,加上阴影渲染
          this.renderer.shadowMapEnabled = true;
    
          // 设置渲染器场景大小 参数: 宽,高
          this.renderer.setSize(window.innerWidth, window.innerHeight);
          
          // 把渲染器添加到页面中
          document.getElementById('three').appendChild(this.renderer.domElement);
    
          this.plane() // 平面模型
    
          this.wall({x: 500, y: 60, z: 10}, {x: 0, y: 30, z: -145}) // 外墙壁 1
          this.wall({x: 500, y: 60, z: 10}, {x: 0, y: 30, z: 145}) // 外墙壁 2
          this.wall({x: 10, y: 60, z: 300}, {x: 250, y: 30, z: 0}) // 外墙壁 3
          this.wall({x: 10, y: 60, z: 300}, {x: -250, y: 30, z: 0}) // 外墙壁 4
    
          this.wall({x: 10, y: 60, z: 120}, {x: 160, y: 30, z: -80}) // 内墙壁 5
          this.wall({x: 90, y: 60, z: 10}, {x: 200, y: 30, z: -20}) // 内墙壁 6
    
          for(let i = 0; i < 4; i ++){
            // this.chartlet(-220, 30, (-100 +  i * 41)) // 横排
            this.chartlet((-220 + i * 35), 30, -100) // 纵排
            this.chartlet((-220 + i * 35), 30, -55) // 纵排
            this.chartlet((-220 + i * 35), 30, 100) // 纵排
            this.chartlet((-220 + i * 35), 30, 55) // 纵排
          }
          this.vavAair(100,50,135)
    
          // 将网格对象添加到场景中
          this.parts.forEach(item => {
            this.scene.add(item);
          });
          
          // 创建光源
          this.createLight()
    
          // 辅助坐标系  参数250表示坐标系大小,可以根据场景大小去设置
          this.axesHelper = new THREE.AxesHelper(500);
    
          // 将坐标系添加到场景中
          this.scene.add(this.axesHelper);
    
          // 摄像机空间轴位置
          this.camera.position.z = 300
          this.camera.position.y = 350
          this.camera.position.x = 100
    
          // 创建鼠标控件对象
          this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    
          this.animate()
        },
    
        // 添加帧渲染
        animate(){
          let that = this
          requestAnimationFrame(this.animate);
          // 网格对象自动旋转
          // this.cube.rotation.x += 0.005
          // this.cube.rotation.y += 0.005
    
          if (this.mixer !== null){
            that.mixer.update(that.clock.getDelta());
          }
    
          // 初始化controls
          this.controls.update()
    
          this.render()
        },
    
        // 渲染器渲染场景和摄像机
        render(){
          this.renderer.render(this.scene, this.camera)
        },
    
        // 创建光源
        createLight () {
          // 环境光
          const ambint = new THREE.AmbientLight(0xffffff)
          this.scene.add(ambint)
          // 聚光灯光源
          this.spotLight(0x03FF6A, 245, 60, 140, 600)
          this.spotLight(0xff0000, -245, 60, 140, 500)
          // this.pointLight(0xffffff, 0, 900, 0, 1000)
          this.pointLight(0x0070ee, 205, 100, -80, 130)
        },
    
        // 聚光灯光源
        spotLight (color, x, y, z, dis) {
          const spotLight = new THREE.SpotLight(color)
          spotLight.position.set(x, y, z); // 光源位置
          spotLight.castShadow = true; //开启灯光投射阴影
          spotLight.intensity = 3 // 强度
          spotLight.angle = 0.3; // 角度
          spotLight.penumbra = 1; // 半影
          spotLight.decay = 1; // 衰退
          spotLight.distance = dis; // 距离
    
          this.scene.add(spotLight)
    
          // 辅助线
          // let spotLightHelper = new THREE.SpotLightHelper(spotLight, 0x976fb6);
          // this.scene.add(spotLightHelper)
    
          // 光源寄托
          this.createLightView(color, x, y, z)
        },
        // 点光灯光源
        pointLight (color, x, y, z, dis) {
          const pointLight = new THREE.PointLight(color)
          pointLight.position.set(x, y, z); // 光源位置
          pointLight.castShadow = true; //开启灯光投射阴影
          pointLight.intensity = 4 // 强度
          // pointLight.angle = 0.3; // 角度
          pointLight.penumbra = 1; // 半影
          // pointLight.decay = 1; // 衰退
          pointLight.distance = dis; // 距离
    
          this.scene.add(pointLight)
    
          // 辅助线
          // let spotLightHelper = new THREE.SpotLightHelper(pointLight, 0x976fb6);
          // this.scene.add(spotLightHelper)
    
          // 光源寄托
          this.createLightView(color, x, y, z)
        },
    
        // 光源寄托
        createLightView(color, x, y, z){
          let geometry = new THREE.SphereGeometry(3, 3, 3);
          let material = new THREE.MeshPhongMaterial({ color });
          let cube = new THREE.Mesh(geometry, material);
          cube.position.set(x, y, z)
          this.scene.add(cube)
        },
    
        // 平面模型
        plane(){
          let geometry = new THREE.PlaneGeometry(640, 400, 1, 1);
          let material = new THREE.MeshPhongMaterial({ color: 0xE5E5E5, wireframe: false });
          let cube = new THREE.Mesh(geometry, material);
          cube.rotation.x = -0.5 * Math.PI
          cube.position.set(0, 0, 0)
          cube.receiveShadow = true
    
          this.parts.push(cube)
        },
    
        // 墙壁
        wall(size, position){
          let texture = new THREE.TextureLoader().load(require('@/assets/three/tile.jpg'));
          texture.anisotropy = 4
          let data = {
            map: texture,
            // color: 0x07313F,
            transparent: true,
            opacity: 1
          }
          let geometry = new THREE.BoxGeometry(size.x, size.y,size.z);
          let material = new THREE.MeshLambertMaterial(data);
          let cube = new THREE.Mesh(geometry, material);
          cube.position.set(position.x, position.y, position.z)
          this.scene.add(cube);
        },
    
        // 机柜
        chartlet(x, y, z){
          let map = new THREE.TextureLoader().load(require('@/assets/three/jigui.jpg'));
          let group = new THREE.Mesh();
          let mats = [];
          mats.push(new THREE.MeshPhongMaterial({ map }));
          mats.push(new THREE.MeshPhongMaterial({
            color: 0x3C3B42
          }));
          mats.push(new THREE.MeshPhongMaterial({
            color: 0x3C3B42
          }));
          mats.push(new THREE.MeshPhongMaterial({
            color: 0x3C3B42
          }));
          mats.push(new THREE.MeshPhongMaterial({
            color: 0x3C3B42
          }));
          mats.push(new THREE.MeshPhongMaterial({
            color: 0x3C3B42
          }));
    
          let cubeGeom = new THREE.BoxBufferGeometry(15, 50, 30);
          let cube = new THREE.Mesh(cubeGeom, mats);
          cube.position.set(x, y, z)
    
          group.add(cube);
          this.scene.add(group)
        },
    
        // 空调
        vavAair(x, y, z){
          let map = new THREE.TextureLoader().load(require('@/assets/three/kt.png'));
          let group = new THREE.Mesh();
          let mats = [];
          mats.push(new THREE.MeshPhongMaterial({ color: 0xffffff }));
          mats.push(new THREE.MeshPhongMaterial({
            color: 0xffffff
          }));
          mats.push(new THREE.MeshPhongMaterial({
            color: 0xffffff
          }));
          mats.push(new THREE.MeshPhongMaterial({
            color: 0xffffff
          }));
          mats.push(new THREE.MeshPhongMaterial({
            color: 0xffffff
          }));
          mats.push(new THREE.MeshPhongMaterial({
            map
          }));
    
          let cubeGeom = new THREE.BoxBufferGeometry(40, 15, 15);
          let cube = new THREE.Mesh(cubeGeom, mats);
          cube.position.set(x, y, z)
    
          group.add(cube);
          this.scene.add(group)
        },
    
        // 鼠标点击事件
        mousedown(){
          let raycaster = new THREE.Raycaster(); //光线投射,用于确定鼠标点击位置
          let mouse1 = new THREE.Vector2()
          let mouse2 = new THREE.Vector2()
    
          let top = 69
    
          window.addEventListener("pointerdown", (event) => {
            mouse1.x = ( event.clientX / window.innerWidth ) * 2 - 1;
            mouse1.y = - ( (event.clientY - top) / window.innerHeight ) * 2 + 1;
          });
          window.addEventListener("pointerup", (event) => {
            mouse2.x = ( event.clientX / window.innerWidth ) * 2 - 1;
            mouse2.y = - ( (event.clientY - top) / window.innerHeight ) * 2 + 1;
            if(mouse1.x === mouse2.x && mouse1.y === mouse2.y){
              //以camera为z坐标,确定所点击物体的3D空间位置
              raycaster.setFromCamera(mouse1, this.camera);
              //确定所点击位置上的物体数量
              let intersects = raycaster.intersectObjects(this.scene.children);
              //选中后进行的操作
              if(intersects.length){
                console.log(intersects)
                // intersects[0].object.material.color.set( 0xff0000 );
              }
            }
          });
        },
    
        // 引入模型 人物
        mod(){
          let that = this
          let loader = new FBXLoader()
          loader.load('three/SambaDancing.fbx', function(obj){
            obj.scale.set(.35, .35, .35); // 放大缩小
            obj.position.set(205, 0, -80); // 位置
            obj.rotation.y += 1.55; // 旋转
            that.scene.add(obj)
    
            that.clock = new THREE.Clock()
            // obj作为参数创建一个混合器,解析播放obj及其子对象包含的动画数据
            that.mixer = new THREE.AnimationMixer(obj);
            let animationAction = that.mixer.clipAction(obj.animations[0]);
            // animationAction.timeScale = 1; //默认1,可以调节播放速度
            // animationAction.loop = THREE.LoopOnce; //不循环播放
            // animationAction.clampWhenFinished=true;//暂停在最后一帧播放的状态
            animationAction.play(); //播放动画
          }, undefined, function ( error ) {
            console.error( error );
          });
        },
    
      }
    
    };
    </script>
    
    <style scoped>
    body {
      margin: 0;
      padding: 0;
      background-color: #000;
      color: #fff;
      font-family: Monospace;
      font-size: 13px;
      line-height: 24px;
      overscroll-behavior: none;
    }
    #info {
      position: absolute;
      top: 0px;
      width: 100%;
      padding: 0;
      box-sizing: border-box;
      text-align: center;
      -moz-user-select: none;
      -webkit-user-select: none;
      -ms-user-select: none;
      user-select: none;
      pointer-events: none;
      z-index: 1; /* TODO Solve this in HTML */
    }
    </style>
    

    相关文章

      网友评论

          本文标题:vue-three 基础模板

          本文链接:https://www.haomeiwen.com/subject/zliqyltx.html