threeJs学习笔记(一)

官网:Three.js – JavaScript 3D Library

1.threeJs三要素

1.场 景:放置物体的容器

import * as THREE from 'three'

let scene = new THREE.Scene()

2.摄像机:类似人眼,可调位置,角度等信息,展示不同画面

// 参数1:垂直角度(建议 75),视野范围
// 参数2:宽高比(建议与画布相同宽高),物体绘制比例
// 参数3:近截面距离摄像机距离
// 参数4:远截面距离摄像机距离
let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)

摄像机 4 个参数讲解:

  1. 角度:视野垂直范围,越大看到越多,物体越小

  2. 宽高比:影响图形拉伸/压缩,摄像机宽高比 = 画布宽高比(标准图形)

  3. 近截面:近边界

  4. 远截面:远边界

3.渲染器:接收场景和摄像机,计算在浏览器上渲染的最终 2D 画面

//创建渲染器
let renderer = new THREE.WebGLRenderer()

例如(以下代码俊以vue3为例):

下包:npm  i  three

<template>
  <div id="threeID">

  </div>
</template>

<script setup>
// 1. 引入 three 库
import * as THREE from 'three'
// 创建场景,摄像机,渲染器
let scene, camera, renderer

function init() {
  // 2. 创建场景对象
  scene = new THREE.Scene()
  // 3. 创建摄像机对象
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
  // 4. 创建渲染器,并设置画布大小,添加到 DOM 显示
  renderer = new THREE.WebGLRenderer()
  // 设置画布大小
  renderer.setSize(window.innerWidth, window.innerHeight)
  // 把画布 canvas 标签添加到id为threeID上
  document.querySelector('#threeID').append(renderer.domElement)
  // 传入场景和摄像机,渲染画面
  renderer.render(scene, camera)
}

onMounted(() => {
  init()
})
</script>

<style  scoped></style>

 2.three.js立方体

1. 创建图形,宽高深为 1 单位(立方缓冲几何体)

const geometry = new THREE.BoxGeometry(1, 1, 1);

2. 创建材质,颜色为绿色 0x00ff00 (网格基础材质-线面纯颜色描绘表面) 

const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

3. 创建网格物体对象,传入图形和材质(网格物体对象)

const cube = new THREE.Mesh(geometry, material);

4. 把创建的物体加入到场景中 

scene.add(cube);

整个代码:

function createCube() {
  // 1. 创建图形,宽高深为 1 单位(立方缓冲几何体)
  const geometry = new THREE.BoxGeometry(1, 1, 1);
  // 2. 创建材质,颜色为绿色 0x00ff00 (网格基础材质-线面纯颜色描绘表面)
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  // 3. 创建网格物体对象,传入图形和材质(网格物体对象)
  const cube = new THREE.Mesh(geometry, material);
  // 4. 把物体加入到场景中
  scene.add(cube);
}

onMounted(() => {
  init()
  createCube()
  renderer.render(scene, camera)
})

移动摄像机向z轴5个单位(默认摄像机和物体在原点)

 camera.position.z = 5

更多材质和几何体需要查询官方文档

 3.three.js轨道控制器

目的:使摄像机围绕目标进行轨道运动,可以右键拖动,左键旋转,滚轮拉进,拉远摄像机。

 1.单独引入 OrbitControls 轨道控制器构造函数

import { OrbitControls } from 'three/addons/controls/OrbitControls.js'

2.创建轨道控制器

let controls
controls = new OrbitControls( camera, renderer.domElement )

 3.在渲染循环中更新场景渲染

function renderLoop() {
//在渲染循环中更新场景渲染
renderer.render(scene, camera)

// 手动 JS 代码更新过摄像机信息,必须调用轨道控制器 update 方法
controls.update()

// 根据当前计算机浏览器刷新帧率(默认 60 次/秒),不断递归调用此函数渲染最新的画面状态
// 好处:当前页面切换到后台,暂停递归
requestAnimationFrame(renderLoop)
}

renderLoop()

4.three.js坐标轴

目的:一个 x,y,z 方向的坐标轴辅助对象 ,帮我们理解物体在世界坐标系中位移,缩放,渲染等效果,可以辅助我们开发和调试。

function createHelper() {
  // 1. 创建坐标轴对象,设置长度
  const axesHelper = new THREE.AxesHelper(5)
  // 2. 添加到场景中
  scene.add(axesHelper)
}

createHelper()

5.three.js轨道控制器-控制效果

目的:调整轨道控制器属性,影响摄像机细节

阻尼效果(带有缓冲效果):new OrbitControls(camera, renderer.domElement).enableDamping = true

开启自动旋转轨道控制器效果:new OrbitControls(camera, renderer.domElement).autoRotate = true

