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. Float浮动(慕课网学习笔记)

    float浮动 属性:值 意义 float:left 左浮动 float:right 右浮动 float:none 不浮动 float:inherit 继承父元素浮动属性,若父元素没有浮动属性则失效 ...

  2. YARN的工作过程

    yarn的工作执行流程图 1.用户向YARN中提交应用程序 2.ResourceManager为该应用程序找到一个可用的NodeManager 并分配一个Container,然后在这个Containe ...

  3. Python - 面向对象编程 - 公共属性、保护属性、私有属性

    公共属性 在 Python 的类里面,所有属性和方法默认都是公共的 class PoloBlog: # 公共属性 sum = 0 # 构造方法 def __init__(self, name): se ...

  4. Bing每日壁纸的RESTful接口实现

    0x00 存在意义 权且当作Docker打包的练习. 显然可以通过构造请求获得每天的壁纸,但是如果想要优雅地在其它地方使用这一网络资源,封装一个RESTful API将会保证整洁美观,在编写CSS等场 ...

  5. 树莓派4B切换国内源-亲测有效

    参考:https://blog.csdn.net/qq_30290661/article/details/103386997 修改/etc/apt/sources.list,去掉自带的源,添加如下源: ...

  6. ffplay 播放网络摄像头视频

    shell脚本如下,无须加port ffplay rtsp://cameral_ip

  7. Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo

    Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo CountDownLatch countDownLatch这个类使一个线程等待其他线程 ...

  8. web基础常识

    1.b/s架构 2.tcp协议 3.web服务器

  9. AOP联盟通知类型和Spring编写代理半自动

    一.cglib功能更强大 二.Spring核心jar包 三.AOP联盟通知 三.代码实现Spring半自动代理 1.环绕通知的切面 2.bean.xml配置 3.创建bean容器,获取bean,即已经 ...

  10. Spring-图解