Three.js——learn03

28 篇文章 10 订阅

Three.js——learn03

Mesh物体对象基础操作

表示基于以三角形为polygon mesh(多边形网格)的物体的类。 同时也作为其他类的基类,例如SkinnedMesh
实际上Mesh被称为网格,真正到最后生成的物体时Object3D对象

创建

物体对象的创建需要两个参数:

  1. geometry:几何体类型
  2. material:材质
//创建几何体对象
const geometry = new THREE.BoxGeometry(1, 1, 1)
//设置基础材质(颜色:0x00ff00)
const material = new THREE.MeshBasicMaterial({ color: 0xffffff })
//创建物体对象(几何体+材质)
const cube = new THREE.Mesh(geometry, material)
//添加物体到材质中
scene.add(cube)

移动(position)

通过x,y,z属性设置移动
//x,y,z属性设置移动
cube.position.x = 3

在这里插入图片描述

通过set方法设置移动

set方法直接指定一个Vector3

//set方法设置移动
cube.position.set(0, 2, 1)

在这里插入图片描述

通过动画设置移动
const move = () => {
  cube.position.x += 0.01
  cube.position.y += 0.01
  if (cube.position.x >= 2) {
    cube.position.set(0, 0, 0)
  }

  requestAnimationFrame(move)
}

move()

在这里插入图片描述

完整代码
import * as THREE from 'three'
//导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

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

/**
 * 创建相机并设置相机参数
 * 参数:
 * 1. fov视野角度
 * 2.长宽比
 * 3.近端距离参数(近截面)最近能看到哪里
 * 4.远端距离参数(远截面)最远能看到哪里
 */
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
//设置相机位置
camera.position.set(0, 0, 5)
//将相机放置到场景中
scene.add(camera)
//创建渲染器
const renderer = new THREE.WebGLRenderer()
//设置渲染器渲染大小
renderer.setSize(window.innerWidth, window.innerHeight)
//添加渲染器到页面中
document.body.appendChild(renderer.domElement)
//创建几何体对象
const geometry = new THREE.BoxGeometry(1, 1, 1)
//设置基础材质(颜色:0x00ff00)
const material = new THREE.MeshBasicMaterial({ color: 0xffffff })
//创建物体对象(几何体+材质)
const cube = new THREE.Mesh(geometry, material)
//添加物体到材质中
scene.add(cube)
//创建轨道控制器
const control = new OrbitControls(camera, renderer.domElement)
//更新控制器
control.update()
//创建辅助器
const axesHelper = new THREE.AxesHelper(5)
//场景中添加辅助器,用于简单模拟3个坐标轴的对象
scene.add(axesHelper)
/**
 * 构建一个三维向量
 * x - 向量的x值,默认为0。
 * y - 向量的y值,默认为0。
 * z - 向量的z值,默认为0。
 */
const dirx = new THREE.Vector3(1, 0, 0)
const diry = new THREE.Vector3(0, 1, 0)
const dirz = new THREE.Vector3(0, 0, 1)
//将该向量转换为单位向量(unit vector), 也就是说,将该向量的方向设置为和原向量相同,但是其长度(length)为1。
dirx.normalize()
diry.normalize()
dirz.normalize()
const origin = new THREE.Vector3(0, 0, 0)
const length = 3
const hex = 0xffffff
/**
 * 构建箭头
 * dir -- 基于箭头原点的方向. 必须为单位向量.
 * origin -- 箭头的原点.
 * length -- 箭头的长度. 默认为 1.
 * hex -- 定义的16进制颜色值. 默认为 0xffff00.
 * headLength -- 箭头头部(锥体)的长度. 默认为箭头长度的0.2倍(0.2 * length).
 * headWidth -- The width of the head of the arrow. Default is 0.2 * headLength.
 */
const arrowHelperX = new THREE.ArrowHelper(dirx, origin, length, hex)
const arrowHelperY = new THREE.ArrowHelper(diry, origin, length, hex)
const arrowHelperZ = new THREE.ArrowHelper(dirz, origin, length, hex)

//我们可以给三个轴线添加箭头
//添加到场景中
scene.add(arrowHelperX)
scene.add(arrowHelperY)
scene.add(arrowHelperZ)
//创建摄像机视锥辅助器
const helper = new THREE.CameraHelper(camera)
scene.add(helper)
const size = 10
const divisions = 10

const gridHelper = new THREE.GridHelper(size, divisions)
scene.add(gridHelper)
//给物体添加动画
const an = () => {
  //requestAnimationFrame有很多的优点。最重要的一点或许就是当用户切换到其它的标签页时,它会暂停,因此不会浪费用户宝贵的处理器资源,也不会损耗电池的使用寿命
  requestAnimationFrame(an)
  control.update()
  //开始渲染
  renderer.render(scene, camera)
}
an()
// //x,y,z属性设置移动
// cube.position.x = 3
// //set方法设置移动
// cube.position.set(0, 2, 1)