function controlsCreate() {
  //  创建轨道控制器
  controls = new OrbitControls(camera, renderer.domElement)
  // 1. 阻尼效果
  controls.enableDamping = true
  // 2. 开启自动旋转轨道控制器效果->带动摄像机一起旋转(摄像机顺时针水平旋转)
  // controls.autoRotate = true
  // 3. 垂直角度范围控制(0 上面,Math.PI 下面)
  controls.maxPolarAngle = Math.PI
  controls.minPolarAngle = 0
  // 水平角度范围控制
  controls.maxAzimuthAngle = 1.5 * Math.PI
  controls.minAzimuthAngle = 0.5 * Math.PI
  // 4. 摄像机移动范围控制
  controls.minDistance = 2
  controls.maxDistance = 10
}

更多属性查看官方文档:

6. 优化-适配场景大小

目的:浏览器窗口,尺寸改变时,画布自适应

1.创建适配函数,监听浏览器 resize 事件

2.调整渲染器画布宽高,摄像机宽高比和更新视椎体空间

function createHelper() {
  // 1. 创建坐标轴对象,设置长度
  const axesHelper = new THREE.AxesHelper(5)
  // 2. 添加到场景中
  scene.add(axesHelper)
}
renderResize()

7.three.js移动立方体

目的:移动目标立方体,查看效果和 three.js 组织对象的类关系

1.位移 position 属性

2.旋转 rotation 属性

3.缩放 scale 属性

function moveCube() {
  // 1. 位移 position 属性(Vector3 三维向量对象)
  cube.position.x = 5
  // cube.position.set(5, 5, 0)
  // 2. 旋转 rotation 属性(Euler 欧拉角弧度制角度对象)
   在轴的正方向看是逆时针旋转
  // cube.rotation.x = Math.PI / 4
  // 3. 缩放 scale 属性(Vector3 三维向量对象,中心原点不动,向 2 边拉伸/缩小)
   cube.scale.z = 2
}
moveCube()

8.three.js 使用 GUI 工具

目的:借助 GUI 工具实时辅助调试 3D 物体

安装:npm i dat.gui

引入:import * as dat from 'dat.gui'

使用:

1. 创建 GUI 对象

  const gui = new dat.GUI()

2.添加具体控制器使用

gui.add(参数1,参数2)

参数1:关联 DOM 对象,JS 对象,3D 物体对象

参数2:对象其中的某个属性,给这个属性关联用户界面工具(从而快速调整它的值)

3.控制立方体颜色

gui.addColol()

4.创建分组-影响立方体位置

 gui.addFolder()

插件文档:https://github.com/dataarts/dat.gui/blob/master/API.md 

function createGUI() {
  const gui = new dat.GUI()
  gui.add(document, 'title')

  // 1 控制立方体显示/隐藏(布尔->多选框)
  gui.add(cube, 'visible')
  // 2 轨道控制器回归初始角度(函数->按钮)
  gui.add(controls, 'reset')
  // 3 控制立方体颜色(找属性方式:文档->打印->百度)
  // 效果:立方体默认颜色和文字 <=> 显示在工具标签上
  const colorObj = {
    'col': `#${cube.material.color.getHexString()}`
  }
  gui.addColor(colorObj, 'col').onChange(val => {
    // val: #ff00ff 十六进制的颜色字符串
    cube.material.color = new THREE.Color(val)
  })
  // 4 创建分组-影响立方体位置
  const folder = gui.addFolder('位移')
  // 参数3:最小值范围,参数4:最大值范围,参数5:步长 (数字->进度条)
  folder.add(cube.position, 'x', 0, 5, 0.1)
  folder.add(cube.position, 'y', 0, 5, 0.1)
  folder.add(cube.position, 'z', 0, 5, 0.1)
  // 5 下拉菜单(关键:第三个参数为对象时->下拉菜单)
  // 对象中属性名->下拉菜单选项名
  // 初始值匹配后会影响下拉菜单默认选中哪一项
  gui.add({ type: '1' }, 'type', { '方案1': '1', '方案2': '2', '方案3': '3' }).onChange(val => {
    // val 方案对象的 '1','2'
    switch (val) {
      //方案1
      case '1':
        cube.position.set(0, 0, 0)
        break;
      //方案2
      case '2':
        cube.position.set(2, 2, 2)
        break;
      //方案3
      case '3':
        cube.position.set(2, 0, 0)
        break;
    }
  })

}
createGUI()

整个代码:

<template>
  <div id="threeID">

  </div>
</template>

<script setup>
//  引入 three 库
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
//引入dat.gui 库
import * as dat from 'dat.gui'
// 创建场景,摄像机,渲染器
let scene, camera, renderer
// 创建轨道控制器
let controls
//创建立方体
let cube

/**
 * 创建基础场景
 */
function init() {
  // 1. 创建场景对象
  scene = new THREE.Scene()
  // 2. 创建摄像机对象
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
  //移动摄像机向z轴5个单位(默认摄像机和物体在原点)
  camera.position.z = 5
  // 3. 创建渲染器,并设置画布大小,添加到 DOM 显示
  renderer = new THREE.WebGLRenderer()
  // 设置画布大小
  renderer.setSize(window.innerWidth, window.innerHeight)
  // 把画布 canvas 标签添加到id为threeID上
  document.querySelector('#threeID').append(renderer.domElement)
}

/**
 * 创建立方体
 */
