three.js基础案例day04——动画animation

今天主要学习的有关动画相关的技术,使用一个小球在场景中画一个爱心,同时颜色也会改变,也可以修改小球缩放或者旋转(这个案例中没有体现)。具体效果如下:

首先也是需要创建场景,相机、渲染器、控制器(这个案例中可有可无),不懂的可以查看day01的那篇。

这个场景添加了背景颜色和三维坐标,代码如下

scene.background = new THREE.Color(0x888888)
// 三维坐标
const axesHelper = new THREE.AxesHelper(8)
scene.add(axesHelper)

相机的位置在Z轴上,所以上面的视频中只能看到X轴和Y轴

 1.设置灯光

  scene.add(new THREE.AmbientLight(0xffffff, 0.2))
  const dirLight = new THREE.DirectionalLight(0xfffff, 1)
  dirLight.position.set(2, 2, 2)
  scene.add(dirLight)

2.创建小球

  const geometry = new THREE.SphereGeometry(0.5, 32, 16)
  const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
  cube = new THREE.Mesh(geometry, material)
  scene.add(cube)

3.初始化动画轨道和动画剪辑

  // 位置
 const positionKF = new THREE.VectorKeyframeTrack(
    '.position',
    [0, 1, 2, 3, 4, 5, 6],
    [0, 0, 0, -4, 4, 0, -2, 6, 0, 0, 5, 0, 2, 6, 0, 4, 4, 0, 0, 0, 0],
  )
  
  // 颜色
  const colorKF = new THREE.ColorKeyframeTrack(
    '.material.color',
    [0, 1, 2, 3, 4, 5, 6],
    [1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0],
  )
  // 动画剪辑,是可复用的关键帧轨道集
  clip = new THREE.AnimationClip('Action', 6, [positionKF, colorKF])

4.启用动画, 不要忘记在animate函数中更新mixer

 // 动画混合器
  mixer = new THREE.AnimationMixer(cube)
  clipAction = mixer.clipAction(clip)
  clipAction.play()
function animate() {
  requestAnimationFrame(animate)
  // 获取帧时间,在最开始的时候有设置clock = new THREE.Clock()
  const delta = clock.getDelta()
  renderer.render(scene, camera)
   // 更新
  mixer.update(delta)
}

全部代码

<template>
  <div id="threeId" ref="elementRef"></div>
</template>

<script setup lang="ts">
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { ref, onMounted } from 'vue'
let width, height, scene, camera, renderer, controls
let cube
let clip, mixer, clipAction
const elementRef = ref(null)
let clock = new THREE.Clock()
onMounted(() => {
  const element = elementRef.value
  width = element.offsetWidth
  height = element.offsetHeight
  initScene()
  initCamera()
  initRender()
  initLight()
  initMesh()
  initAnimation()
  enableAnimation()
  initAxesHelper()
  initControls()
  animate()
})
function initScene() {
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0x888888)
}
function initCamera() {
  camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000)
  camera.position.z = 20
  scene.add(camera)
}
function initRender() {
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setPixelRatio(window.devicePixelRatio)
  renderer.setSize(width, height)
  elementRef.value.appendChild(renderer.domElement)
}
function initLight() {
  scene.add(new THREE.AmbientLight(0xffffff, 0.2))
  const dirLight = new THREE.DirectionalLight(0xfffff, 1)
  dirLight.position.set(2, 2, 2)
  scene.add(dirLight)
}
function initMesh() {
  const geometry = new THREE.SphereGeometry(0.5, 32, 16)
  const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
  cube = new THREE.Mesh(geometry, material)
  scene.add(cube)
}
function initAnimation() {
  // VectorKeyframeTrack 向量类型的关键帧轨道:参数:名称,时间数组,与时间数组中的时间点对应的值数组, 使用的插值类型
  // 位置
  const positionKF = new THREE.VectorKeyframeTrack(
    '.position',
    [0, 1, 2, 3, 4, 5, 6],
    [0, 0, 0, -4, 4, 0, -2, 6, 0, 0, 5, 0, 2, 6, 0, 4, 4, 0, 0, 0, 0],
  )
  // 颜色
  const colorKF = new THREE.ColorKeyframeTrack(
    '.material.color',
    [0, 1, 2, 3, 4, 5, 6],
    [1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0],
  )
  // 动画剪辑,是可复用的关键帧轨道集,他代表动画
  clip = new THREE.AnimationClip('Action', 6, [positionKF, colorKF])
  clip.tracks.forEach((track) => {
    track.timeScale = 0.5 // 设置动画播放速度,这里设置为原来的一半
  })
}
function enableAnimation() {
  // 动画混合器
  mixer = new THREE.AnimationMixer(cube)
  clipAction = mixer.clipAction(clip)
  clipAction.play()
}

function initAxesHelper() {
  const axesHelper = new THREE.AxesHelper(8)
  scene.add(axesHelper)
}
function initControls() {
  controls = new OrbitControls(camera, renderer.domElement)
}
function animate() {
  requestAnimationFrame(animate)
  const delta = clock.getDelta()
  renderer.render(scene, camera)
  mixer.update(delta)
}

</script>

<style scoped>
#threeId {
  width: 100%;
  height: 100%;
}
</style>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值