Three 之 Animation 体验一
Animation 体验一
动画效果

其中涉及到 skeletion、clipAction、GUI
Skeletion
在建模软件中可导出 skeletion,这里安利一个可以创建动画的网站 https://www.mixamo.com/ ,以上模型均从该网站创建下载,注意,在下载时需要勾选 Skeletion

加载好模型后,就可以使用 helper 方法创建骨架,并将其添加至场景中
// 加载骨架,obj 为加载好后的模型
skeletion = new THREE.SkeletonHelper(obj);
// 设置可见性为 false
skeletion.visible = false;
// 添加到场景中
scene.add(skeletion);
clipAction
使用 API 最好的方法是去官网搜索
首先获取到跳舞动作的 action
clipAction = mixer.clipAction(obj.animations[0]);
点击暂停播放按钮进行动作切换,动作切换的 api 十分简单
// 如果动作正在进行就停止,否指播放
if (clipAction.isRunning()) {
clipAction.stop();
} else {
clipAction.play();
}
GUI
import { GUI } from "three/examples/jsm/libs/dat.gui.module";
该 UI 库能够绑定 js 中的变量和 UI 上显示的变量
使用方法如下
- 创建相应面板
const panel = new GUI({ width: 200 });
// domElement 可以获取到 dom 元素
panel.domElement.style.marginTop = "10px";
// 分别创建两个父文件夹并打开
const folder1 = panel.addFolder("visibility");
const folder2 = panel.addFolder("pause/continue");
folder1.open();
folder2.open();

