学习threejs,对模型多个动画切换展示

👨‍⚕️ 主页: gis分享者

👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!

👨‍⚕️ 收录于专栏:threejs gis工程师


文章目录


一、🍀前言

本文详细介绍如何基于threejs在三维场景中对模型多个动画切换展示,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️THREE.AnimationMixer 动画混合器

THREE.AnimationMixer动画混合器是用于场景中特定对象的动画的播放器。当场景中的多个对象独立动画时,每个对象都可以使用同一个动画混合器。
创建方法:

AnimationMixer( rootObject : Object3D )

rootObject 是 混合器播放的动画所属的对象
属性:

time:Number 全局的混合器时间(单位秒; 混合器创建的时刻记作0时刻)。

timeScale:全局时间(mixer time)的比例因子。

说明: 将混合器的时间比例设为0, 稍后再设置为1,可以暂停/取消暂停由该混合器控制的所有动作。
方法:

clipAction(clip : AnimationClip, optionalRoot : Object3D):AnimationAction 返回所传入的剪辑参数的AnimationAction, 根对象参数可选,默认值为混合器的默认根对象。第一个参数可以是动画剪辑(AnimationClip)对象或者动画剪辑的名称。

如果不存在符合传入的剪辑和根对象这两个参数的动作, 该方法将会创建一个。传入相同的参数多次调用将会返回同一个剪辑实例。

existingAction (clip : AnimationClip, optionalRoot : Object3D) : AnimationAction 返回传入剪辑的已有AnimationAction, 根对象参数可选,默认值为混合器的默认根对象。

第一个参数可以是动画剪辑(AnimationClip)对象或者动画剪辑的名称。

update (deltaTimeInSeconds : Number) : AnimationMixer 推进混合器时间并更新动画。

deltaTimeInSeconds 参数表示当前帧与前一帧之间的时间差(以秒为单位)。

二、🍀对模型多个动画切换展示

1. ☘️实现思路

  • 1、初始化renderer渲染器
  • 2、初始化Scene三维场景
  • 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt。
  • 4、初始化THREE.AmbientLight环境光源,scene场景加入环境光源,初始化THREE.PointLight点光源,设置点光源位置,设置点光源投影,scene添加点光源。
  • 5、加载几何模型:创建THREE.AxesHelper坐标辅助工具,创建THREE.PlaneBufferGeometry平面几何体、THREE.GridHelper地板割线,scene场景中加入创建的平面几何体和地板割线。创建gui控件datGui。通过THREE.FBXLoader类加载 'Naruto.fbx' 模型文件mesh,在加载模型的回调函数中,定义mesh动画,datGui加入动画控制。具体实现参考代码样例。
  • 6、加入controls控制,加入stats监控器,监控帧数信息。

2. ☘️代码样例

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>learn50(对模型多个动画切换展示)</title>
    <script src="lib/threejs/127/three.js-master/build/three.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/controls/OrbitControls.js"></script>
    <!--<script src="lib/js/inflate.min.js"></script>-->
    <script src="lib/threejs/127/three.js-master/examples/js/loaders/FBXLoader.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/libs/fflate.min.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/libs/stats.min.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/libs/dat.gui.min.js"></script>
    <script src="lib/js/Detector.js"></script>
</head>
<style type="text/css">
    html, body {
        margin: 0;
        height: 100%;
    }

    canvas {
        display: block;
    }

