demo来源(如果觉得有用请点赞,如果收藏更好了 谢谢各位)
本期为github拉取Three.js源代码中的对引入glb格式的模型demo分析
clone地址:[email protected]:mrdoob/three.js.git
demo目录:examples\webgl_animation_keyframes
源代码如下 (下方我会对源代码进行逐条分析)
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - animation - keyframes</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
<style>
body {
background-color: #bfe3dd;
color: #000;
}
a {
color: #2983ff;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - animation - keyframes<br />
Model: <a href="https://artstation.com/artwork/1AGwX" target="_blank" rel="noopener">Littlest Tokyo</a> by
<a href="https://artstation.com/glenatron" target="_blank" rel="noopener">Glen Fox</a>, CC Attribution.
</div>
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "../build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import Stats from './jsm/libs/stats.module.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
import { RoomEnvironment } from './jsm/environments/RoomEnvironment.js';
import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from './jsm/loaders/DRACOLoader.js';
let mixer;
const clock = new THREE.Clock();
const container = document.getElementById( 'container' );
const stats = new Stats();
container.appendChild( stats.dom );
const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.outputEncoding = THREE.sRGBEncoding;//材质
container.appendChild( renderer.domElement );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
const scene = new THREE.Scene();
scene.background = new THREE.Color( 0xbfe3dd );
scene.environment = pmremGenerator.fromScene( new RoomEnvironment(), 0.04 ).texture;
const camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.set( 5, 2, 8 );
const controls = new OrbitControls( camera, renderer.domElement );
// controls.target.set( 0, 0.5, 0 );
controls.update();
controls.enablePan = false;
controls.enableDamping = true;
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath( 'js/libs/draco/gltf/' );
const loader = new GLTFLoader();
loader.setDRACOLoader( dracoLoader );
loader.load( 'models/gltf/Horse.glb', function ( gltf ) {
const model = gltf.scene;
model.position.set( 1, 1, 0 );
model.scale.set( 0.01, 0.01, 0.01 );
scene.add( model );
mixer = new THREE.AnimationMixer( model );
mixer.clipAction( gltf.animations[ 0 ] ).play();
animate();
}, undefined, function ( e ) {
console.error( e );
} );
window.onresize = function () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
};
function animate() {
requestAnimationFrame( animate );
const delta = clock.getDelta();
mixer.update( delta );
controls.update();
stats.update();
renderer.render( scene, camera );
console.log( delta );
console.log( mixer.update( delta ) );
}
</script>
</body>
</html>
demo效果图

代码逐条分析
导入three库
javascript
import * as THREE from 'three';
导入一个性能查看插件 这个东西基本项目上不会用到,用于分析 这个东西就是效果图右上角的 如下图
javascript
import Stats from './jsm/libs/stats.module.js';

导入一个 轨道控制器:也称相机视角控制器(具体使用下文会有介绍)
javascript
import { OrbitControls } from './jsm/controls/OrbitControls.js';
导入模型的材质文件。
javascript
import { RoomEnvironment } from './jsm/environments/RoomEnvironment.js';
分别导入模型格式所需的loader文件。如果需要导入其余模型格式,可在上文的git源码中找到
javascript
import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from './jsm/loaders/DRACOLoader.js';
创建一个时钟对象Clock**(将用于demo中的小车运动)**
javascript
const clock = new THREE.Clock();
这里获取了container元素。并赋值给了变量container new一个性能查看的插件 添加到了元素上
javascript
const container = document.getElementById( 'container' );
const stats = new Stats();
container.appendChild( stats.dom );
设置three的渲染为webGL并赋值给了变量renderer 对renderer的详细设置看注释
javascript
const renderer = new THREE.WebGLRenderer( { antialias: true } );
// 像素比设置
renderer.setPixelRatio( window.devicePixelRatio );
// 渲染容器大小设置
renderer.setSize( window.innerWidth, window.innerHeight );
// 在导入材质时,会默认将贴图编码格式定义为Three.LinearEncoding,故需将带颜色信息手动指定为Three.sRGBEncodin
renderer.outputEncoding = THREE.sRGBEncoding;//材质
将randerer元素添加到了 container中。 生成一个亮度环境,传入renderer 并赋值给了pmremGenerator Scene:生成为场景对象。 设置scene场景对象的背景颜色
javascript
// 添加渲染容器到html盒子中
container.appendChild( renderer.domElement );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
const scene = new THREE.Scene();
scene.background = new THREE.Color( 0xbfe3dd );
此处用到了导入的模型。RoomEnvironment.js文件感兴趣的同学可以去分析文件目录如下
javascript
examples\jsm\environments
javascript
import { RoomEnvironment } from './jsm/environments/RoomEnvironment.js';
...
...
scene.environment = pmremGenerator.fromScene( new RoomEnvironment(), 0.04 ).texture;
接下来为设置摄像机 PerspectiveCamera 函数共有4个参数 数据类型均为number PerspectiveCamera( fov, aspect, near, far );
- fov------fov表示视场,所谓视场就是能够看到的角度范围,人的眼睛大约能够看到180度的视场,视角大小设置要根据具体应用,一般游戏会设置60~90度。 默认值45
- aspect------aspect表示渲染窗口的长宽比,如果一个网页上只有一个全屏的canvas画布且画布上只有一个窗口,那么aspect的值就是网页窗口客户区的宽高比 window.innerWidth/window.innerHeight
- near------near属性表示的是从距离相机多远的位置开始渲染,一般情况会设置一个很小的值。 默认值0.1
- far------far属性表示的是距离相机多远的位置截止渲染,如果设置的值偏小小,会有部分场景看不到。 默认值1000 new一个PerspectiveCamera 设置参数并设置其初始视角
往下OrbitControls 导入的通用的OrbitControls相机控制器并设置其属性值
javascript
const camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.set( 5, 2, 8 );
const controls = new OrbitControls( camera, renderer.domElement );
controls.update();
// 是否禁止右键拖拽
controls.enablePan = false;
controls.enableDamping = true;
导如loader模型。代码每一步都有注释 loader.load函数接收参数,分别问。模型地址。渲染函数,也可以接收错误信息,打印出来查看具体错误
javascript
// 导入DRACO格式的loader
const dracoLoader = new DRACOLoader();
// 设置loader路径解压压缩模型
dracoLoader.setDecoderPath( 'js/libs/draco/gltf/' );
// 导入GLTF格式的loader
const loader = new GLTFLoader();
//设置DRACOloader
loader.setDRACOLoader( dracoLoader );
// 导入
loader.load( 'models/gltf/LittlestTokyo.glb', function ( gltf ) {
const model = gltf.scene;
model.position.set( 1, 1, 0 );
model.scale.set( 0.01, 0.01, 0.01 );
scene.add( model );
mixer = new THREE.AnimationMixer( model );
mixer.clipAction( gltf.animations[ 0 ] ).play();
animate();
}, undefined, function ( e ) {
console.error( e );
} );
动画执行函数 重复执行animate 函数获取时间更新renderer
javascript
function animate() {
requestAnimationFrame( animate );
// 获得前后两次执行该方法的时间间隔
const delta = clock.getDelta();
mixer.update( delta );
controls.update();
// 性能控件更新
stats.update();
renderer.render( scene, camera );
}
至此全文结束