初学Threejs,vue实现

199 阅读3分钟

老板最近让改threejs代码的需求
前端小实习记录一下初学three.js
从Hello cube!开始
欢迎各位大佬批评指正

官方文档:three.js

1、首先安装threejs

npm install --save three

2、需要一个canvas标签

<template>
  <div class="three-canvas">
    <h1>hello cube!</h1>
    <canvas id="c"></canvas>
  </div>
</template>

3、引入threejs

轨道控制器可以实现鼠标效果,实现旋转、放大缩小等功能

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'    //引入轨道控制器

4、定义data

data() {
    return {
        camera: null,
        scene: null,
        renderer: null,
        cube:null,
        cubes:null,
        geometry:null,

        // 轨道控制器
        orbitControls:null,    
    }
  },

5、

 methods: {
    init() {
        const canvas = document.querySelector('#c')
        this.renderer = new THREE.WebGLRenderer({      //创建一个WebGL渲染器
            antialias: true,   //是否开启反锯齿
            canvas             //渲染器WebGLRenderer 负责将提供的所有数据渲染绘制到 canvas 上
        })

        // 需要一个透视摄像机 PerspectiveCamera
        const fov = 75;    //视野范围 field of view    垂直方向为75度
        const aspect = 2;  //相机默认值    画布的宽高比    默认情况下: 画布是300x150像素
        const near = 0.1;  //近平面
        const far = 5;     //远平面    近平面和远平面限制了摄像机面朝方向的可绘区域。 任何距离小于或超过这个范围的物体都将被裁剪掉(不绘制)
        // 四个参数定义了一个“视锥(frustum)”。是指一个像被削去顶部的金字塔形状。可以想象成其他三维形状如球体、立方体、棱柱体、截锥体
        this.camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
        this.camera.position.z = 2  //摄像机默认指向Z轴负方向,上方向朝向Y轴正方向。将立方体放置在坐标原点,需要后移一下摄像机才能显示出物体

        this.scene = new THREE.Scene();  //创建一个场景

        //创建一个包含盒子信息的立方几何体 BoxGeometry
        const boxWidth = 1;
        const boxHeight = 1;
        const boxDepth = 1;
        this.geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);

        // 创建一个基本的材质 并设置它的颜色 
        // MeshBasicMaterial材质不会受到灯光的影响。我们将他改成会受灯光影响的MeshPhongMaterial材质。
        const material = new THREE.MeshPhongMaterial({color: 0x44aa88});

        // 创建一个网格(Mesh)对象,包含:1、几何体(Geometry)(物体的形状);2、材质(Material)(如何绘制物体,光滑还是平整,什么颜色,什么贴图等);3、对象在场景中相对于他父对象的位置、朝向、和缩放。
        this.cube = new THREE.Mesh(this.geometry, material);

        // 将网格添加到场景中
        this.scene.add(this.cube);

        // 将场景和摄像机传递给渲染器来渲染出整个场景
        this.renderer.render(this.scene, this.camera)

        // 增加光照效果
        const color = 0xFFFFFF;
        const intensity = 1;
        const light = new THREE.DirectionalLight(color, intensity);
        light.position.set(-1, 2, 4);  //将灯光位置设为(-1,2,4) 位于摄像机前面稍微左上方一点的地方
        this.scene.add(light);

        // 轨道控制器 实现鼠标旋转缩放
        this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement)

    },

    // 让立方体旋转起来  需要用到一个渲染循环函数 requestAnimationFrame  
    // requestAnimationFrame会将页面开始加载到函数运行所经历的时间当作入参传给回调函数,单位是毫秒数。
    // render(time) {
    //     time *= 0.001;  //将时间单位变为秒

    //     this.cube.rotation.x = time;
    //     this.cube.rotation.y = time;

    //     this.renderer.render(this.scene, this.camera);

    //     requestAnimationFrame(this.render);
    // },

    // 创建一个根据指定颜色生成新材质的函数。根据指定的几何体生成对应网格,然后将网格添加进场景并设置其X轴的位置
    makeInstance(geometry, color, x) {
        const material = new THREE.MeshPhongMaterial({color});
        this.cube = new THREE.Mesh(geometry, material);
        this.scene.add(this.cube);
        
        this.cube.position.x = x;
        return this.cube
    },
    
    // 多个立方体自动旋转
    render(time) {
        time *= 0.001;  //将时间单位变为秒
        this.init();
        this.animate()  //逐帧渲染

        // const canvas = this.renderer.domElement;
        // this.camera.aspect = canvas.clientWidth / canvas.clientHeight; //将相机的宽高比设置为canvas的宽高比,保持正常比例
        // this.camera.updateProjectionMatrix();

        if (this.resizeRendererToDisplaySize(this.renderer)) {
            const canvas = this.renderer.domElement;
            this.camera.aspect = canvas.clientWidth / canvas.clientHeight;
            this.camera.updateProjectionMatrix();
        }

        // 实现多个正方体
        // this.cubes = [                                                    
        //     this.makeInstance(this.geometry, 0x44aa88,  0),
        //     this.makeInstance(this.geometry, 0x8844aa, -2),
        //     this.makeInstance(this.geometry, 0xaa8844,  2),
        // ];

        // this.cubes.forEach((cube, ndx) => {
        //     const speed = 1 + ndx * .1;
        //     const rot = time * speed;
        //     cube.rotation.x = rot;
        //     cube.rotation.y = rot;
        // });

        this.renderer.render(this.scene, this.camera);

        // requestAnimationFrame(this.render);
    },

    // 写一个函数来检查渲染器的canvas尺寸是不是和canvas的显示尺寸不一样 如果不一样就设置它。
    resizeRendererToDisplaySize(renderer) {
        const canvas = renderer.domElement;
        const width = canvas.clientWidth;
        const height = canvas.clientHeight;
        const needResize = canvas.width !== width || canvas.height !== height;
        if (needResize) {
            renderer.setSize(width, height, false);
        }
        return needResize;
    },

    // 逐帧渲染 threejs
    animate() {
        this.renderer.render(this.scene, this.camera) 
        requestAnimationFrame(this.animate)
    }
  },

6、

mounted() {
    // this.init();
    this.render()
  },

有点蛇头蛇尾了哈哈哈哈,具体内容都写在注释里啦hhh