</style>
<body onload="draw()">
</body>
<script>
  var renderer
  var initRender = () => {
    renderer = new THREE.WebGLRenderer({antialias: true})
    renderer.setPixelRatio(window.devicePixelRatio)
    renderer.setClearColor(0xeeeeee)
    renderer.setSize(window.innerWidth, window.innerHeight)
    renderer.shadowMap.enabled = true
    document.body.appendChild(renderer.domElement)
  }
  var scene
  var initScene = () => {
    scene = new THREE.Scene()
    scene.backgroundColor = new THREE.Color(0xa0a0a0)
    scene.fog = new THREE.Fog(0xa0a0a0, 200, 1000)
  }
  var camera
  var initCamera = () => {
    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000)
    camera.position.set(100, 200, 300)
  }
  var light
  var initLight = () => {
    scene.add(new THREE.AmbientLight(0x444444))

    light = new THREE.DirectionalLight(0xffffff)
    light.position.set(0, 200, 100)
    light.castShadow = true
    light.shadow.camera.top = 180
    light.shadow.camera.bottom = -100
    light.shadow.camera.left = -120
    light.shadow.camera.right = 120
    scene.add(light)
  }
  var gui, datGui, meshHelper, mixer
  var initGui = () => {
    gui = {
      helper: true
    }
    datGui = new dat.GUI()
    datGui.add(gui, 'helper').onChange(e => {
      meshHelper.visible = e
    })
  }
  var initModel = () => {
    var helper = new THREE.AxesHelper(50)
    scene.add(helper)
    var mesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(2000, 2000), new THREE.MeshPhongMaterial({
      color: 0xffffff,
      depthWrite: false
    }))
    mesh.receiveShadow = true
    mesh.rotation.x = -0.5 * Math.PI
    scene.add(mesh)

    // var planeGeometry = new THREE.PlaneBufferGeometry(2000, 2000)
    // var planeMatarial = new THREE.MeshPhongMaterial({
    //   color: 0xffffff,
    //   depthWrite: false
    // })
    // var plane = new THREE.Mesh(planeGeometry, planeMatarial)
    // plane.rotation.x = -0.5 * Math.PI
    // plane.position.y = -0
    // plane.receiveShadow = true
    // scene.add(plane)

    // 添加地板割线
    var grid = new THREE.GridHelper(2000, 20, 0x000000, 0x000000)
    grid.material.opacity = 0.2
    grid.material.transparent = true
    scene.add(grid)

    var loader = new THREE.FBXLoader()
    loader.load('data/model/NarutoFbx/Naruto.fbx', mesh => {
      meshHelper = new THREE.SkeletonHelper(mesh)
      scene.add(meshHelper)
      mesh.traverse(child => {
        if (child.isMesh) {
          child.castShadow = true
          child.receiveShadow = true
        }
      })
      mixer = mesh.mixer = new THREE.AnimationMixer(mesh)
      var actions = []
      var animations = datGui.addFolder('animations')
      var createAction = (i) => {
        actions[i] = mixer.clipAction(mesh.animations[i])
        gui['action' + i] = () => {
          for (var j = 0; j < actions.length; j++) {
            if (j === i) {
              actions[j].play()
            } else {
              actions[j].stop()
            }
          }
        }
        animations.add(gui, 'action' + i)
      }
      for (var i = 0; i < mesh.animations.length; i++) {
        createAction(i)
      }
      gui.stop = () => {
        for (var i = 0; i < actions.length; i++) {
          actions[i].stop()
        }
      }
      datGui.add(gui, 'stop')
      mesh.position.y += 100
      scene.add(mesh)
    })
  }
  var stats
  var initStats = () => {
    stats = new Stats()
    document.body.appendChild(stats.dom)
  }
  var controls
  var initControls = () => {
    controls = new THREE.OrbitControls(camera, renderer.domElement)
    controls.enableDamping = true
  }
  var clock = new THREE.Clock()
  var render = () => {
    var time = clock.getDelta()
    if (mixer) {
      mixer.update(time)
    }
    controls.update()
  }
  var onWindowResize = () => {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    render.setSize(window.innerWidth, window.innerHeight)
  }
  var animate = () => {
    render()
    stats.update()
    renderer.render(scene, camera)
    requestAnimationFrame(animate)
  }
  var draw = () => {
    initRender()
    initScene()
    initCamera()
    initGui()
    initLight()
    initModel()
    initStats()
    initControls()

    animate()

    window.onresize = onWindowResize
  }
</script>
</html>

效果如下:

相关推荐
gis分享者3 小时前
学习threejs,导入FBX格式骨骼绑定模型
threejs·骨骼动画·fbx
allenjiao1 天前
webgl threejs 云渲染(服务器渲染、后端渲染)解决方案
webgl·云渲染·threejs·服务器渲染·后端渲染·云流化·三维云渲染
gis分享者6 天前
学习threejs,使用TWEEN插件实现动画
threejs·tween·补间动画
优雅永不过时·7 天前
Three.js 原生 实现 react-three-fiber drei 的 磨砂反射的效果
前端·javascript·react.js·webgl·threejs·three
gis分享者8 天前
学习threejs,使用第一视角控制器FirstPersonControls控制相机
threejs·第一人称视角
gis分享者9 天前
学习threejs,使用导入的模型生成粒子
threejs·模型粒子化
gis分享者16 天前
学习threejs,将多个网格合并成一个网格
threejs·网格合并
优雅永不过时·17 天前
three.js 实现 css2d css3d效果 将 二维Dom 和 三维场景结合
前端·javascript·css3·threejs·three
优雅永不过时·18 天前
使用three.js 实现 自定义绘制平面的效果
前端·javascript·平面·github·threejs·着色器