- 绑定对象中的数据
setting = {
"show model": true,
"show skeleton": false,
"pause/continue": pauseContinue,
};
// folder.add() 第一个参数为对象,第二个参数为属性名,第三个参数代表发生变化时触发的回调函数
// 使用 setting 中的 show model 属性,由于值时 Boolean 类型,因此回调函数的参数也是相同类型
folder1.add(setting, "show model").onChange((visible) => {
model.visible = visible;
});
// 直接绑定 skeletion 对象上的 visible 属性,界面上显示的就是 skeletion 对象上真实的 visible
folder1.add(skeletion, "visible").onChange((visible) => {
skeletion.visible = visible;
});
// 相当于添加了一个点击按钮,触发 pauseContinue 方法
folder2.add(setting, "pause/continue");
function pauseContinue() {
if (clipAction.isRunning()) {
clipAction.stop();
} else {
clipAction.play();
}
}
源代码
import React, { useEffect, useRef } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
import { GUI } from "three/examples/jsm/libs/dat.gui.module";
import Stats from "three/examples/jsm/libs/stats.module";
export function List2() {
const content = useRef();
// 场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xa0a0a0);
scene.fog = new THREE.Fog(0xa0a0a0, 10, 500);
const pointLight = new THREE.PointLight(0xffffff, 0.6);
pointLight.position.set(150, 150, 150);
scene.add(pointLight);
scene.add(new THREE.AmbientLight(0xffffff, 2));
// 骨架
let skeletion, model, clipAction;
let setting;
// 添加平面
const mesh = new THREE.Mesh(
new THREE.PlaneGeometry(1000, 1000),
new THREE.MeshPhongMaterial({ color: 0x999999, depthWrite: false })
);
mesh.rotation.x = -Math.PI / 2;
mesh.receiveShadow = true;
scene.add(mesh);
const clock = new THREE.Clock();
let mixer;
useEffect(() => {
const canvas = content.current;
const renderer = new THREE.WebGLRenderer({ antialias: true, canvas });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(canvas.clientWidth, canvas.clientHeight);
const stats = new Stats();
canvas.appendChild(stats.dom);
const camera = new THREE.PerspectiveCamera(
40,
canvas.clientWidth / canvas.clientHeight,
1,
1000
);
camera.position.set(200, 200, 200);
const controls = new OrbitControls(camera, canvas);
controls.update();
const loader = new FBXLoader();
loader.load("/RumbaDancing.fbx", (obj) => {
scene.add(obj);
model = obj;
skeletion = new THREE.SkeletonHelper(obj);
skeletion.visible = false;
scene.add(skeletion);
mixer = new THREE.AnimationMixer(obj);
clipAction = mixer.clipAction(obj.animations[0]);
clipAction.play();
createPanel();
});
animate();
function createPanel() {
const panel = new GUI({ width: 200 });
panel.domElement.style.marginTop = "10px";
const folder1 = panel.addFolder("visibility");
const folder2 = panel.addFolder("pause/continue");
folder1.open();
folder2.open();
setting = {
"show model": true,
"show skeleton": false,
"pause/continue": pauseContinue,
};
folder1.add(setting, "show model").onChange((visible) => {
model.visible = visible;
});
folder1.add(skeletion, "visible").onChange((visible) => {
skeletion.visible = visible;
});
folder2.add(setting, "pause/continue");
function pauseContinue() {
if (clipAction.isRunning()) {
clipAction.stop();
} else {
clipAction.play();
}
}
}
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
if (mixer) mixer.update(delta);
controls.update();
stats.update();
renderer.render(scene, camera);
}
});
return <canvas ref={content} />;
}
Three 之 Animation 体验一的更多相关文章
- Angular 学习笔记 (动态组件 & Material Overlay & Dialog 分析)
更新: 2019-11-24 dialog vs router link refer : https://stackoverflow.com/questions/51821766/angular-m ...
- css Animation初体验
目前有越来越多的网站都使用animation,无论他们是用GIF,SVG,WebGL,视频背景或者其他形式展示.适当地使用动画会让网站更生动,互动性更好,为用户增加一个额外的反馈和体验层. 在本教程中 ...
- 谈谈iOS Animation
零.前言 这里没有太多的代码细节,只是探索iOS动画的基本概念,以及其抽象模型,数学基础等.我们学习一个知识的时候一般有两个部分,抽象部分和形象部分,抽象好比语言的语法,是规则,形象好比具体的句子,可 ...
- 浅谈Android样式开发之View Animation (视图动画)
引言 一个用户体验良好的App肯定少不了动画效果.Android为我们提供了2种动画框架,分别是视图动画(View Animation)和属性动画(Property Animation).视图动画比较 ...
- 今日提及之动画animation
今天没有说什么内容,只是对HTML5的细节补充,如HTML结构的可以省略到最大的地步 <!DOCTYPE html><meta charset="UTF-8"&g ...
- Material Design Animation
Material Design Animation Authentic motion 真实的运动 运动以一种优美流动的形式描述了空间关系,功能和目的. Mass and weight: 质量和重量 在 ...
- css3 animation实现风车转动
项目中经常有用到动画效果,比如Loading.风车转动等等.最简单的办法是使用gif,但是gif在半透明背景下有白边,体验不友好,好在现在可以使用css3的anmiation来实现动画效果,极大的提升 ...
- vue初体验:实现一个增删查改成绩单
前端变化层出不穷,去年NG火一片,今年react,vue火一片,ng硬着头皮看了几套教程,总被其中的概念绕晕,react是faceback出品,正在不断学习中,同时抽时间了解了vue,查看了vue官方 ...
- core animation (转)
iOS Core Animation 简明系列教程 看到无数的CA教程,都非常的难懂,各种事务各种图层关系看的人头大.自己就想用通俗的语言翻译给大家听,尽可能准确表达,如果哪里有问题,请您指出我会尽快 ...
随机推荐
- 轻松入门vue系列
一.vue基础语法 二.vue组件化开发 三.Vue前后端交互 四.vue前端路由 喜欢不要忘了点个赞哟
- gradle依赖冲突
# 如何定位依赖冲突? 了解如何定位依赖冲突问题之前,我们先手动制造一个依赖冲突. 我们在 build.gradle 引入两个依赖库: compile 'org.hibernate:hibernate ...
- 利用Python快速绘制海报级别地图
1 简介 基于Python中诸如matplotlib等功能丰富.自由度极高的绘图库,我们可以完成各种极富艺术感的可视化作品,关于这一点我在系列文章在模仿中精进数据可视化中已经带大家学习过很多案例了. ...
- Qt编译工程提示qt creator no rule to make target opencv2/core/hal/interface.h need by debug解决方法
总是提示 qt creator no rule to make target opencv2/core/hal/interface.h need by debug解决方法: 也算是花了整整两个小时踩坑 ...
- k8s 存活探针(健康检查)
重启策略 (RestartPolicy ) Always:当容器终止退出后,总是重启容器,默认策略. OnFailure:当容器异常退出(退出状态码非0)时,才重启容器. Never:当容器终止退出, ...
- hibernate01
什么是hibernate ORM框架/持久层框架 jdbc的一个框架 object reference mapping 通过管理对象来改变数据库中的数据 通过管理对象来操作数据库 hibernate的 ...
- Flask(6)- debug 模式
使用 Flask 开发过程中存在两个常见的问题 当 Flask 程序出错时,没有提示错误的详细信息 修改 Flask 源代码后需要重启 Flask 程序 这两个问题非常的影响开发效率,因此 Flask ...
- .net中使用JSON
在.NET使用JSON作为数据交换格式 ASP.NET中JSON的序列化和反序列化 三种方式: 使用System.Web.Script.Serialization.JavaScriptSerializ ...
- 掌握基于AOP事务管理
一.手动管理和半自动工厂模式 二.AOP事务管理 1.表达式中,第一个※是返回值所有类型,service包下一个点意思是service包下的类,两个点意思是service包下的类和其子包下的类也包含, ...
- 测试平台系列(55) 引入AceEditor(代码编辑器)
大家好,我是米洛,求三连!求关注测试开发坑货! 回顾 我们上一节已经写好了左侧数据表目录,今天继续完成sql编辑器的部分. 调研组件 monaco 因为我们的项目用的是React,市面上很多编辑器都是 ...