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教程,都非常的难懂,各种事务各种图层关系看的人头大.自己就想用通俗的语言翻译给大家听,尽可能准确表达,如果哪里有问题,请您指出我会尽快 ...
随机推荐
- Java学习之 多态 Polymorphism
转自:http://www.cnblogs.com/mengdd/archive/2012/12/25/2832288.html 多态的概念 多态==晚绑定. 不要把函数重载理解为多态. 因为多态是一 ...
- Visual Studio 2022 预览版3 最新功能解说
我们很高兴地宣布Visual Studio 2022 的第三个预览版问世啦!预览版3 提供了更多关于个人和团队生产力.现代开发和持续创新等主题的新功能.在本文中,我们将重点介绍Visual Studi ...
- MVVM框架三巨头之Vue的前世今生。
前端有三宝,Angular,Vue,React.目前这三大主流JS框架已经成三分之势.其中的React框架是由脸书开发的,今天我们就来聊一聊VueJS的前世今生. 前世 在2013年的js开发者大会上 ...
- 剑指offer 计划1(栈与队列)---java
1.1.题目1 剑指 Offer 09. 用两个栈实现队列 1.2.解法 解法如题目所说.定义两个栈.这里假设第一个栈为a,第二个栈为b. 实现两个函数增加尾和删除头. 增加即直接push入第一个栈. ...
- android activity pass data to accessibilityservice 数据传递
不同类型的 service 传递数据的方式不同,accessibilityservice 运行在独立进程,且被系统接管,比较特别 在 AccessibilityService 的 onCreate 内 ...
- 口护万亿市场杀出的实力派 Oclean欧可林
撰文 |懂懂 编辑 | 秦言 来源:懂懂笔记 在"青年必去的电影节"上,发现了一个跟他们打成一片的智能护齿"新星". 25日,备受关注的第15届FIRST青年电 ...
- js-监听网络状态
<script> // 监听网络状态 window.addEventListener("online", function(){ alert("网络连接了&q ...
- 基于python2.7 Tkinter 做一个小工具
1.源码:先写一个界面出来,放需要放入的点击事件的函数 # -*- coding:utf-8 -*- import Tkinter from Tkinter import * import Excle ...
- C#中List是链表吗?为什么可以通过下标访问
使用C#的同学对List应该并不陌生,我们不需要初始化它的大小,并且可以方便的使用Add和Remove方法执行添加和删除操作,但却可以使用下标来访问它的数据,它是我们常说的链表吗? List& ...
- leetcode8 字符串转换为整数
最笨的办法实现 一步步判断 /** * @param {string} s * @return {number} */ var myAtoi = function(s) { s = s.trim() ...