第一天:基础

24 阅读4分钟

three.js其实是使用WebGL来绘制三维效果的,它封装了诸如场景、灯光、阴影、材质、贴图、空间运算等一系列功能,让你不必要再从底层WebGL开始写起。

threejs-structure.svg 上图需要注意的事项:

下面在vue中使用three.js绘制出三个可以旋转的立方体的例子:

QQ截图20231016162331.png

<template>
  <div style="position:relative;width:100%;height: 100%;">
    <canvas id="op"></canvas>
  </div>
</template>

<script setup lang="ts">
import * as THREE from 'three'
import { onMounted } from 'vue';
onMounted(() => {
  main();
})
function main() {

  const canvas = document.querySelector('#op');
  const renderer = new THREE.WebGLRenderer({ antialias: true, canvas }); // 创建WEBGL渲染器

  const fov = 75;
  const aspect = 2; // the canvas default
  const near = 0.1;
  const far = 5;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); // 创建摄像机对象
  camera.position.z = 2;

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

  {

    const color = 0xFFFFFF;
    const intensity = 3;
    const light = new THREE.DirectionalLight(color, intensity);
    light.position.set(- 1, 2, 4);
    scene.add(light); // 添加灯光效果

  }

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

  function makeInstance(geometry, color, x) {

    const material = new THREE.MeshPhongMaterial({ color }); // 创建材质对象

    const cube = new THREE.Mesh(geometry, material); // 创建网格对象
    scene.add(cube);

    cube.position.x = x;

    return cube;

  }

  const cubes = [
    makeInstance(geometry, 0x44aa88, 0),
    makeInstance(geometry, 0x8844aa, - 2),
    makeInstance(geometry, 0xaa8844, 2),
  ];

  function render(time) {

    time *= 0.001;
    // 解决不同屏幕保持比例与清晰度问题
    if (resizeRendererToDisplaySize(renderer)) {
    // 通过设置相机的宽高比为canvas的宽高比解决比例适配问题
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }
    // 旋转动画效果
    cubes.forEach((cube, ndx) => {

      const speed = 1 + ndx * .1;
      const rot = time * speed;
      cube.rotation.x = rot;
      cube.rotation.y = rot;

    });

    renderer.render(scene, camera);

    requestAnimationFrame(render);

  }
  // 与图片相似,canvas内部分辨率又叫做绘图缓冲区(drawingbuffer)尺寸,设置canvas的绘图缓冲区与canvas显示尺寸相同解决清晰度问题
  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    console.log('canvas', canvas)
    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;
  }
  requestAnimationFrame(render);

}

</script>

<style scoped>
#op {
  display: block;
  width: 100%;
  height: 100%;
}
</style>