function createCube() {
  // 1. 创建图形,宽高深为 1 单位(立方缓冲几何体)
  const geometry = new THREE.BoxGeometry(1, 1, 1);
  // 2. 创建材质,颜色为绿色 0x00ff00 (网格基础材质-线面纯颜色描绘表面)
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  // 3. 创建网格物体对象,传入图形和材质(网格物体对象)
  cube = new THREE.Mesh(geometry, material);
  // 4. 把物体加入到场景中
  scene.add(cube);
}

/**
 * 轨道控制器
 */
function controlsCreate() {
  //  创建轨道控制器
  controls = new OrbitControls(camera, renderer.domElement)
  // 1. 阻尼效果
  controls.enableDamping = true
  // 2. 开启自动旋转轨道控制器效果->带动摄像机一起旋转(摄像机顺时针水平旋转)
  // controls.autoRotate = true
  // 3. 垂直角度范围控制(0 上面,Math.PI 下面)
  // controls.maxPolarAngle = Math.PI
  // controls.minPolarAngle = 0
  // 水平角度范围控制
  // controls.maxAzimuthAngle = 1.5 * Math.PI
  // controls.minAzimuthAngle = 0.5 * Math.PI
  // 4. 摄像机移动范围控制
  // controls.minDistance = 2
  // controls.maxDistance = 10
}

function renderLoop() {
  //  在渲染循环中更新场景渲染
  renderer.render(scene, camera)
  // 手动 JS 代码更新过摄像机信息,必须调用轨道控制器 update 方法
  controls.update()
  // 根据当前计算机浏览器刷新帧率(默认 60 次/秒),不断递归调用此函数渲染最新的画面状态
  // 好处:当前页面切换到后台,暂停递归
  requestAnimationFrame(renderLoop)
}


/**
 * 坐标轴
 */
function createHelper() {
  // 1. 创建坐标轴对象,设置长度
  const axesHelper = new THREE.AxesHelper(5)
  // 2. 添加到场景中
  scene.add(axesHelper)
}

/**
 * 适配场景大小
 */
function renderResize() {
  // 1. 创建适配函数,监听浏览器 resize 事件
  window.addEventListener('resize', () => {
    // 2. 调整渲染器画布大小,摄像机宽高比和更新视椎体空间
    renderer.setSize(window.innerWidth, window.innerHeight)
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
  })
}

/**
 * 移动立方体
 */
function moveCube() {
  // 1. 位移 position 属性(Vector3 三维向量对象)
  cube.position.x = 5
  // cube.position.set(5, 5, 0)
  // 2. 旋转 rotation 属性(Euler 欧拉角弧度制角度对象)
  // 在轴的正方向看是逆时针旋转
  // cube.rotation.x = Math.PI / 4
  // 3. 缩放 scale 属性(Vector3 三维向量对象,中心原点不动,向 2 边拉伸/缩小)
  // cube.scale.z = 2
}

/**
 * 使用GUI工具
 */
function createGUI() {
  const gui = new dat.GUI()
  gui.add(document, 'title')

  // 1 控制立方体显示/隐藏(布尔->多选框)
  gui.add(cube, 'visible')
  // 2 轨道控制器回归初始角度(函数->按钮)
  gui.add(controls, 'reset')
  // 3 控制立方体颜色(找属性方式:文档->打印->百度)
  // 效果:立方体默认颜色和文字 <=> 显示在工具标签上
  const colorObj = {
    'col': `#${cube.material.color.getHexString()}`
  }
  gui.addColor(colorObj, 'col').onChange(val => {
    // val: #ff00ff 十六进制的颜色字符串
    cube.material.color = new THREE.Color(val)
  })
  // 4 创建分组-影响立方体位置
  const folder = gui.addFolder('位移')
  // 参数3:最小值范围,参数4:最大值范围,参数5:步长 (数字->进度条)
  folder.add(cube.position, 'x', 0, 5, 0.1)
  folder.add(cube.position, 'y', 0, 5, 0.1)
  folder.add(cube.position, 'z', 0, 5, 0.1)
  // 5 下拉菜单(关键:第三个参数为对象时->下拉菜单)
  // 对象中属性名->下拉菜单选项名
  // 初始值匹配后会影响下拉菜单默认选中哪一项
  gui.add({ type: '1' }, 'type', { '方案1': '1', '方案2': '2', '方案3': '3' }).onChange(val => {
    // val 方案对象的 '1','2'
    switch (val) {
      //方案1
      case '1':
        cube.position.set(0, 0, 0)
        break;
      //方案2
      case '2':
        cube.position.set(2, 2, 2)
        break;
      //方案3
      case '3':
        cube.position.set(2, 0, 0)
        break;
    }
  })

}


onMounted(() => {
  init() //初始化
  createCube()//创建立方体
  controlsCreate()//轨道控制器
  renderLoop()//循环渲染轨道控制器
  createHelper()//坐标轴
  renderResize()//适配场景大小
  moveCube()//移动立方体
  createGUI()//使用GUI工具
  renderer.render(scene, camera)
})
</script>

<style  scoped></style>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值