const move = () => {
  cube.position.x += 0.01
  cube.position.y += 0.01
  if (cube.position.x >= 2) {
    cube.position.set(0, 0, 0)
  }

  requestAnimationFrame(move)
}

move()

旋转(rotation)

旋转使用是Eular欧拉角,也可以设置x,y,z当然也能用set方法直接设置

cube.rotation.x = 45
//设置Π/4 = 45°,Π/2 = 90°,0
cube.rotation.set(Math.PI / 4, Math.PI / 2, 0)

在这里插入图片描述

缩放(scale)

缩放其实也是使用Vector3做的所以和移动一样可以通过x,y,z属性调整,也可以使用set直接设置

cube.scale.x = 0.5
cube.scale.set(0.8, 0.6, 1.2)

在这里插入图片描述

通过使用Clock跟踪处理动画

该对象用于跟踪时间。如果performance.now可用,则 Clock 对象通过该方法实现,否则回落到使用略欠精准的Date.now来实现

核心代码

//创建Clock时钟对象
const clock = new THREE.Clock()

const move = () => {
  //动画中通过getElapsedTime获取运行总时长
  let t = clock.getElapsedTime()
  //获取两次运行的间隔时间
  let splitTime = clock.getDelta()

  console.log('总时长:' + t)
  console.log('间隔时间:' + splitTime)

  requestAnimationFrame(move)
}

注意点

如上的方式获取的间隔时间为0
我们看文档对于他们的解释:

  • oldTime:存储时钟最后一次调用 start, .getElapsedTime() 或 .getDelta() 方法的时间。默认值是 0
  • getDelta ()获取自 .oldTime 设置后到当前的秒数。 同时将 .oldTime 设置为当前时间

从这里我们可以知道在使用getElapsedTime的时候已经记录了oldTime,下一行getDelta获取的是oldTime到当前调用的秒数,自然很短很短约等于0,所以会导致输出为0

GSAP

tweenMax 是高性能 JavaScript 动画框架

安装

npm install gsap

导入

//导入GSAP
import gsap from 'gsap'

简单使用

参数:

  1. 动画对象
  2. 动画参数
    • 动画效果如x表示x轴
    • duration:动画持续时间
    • ease:动画速率,可选值:(none,power1,power2,power3,power4,back,elastic,bounce,rough,slow,steps,circ,expo,sine,Custom)
      写法:“power1.in/inOut/out”
    • repeat:重复次数 -1表示一直循环
    • delay:延迟时间
    • yoyo:是否往返 true/false
    • onStart:开始回调
    • onRepeat:重复回调
    • onUpdate:更新回调
    • onComplete:完成回调
//设置动画( use gsap)
/**
 * 参数:
 * 1.动画对象
 * 2.动画参数
 *  - 动画效果如x表示x轴
 *  - duration:动画持续时间
 *  - ease:动画速率,可选值:(none,power1,power2,power3,power4,back,elastic,bounce,rough,slow,steps,circ,expo,sine,Custom)
 *    写法:"power1.in/inOut/out"
 *  - repeat:重复次数 -1表示一直循环
 *  - yoyo:是否往返 true/false
 *  - delay:延迟时间
 *  - onStart:开始回调
 *  - onRepeat:重复回调
 *  - onUpdate:更新回调
 *  - onComplete:完成回调
 */
gsap.to(cube.position, {
  x: 2,
  duration: 3,
  ease: 'power1.inOut',
  repeat: 3,
  onStart: () => {
    console.log('start')
  },
  onRepeat: () => {
    console.log('repeat')
  },
  onUpdate: () => {
    console.log('update')
  },
  onComplete: () => {
    console.log('complete')
  }
})

效果

在这里插入图片描述
在这里插入图片描述

控制动画的开始或结束

let gsapAn = gsap.to(cube.position, {
  x: 2,
  duration: 3,
  ease: 'power1.inOut',
  repeat: 3,
  yoyo: true,
  onStart: () => {
    console.log('start')
  },
  onRepeat: () => {
    console.log('repeat')
  },
  onUpdate: () => {
    console.log('update')
  },
  onComplete: () => {
    console.log('complete')
  }
})

//添加点击事件
window.addEventListener('click', () => {
  //pause:暂停
  //resume:恢复运动
  gsapAn.isActive() ? gsapAn.pause() : gsapAn.resume()
})

视图更新


window.addEventListener('resize', () => {
  //更新摄像头
  camera.aspect = window.innerWidth / window.innerHeight
  //更新投影矩阵
  camera.updateProjectionMatrix()
  //更新渲染器
  renderer.setSize(window.innerWidth,window.innerHeight)
  //更新像素比例
  renderer.setPixelRatio(window.devicePixelRatio())
})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值