ThreeJS实现跳跃小球

523 阅读5分钟

入门ThreeJs

threejs是一个让用户通过javascript入手进入搭建webgl项目的类库。众所周知学习webgl需要图形学知识,而webgl需要通过js和glsl两种语言。如果我们不通过threejs使用webgl势必逃不过底层知识:必须全面了解着色器语法和自己编写顶点着色片元着色;但你使用了threejs可以便捷的逃过这些难懂的底层。

那么学习ThreeJS首先我们必须了解几个基础的概念:即什么是点、线、面,什么是几何体、材质、场景、相机、渲染器、动画、控制器。

点、线、面

这块主要为几何学里面的知识,我的个人理解是:在2D空间中两个坐标为一个点,两个点为一条线,三条以上的线就形成一个面(当然一条曲线和一条直线也可以形成一个面),借用百度百科的一段话来描述下他们之间关系就是:

  1. 点最重要的功能在于表明位置和进行聚焦,点与面是比较而形成的,同样一个点,如果布满整个或大面积的平面,它就是面了,如果在一个平面中多次出现,就可以理解为点;
  2. 点与点之间连接形成线,或者点沿着一定方面规律性的延伸可以成为线,线强调方向和外形;
  3. 平面上三个以上点的连接可以形成面,同时,平面上线的封闭或者线的展开也可以形成面,面强调形状和面积;

场景、相机、渲染器

首先我们先明白这三个基础概念,我们现在看到的浏览器是二维的屏幕,那么为了将三维的内容显示在二维的屏幕上。我们需要创建一个场景来放置物体,放置好物体后,由谁来帮助我们观察物体的各个角度的状态,这时候就引入了我们的相机,最后想要显示就要把相机拍的内容渲染出来,那么就用到了我们的渲染器。

 import * as THREE from 'three'
  // 声明场景
  const scene = new THREE.Scene()
   /* 初始化相机
   PerspectiveCamera属于透视相机 接受四个参数 
     fov:角度范围(视角范围) 
     aspect:渲染窗口的长宽比 
     near:从距离相机多远的位置开始渲染 
     far:表示的是距离相机多远的位置截止渲染
   */
  const camera = new THREE.PerspectiveCamera(
      75window.innerWidth / window.innerHeight,
      0.1,
      1000
  )
  // 设置相机在空间的位置
  camera.position.set(1,1,100)
  
  // 初始化渲染器
  const renderer = new THREE.WebGLRenderer();
  
 // 设置渲染尺寸大小
  renderer.setSize(window.innerWidth, window.innerHeight);
  
 // 将webgl渲染的canvas内容添加到body
  document.body.appendChild(renderer.domElement);
  
 // 在Vue中的话 通过Ref
 let container = ref(null)
 onMounted(()=>{
     container.value.appendChild(renderer.domElement)
 })

// 使用渲染器,通过相机将场景渲染进来
  renderer.render(scene, camera);

至此我们已经创建了一个基础的三维环境,接下来,我们可以向环境里面加入我们想展示的物体以及我们想要使用的工具。

几何体、材质、控制器

几何体也就是我们常说的多面体和球

    // 创建几何体 这里我们创建的是球体 接受三个基本参数  分别为 球的半径 水平分段 垂直分段
    const sphereGeometry = new THREE.SphereGeometry(50,50,50)
    // 创建材质 材质也就是这个几何体表面是什么样的,最简单的就是传入一个颜色来规定这个球表面颜色
    const sphereMaterial = new THREE.MeshBasicMaterial({color:0x00ff00})
    // 根据几何体和材质我们生成物体
    const cube = new THREE.Mesh(sphereGeometry,sphereMaterial)
    // 将物体添加到我们场景中
    scene.add(cube)

至此我们创建了一个几何体并把它显示到了我们的页面中,但是现在我们看到的是一个

image.png 一个圆形,并不是球体,那么这时候我们就需要用到我们的控制器了

    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
    const controls = new OrbitControls(camera, container.value)

当我们声明完控制器后,发现页面并没有什么变化,这是因为我们需要创建一个动画渲染函数,当我们操作时候以确保,相机拍摄的内容也要及时反馈到页面上

  const render = () => {
      renderer.render(scene, camera)
      requestAnimationFrame(render)
 }
 // 然后我们调用下这个函数
 render()
 // 在Vue中需要加载mounted里面调用
 onMounted(()=>{
  container.value.appendChild(renderer.domElement)
  render()
 })

效果还不太明显,那么这时候在我们没学习图片材质前我们可以加入坐标轴来进行观测

  const axesHelper = new THREE.AxesHelper(100)
  scene.add(axesHelper)

image.png

动画

最后就是我们的动画环节,动画其实和我们CSS中动画差不太多,也是通过改变几个属性值来实现 比如:

// 创建两个变量标注下当前我们的运动状态
// 1 表示首次运动 我们默认首次运动是Y轴和X轴正方向的运动
// 2 表示下落运动 
// 3 表示上升运动
let flagY = 1
let flagX = 1
// 重写我们的render函数
const render = () => {
  if (flagX === 1) {
    cube.position.x += 0.5
  }
  if (cube.position.x > 100 || flagX === 2) {
    flagX = 2
    cube.position.x -= 0.5
  }
  if (cube.position.x < -100 || flagX === 3) {
    flagX = 3
    cube.position.x += 0.5
  }
  if (flagY === 1) {
    cube.position.y += 0.5
  }
  if (cube.position.y > 20 || flagY === 2) {
    flagY = 2
    cube.position.y -= 0.5
  }
  if (cube.position.y < -20 || flagY === 3) {
    flagY = 3
    cube.position.y += 0.5
  }
  renderer.render(scene, camera)
  requestAnimationFrame(render)
}

test.gif 我们的动画至此也完成了,但ThreeJS的真正应用在于数字孪生、智慧城市、智慧园区、智慧工厂等等。我也会在后续时间内继续完成ThreeJS的进阶学习。