threejs基本教程

194 阅读4分钟

本章简单介绍threejs的基本用法。从最基础的代码写起,去了解threejs的大致使用流程。threejs中主要包含:场景,相机,渲染器,以及要展示的相关物体。

本文主要总结了B站老陈打码的three.js入门课程基本知识点,具体内容可去视频网站查看。

1、引入threejs包

首先先下载相关的npm包。

npm i --save three

然后通过import引入所需要的构造函数等

import { Scene, PerspectiveCamera, WebGLRenderer, BoxGeometry, MeshBasicMaterial, Mesh, AxesHelper } from 'three';

2、搭建基本的代码

// 场景
const scene = new Scene();

// 相机
const camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 10);
scene.add(camera);

// 相关物体
const geometry = new BoxGeometry(1, 1, 1);
const material = new MeshBasicMaterial({ color: 0x00ff00 });
const cube = new Mesh(geometry, material);
scene.add(cube);

// 渲染器
const renderer = new WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.render(scene, camera);

以上通过搭建一个场景,在场景中加入相机,物体,然后通过渲染器把画面渲染到dom元素中。上面的renderer.domElement其实是一个canvas元素。

代码效果:

image.png

3、加入轨道控制器和坐标辅助器

// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
controls.enableDamping = true;

// 添加坐标轴辅助器
const axesHelper = new AxesHelper(5);
scene.add(axesHelper);

// 动画函数
function animate() {
  controls.update();
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}
animate();

轨道控制器可以使得相机围绕目标进行轨道运动,其引入方式和其他的引入不太一样,需要从examples引入。引入后,鼠标即可拖拽物体进行多方位查看。轨道控制器创建成功后,需要启动动画函数才会生效。控制的阻尼效果,是停止对物体的拖拽查看后,物体会慢慢停下,而不是立刻。

下图中的红,绿,蓝三条线即为添加的坐标轴,分别对应x,y,z轴。为了区分颜色,给正方体换成了黄色。

image.png

4、加入物体移动,旋转动画

function animate() {
  cube.position.x += 0.01;
  if (cube.position.x > 5) {
    cube.position.x = 0;
  }
  cube.rotation.x += Math.PI / 180;
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}

通过在动画函数中修改正方体的位置属性,从而实现最基础的物体移动。效果如下:

image.png

不过,这种移动可能会出现忽快忽慢的情况。本质原因是requestAnimationFrame会在每一帧之前进行回调,但实际情况中,帧间隔时间不是稳定的。代码进行优化如下:

function animate(time: DOMHighResTimeStamp) {
  let t = (time / 1000) % 5;
  cube.position.x = t * 1;
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}

以上写法是通过我们自己去修改物体的属性来完成平移和旋转。接下来是借助一个工具库gsap,完成同样的动画。首先安装:

npm i gsap

下面是新代码:

// 设置动画
let animate1 = gsap.to(cube.position, {
  x: 5,
  duration: 5,
  ease: "power1.inOut",
  //   设置重复的次数,无限次循环-1
  repeat: -1,
  //   往返运动
  yoyo: true,
  //   delay,延迟2秒运动
  delay: 2,
  onComplete: () => {
    console.log("动画完成");
  },
  onStart: () => {
    console.log("动画开始");
  },
});

// 动画函数
function animate(time: DOMHighResTimeStamp) {
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}

通过gsap设置对应的动画,相关属性介绍都在代码中,具体的用法可前往官网查看。通过事件,我们也可以实现动画的暂停和继续。如下:

window.addEventListener("dblclick", () => {
  if (animate1.isActive()) {
    //   暂停
    animate1.pause();
  } else {
    //   恢复
    animate1.resume();
  }
});

5、画面自适应优化

当窗口大小变化时,需要更新摄像头和渲染器来保证良好的视觉效果。如下:

// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {
  // 更新摄像头
  camera.aspect = window.innerWidth / window.innerHeight;
  //   更新摄像机的投影矩阵
  camera.updateProjectionMatrix();

  //   更新渲染器
  renderer.setSize(window.innerWidth, window.innerHeight);
  //   设置渲染器的像素比
  renderer.setPixelRatio(window.devicePixelRatio);
});

6、添加可视化页面GUI

可视化GUI用于用户手动控制场景的物体等。通过GUI可以随时调节物体的位置,颜色,是否展示,动画等等。

// 修改物体位置
gui
  .add(cube.position, "x")
  .min(0)
  .max(5)
  .step(0.01)
  .name("移动x轴")
  .onChange((value) => {
    console.log("值被修改:", value);
  })
  .onFinishChange((value) => {
    console.log("完全停下来:", value);
  });
//   修改物体的颜色
const params = {
  color: "#ffff00",
  fn: () => {
    //   让立方体运动起来
    gsap.to(cube.position, { x: 5, duration: 2, yoyo: true, repeat: -1 });
  },
};
gui.addColor(params, "color").onChange((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("立方体运动");

如下图所示,滑动移动X轴,可以更改物体在x轴的位置;点击color可以修改物体的颜色......

image.png