Threejs里执行对象的多个动画

承接上文,本文讲述如何在Threejs里播放对象的多个动画,这也是研究了很久才解决的…


一 导出模型

在Blender里按照File->Export,选择glTF2.0
image.png

然后在弹框的右上角选择导出为glTF Embedded (.gltf)
image.png

这样就把模型导出来了,该模型里包含了2个动画。


二 Threejs样例

Threejs的安装本文不会描述,可以参考官方文档,比较简单。

main.js内容如下,

import * as THREE from 'three';import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { GUI } from 'lil-gui'const scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff );
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1e-5, 1e10 );
camera.position.set(0, 15, 30);var ambient = new THREE.AmbientLight(0xffffff);
scene.add(ambient);const renderer = new THREE.WebGLRenderer({ antialias: true, logarithmicDepthBuffer: true });
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setPixelRatio(window.devicePixelRatio);
renderer.outputColorSpace = THREE.SRGBColorSpace;document.body.appendChild( renderer.domElement );const loader = new GLTFLoader();const dracoLoader = new DRACOLoader();
loader.setDRACOLoader(dracoLoader);let modelReady = false;
let gltfscene;
let horsevisible = false;
let mixer;let actions;loader.load('/models/33.gltf',function (gltf) {gltfscene = gltf.scene;scene.add(gltfscene);console.log(gltf.animations);mixer = new THREE.AnimationMixer(gltf.scene);let Action1 = mixer.clipAction( gltf.animations[0] );let Action2 = mixer.clipAction( gltf.animations[1] );actions = [Action1, Action2];modelReady = true;},function(xhr) {console.log((xhr.loaded / xhr.total * 100) + '% loaded');},function (error) {console.log('An error happened.');}
)const obj = {myFunction: function () {if (horsevisible == false){actions[0].clampWhenFinished = true;actions[0].setLoop(THREE.LoopOnce);actions[0].play();actions[1].stop(); // 非常关键}else{actions[1].clampWhenFinished = true;actions[1].setLoop(THREE.LoopOnce);actions[1].play();actions[0].stop(); // 非常关键}horsevisible = !horsevisible;}
}
const gui = new GUI()
gui.add(obj, 'myFunction'); // 按钮const grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
grid.material.opacity = 0.3;
grid.material.transparent = true;
scene.add( grid );const controls = new OrbitControls(camera, renderer.domElement);
controls.update();const clock = new THREE.Clock();function animate() {requestAnimationFrame( animate );if (modelReady){mixer.update(clock.getDelta());}controls.update();renderer.render( scene, camera );
}animate();

然后运行npx vite来启动server,打印如下,
image.png

然后在浏览器里打开这个地址,显示如下,
image.png
然后点击myFunction按钮,可以看到这个立方体会移动到右边,再次点击myFunction按钮,立方体又会移到中间。

代码里关键点是myFunction对应的回调函数,因为动画的默认参数会重复执行这个动画,这里把clampWhenFinished设置为true,并把loop设置为THREE.LoopOnce,然后调用play(),这样可以保证这个动画只执行一次。

最后一定要执行一下另外一个动画的stop()函数,这样可以保证另外动画的正确执行,否则会出现位置不正确的情况。


三 总结

本文讲述了如何在Threejs里播放同一对象的多个动画。关键点有2个,

  1. 设置动画只执行一次
  2. 调用下一个动画的stop()函数来保证下一个动画可以正确执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/91426.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker部署nginx,部署springboot项目,并实现访问

一、先部署springboot项目 1、安装docker: yum install docker -y 2、启动docker: service docker start 重启: service docker restart 3、查看版本: docker -v 4、使设置docker.service生效(路径:…

qt第二天

#include "widget.h" #include "ui_widget.h" #include "QDebug" Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);this->resize(QSize(800,600)); //使用匿名对象,调用重…

HarmonyOS开发:超详细了解项目的工程结构

前言 系列文章目录: HarmonyOS开发第一步,熟知开发工具DevEco Studio 当我们熟练的掌握了DevEco Studio之后,就可以创建项目进行练习了,和市场上大多数IDE一样,DevEco Studio也给我们提供了很多的实例模板&#xff0c…

ElasticSearch-集成ik分词器

本文已收录于专栏 《中间件合集》 目录 背景介绍版本选择优势说明集成过程1.下载安装包2.解压安装包3.重启ElasticSearch服务3.1通过ps -ef | grep elastic查看正在启动的es进程号3.2使用kill -9 xxx 杀死进程3.3使用 ./elasticsearch 启动es服务 分词测试细粒度分词方式分词请…

【面试题】UDP和TCP有啥区别?

UDP UDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就…

基于stm32的烟雾浓度检测报警proteus仿真设计(仿真+程序+讲解)

基于STM32的烟雾浓度检测报警仿真设计(仿真程序讲解) 1.主要功能2.仿真3. 程序4. 资料清单&下载链接 基于STM32的烟雾浓度检测报警仿真设计(仿真程序讲解) 仿真图proteus 8.9 程序编译器:keil 5 编程语言:C语言 设计编号&a…

使用TPDSS连接GaussDB数据库

TPDSS是GaussDB官方提供的数据库连接工具,可以在TPDSS查看GaussDB的建库建表语句,于GaussDB使用兼容性比较好,由于TPDSS查找比较麻烦,下面给出了下载链接地址: 链接:https://pan.baidu.com/s/1Lqcu3KriE47…

打破数据孤岛,实现文档数据互通

随着数字经济加速发展,企业数字化转型正向更深层次推进。非结构化数据量也正在飞速增长,这些数据以文档、图片、音频等形式散落在组织内部,这给数据的整理和统一利用增加了难度。由于部门、应用、框架、多云环境等原因形成非结构化数据孤岛。…

JavaWeb 速通Ajax

目录 一、Ajax快速入门 1.基本介绍 : 2.使用原理 : 二、Ajax经典入门案例 1.需求 : 2.前端页面实现 : 3. 处理HTTP请求的servlet实现 4.引入jar包及druid配置文件、工具类 : 5.Domain层实现 : 6.DAO层实现 : 7.Service层实现 : 8.运行测试 : 三、JQuery操作Ajax 1 …

CI/CD 持续集成 持续交付

CI(Continuous integration)持续集成 参考:https://www.jianshu.com/p/2132949ff84a 持续集成是指多名开发者在开发不同功能代码的过程当中,可以频繁的将代码行合并到一起并切相互不影响工作。 持续集成的目的,是让…

网络流量监控-sniffnet

{alert type“info”} 今天来分享一个监控流量的应用sniffnet。 github项目地址:https://github.com/GyulyVGC/sniffnet {/alert} 可以在github的readme上看到这个程序有的特性: 为什么要介绍它呢:主要是多线程、跨平台、可靠、操作简单 我…

进程Start

Linux中的命令解释器和Windows的程序管理器explorer.exe一样地位,都是在用户态下运行的进程 共享变量发生不同进程间的指令交错,就可能会数据出错 进程只作为除CPU之外系统资源的分配单位 CPU的分配单位是线程 每个进程都有自己的独立用户空间 内核空间是OS内核的…