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 最好的方法是去官网搜索

AnimationAction – three.js docs (threejs.org)

首先获取到跳舞动作的 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 上显示的变量

使用方法如下

  1. 创建相应面板
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();

  1. 绑定对象中的数据
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 体验一的更多相关文章

  1. Angular 学习笔记 (动态组件 & Material Overlay & Dialog 分析)

    更新: 2019-11-24  dialog vs router link refer : https://stackoverflow.com/questions/51821766/angular-m ...

  2. css Animation初体验

    目前有越来越多的网站都使用animation,无论他们是用GIF,SVG,WebGL,视频背景或者其他形式展示.适当地使用动画会让网站更生动,互动性更好,为用户增加一个额外的反馈和体验层. 在本教程中 ...

  3. 谈谈iOS Animation

    零.前言 这里没有太多的代码细节,只是探索iOS动画的基本概念,以及其抽象模型,数学基础等.我们学习一个知识的时候一般有两个部分,抽象部分和形象部分,抽象好比语言的语法,是规则,形象好比具体的句子,可 ...

  4. 浅谈Android样式开发之View Animation (视图动画)

    引言 一个用户体验良好的App肯定少不了动画效果.Android为我们提供了2种动画框架,分别是视图动画(View Animation)和属性动画(Property Animation).视图动画比较 ...

  5. 今日提及之动画animation

    今天没有说什么内容,只是对HTML5的细节补充,如HTML结构的可以省略到最大的地步 <!DOCTYPE html><meta charset="UTF-8"&g ...

  6. Material Design Animation

    Material Design Animation Authentic motion 真实的运动 运动以一种优美流动的形式描述了空间关系,功能和目的. Mass and weight: 质量和重量 在 ...

  7. css3 animation实现风车转动

    项目中经常有用到动画效果,比如Loading.风车转动等等.最简单的办法是使用gif,但是gif在半透明背景下有白边,体验不友好,好在现在可以使用css3的anmiation来实现动画效果,极大的提升 ...

  8. vue初体验:实现一个增删查改成绩单

    前端变化层出不穷,去年NG火一片,今年react,vue火一片,ng硬着头皮看了几套教程,总被其中的概念绕晕,react是faceback出品,正在不断学习中,同时抽时间了解了vue,查看了vue官方 ...

  9. core animation (转)

    iOS Core Animation 简明系列教程 看到无数的CA教程,都非常的难懂,各种事务各种图层关系看的人头大.自己就想用通俗的语言翻译给大家听,尽可能准确表达,如果哪里有问题,请您指出我会尽快 ...

随机推荐

  1. 通过PEB的Ldr枚举进程内所有已加载的模块

    一.几个重要的数据结构,可以通过windbg的dt命令查看其详细信息 _PEB._PEB_LDR_DATA._LDR_DATA_TABLE_ENTRY 二.技术原理 1.通过fs:[30h]获取当前进 ...

  2. SpringCloud之网关zuul

    1.微服务网关介绍和使用场景 1)什么是网关 API Gateway,是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求.鉴权.监控.缓存.限流等功能 统一接入 智 ...

  3. BootStrap学习代码

    要为毕设做准备了! 哎,毕设前台得自己来,所以打算学学bootstrap,把学习的代码放到码云上面了,使用HbuilderX来写,界面友好,适合我这种前端小白- 第一天就感受到了写html快捷键的强大 ...

  4. 我对数据库事务的理解(MYSQL中)

    -- 设置数据库事务为手动的提交SET @@AUTOCOMMIT = 0;-- 查看是否被修改SELECT @@autocommit;-- 查看当前的编码格式SELECT @@character_se ...

  5. Playwright-python 教程

    安装 pip install playwright -i https://mirrors.aliyun.com/pypi/simple/ 使用阿里源,下载速度快一点. python -m playwr ...

  6. mongodb重启报错解决

    mongodb关闭后重启失败 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName= ...

  7. VSCode添加某个插件后,Python 运行时出现Segmentation fault (core dumped) 解决办法

    在VSCode添加某个插件后,Debug出现Segmentation fault (core dumped) 解决方案,在当前environment下运行: conda update --all

  8. 对抗生成网络GAN

      该方法常用于: 图像生成 图像修复,训练用了MSE+Global+Local数据,其中Global+Local判别式用于全局+局部一致性. 图像超分辨率重构   GAN的基本原理,主要包含两个网络 ...

  9. 谈谈redis缓存击穿透和缓存击穿的区别,雪崩效应

    面试经历 在很长的一段时间里,我以为缓存击穿和缓存穿透是一个东西,直到最近去腾讯面试,面试官问我缓存击穿和穿透的区别:我回答它俩是一样的,面试官马上抬起头用他那细长的单眼皮眼睛瞪着我说:"你 ...

  10. 假期作业02:安装JDK与文本编辑器并编写第一个Java程序

    假期作业02:安装JDK与文本编辑器并编写第一个Java程序 一.安装JDK与文本编辑器并编写第一个java程序 首先在oracle官网(需要创建账号,进行登录后方可使用)按照自己的需求下载JDK(h ...