Three.js学习笔记

学习Three.js官方例子的一些总结! 🎃

学习链接
three.js
学习帮助论坛

基础

  1. 创建场景
    需要:场景、相机、渲染器(三步)
    设置:把渲染器添加到HTML中-即canvas元素

  2. 创建立方体
    需要:geometry 和 material => mesh
    设置:添加进场景,设置camera的位置!!!

    默认情况添加元素,物体位置(0,0,0),此时考虑移动摄像机

  3. 渲染场景
    以上步骤还没有真正渲染,需要一个render loop / animate loop
    大多数屏幕刷新频率60次/秒

    1
    2
    3
    4
    5
    function animate() {
    requestAnimationFrame( animate );
    renderer.render( scene, camera );
    }
    animate();
  4. 让物体旋转
    代码添加到animate()函数中renderer.render调用的上方:
    当应用程序运行时,想要移动或者改变任何场景中的东西,都必须要经过这个动画循环。
    也可以在这个函数里面调用别的函数

    1
    2
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
  5. 运行
    本地开启live-server


画线

  • 目的:画一个圆或一条线
  • 设置:渲染器、场景、摄像机
  • 需要一些点(3个),材质
  • 点是出现在对称点中间的。

创建文字

  • 目的:使用文本
    方法一
  • 添加DOM,绝对定位,z-index
    方法二
  • 文字绘制到画布中,将其用做Texture
    方法三
  • 用3D软件创建模型
    方法四
  • three.js自带的文字几何体
    THREE.TextGeometry的实例的网格:

载入3D模型
推荐使用glTf格式 - 传输效率高,加载块
根据格式引入加载器

为什么会引入viewport的标签
–用于在移动端浏览器上控制视口的大小和缩放

导入微信公众号

three.js入门001

Three.js先决条件
Three.js 基础

  1. 加载three.js

    1
    2
    3
    4
    5
    注意这里的module
    模块的优点是可以很方便地导入需要的其他模块。这样我们就不用再手动引入它们所依赖的其他文件了。
    <script type="module">
    import * as THREE from './resources/threejs/r127/build/three.module.js';
    </script>
  2. 需要一个canvas标签
    <canvas id="c"></canvas>
    three.js需要使用这个canvas标签来绘制,
    要先获取它然后传给three.js

    1
    2
    3
    4
    function main() {
    const canvas = document.querySelector('#c');
    const renderer = new THREE.WebGLRenderer({canvas});
    ...
  3. 设置一个透视摄像机
    共四个参数

    1
    2
    const camera = new THREE.PerspectiveCamera
    ( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
  • 视野角度,显示器上看到的场景范围,单位是角度
  • 长宽比,用宽度除以高度
  • 近截面、远截面,注意近、远、截面,超过,不会渲染
    需要移动摄像机参能照到物体
    camera.position.z = 2;
  1. 创建场景
    添加一个盒子
    把场景和摄像机都给渲染器渲染

  2. 动起来
    需要调用requestAnimationFrame函数

    官方教程可以调试,好评!!!

  3. 添加灯光

    1
    2
    3
    4
    5
    6
    7
    8
    {
    const color = 0xFFFFFF;
    const intensity = 1;
    平行光
    const light = new THREE.DirectionalLight(color, intensity);
    light.position.set(-1, 2, 4);
    scene.add(light);
    }
  4. 响应式
    使用模块加载。。。


Three.js 场景图
很有收获!!
空对象-类似 自绝父相
渲染有先后顺序 - 轴/网格
统一加入数组,es6可设置旋转
父添加子类。父放大 子也放大 - 像继承 - 需要场景节点。。。

明个在记笔记!


例子

开始敲里面的例子

  • 敲完它!!
  • 21-6-20

css2d_label

记录一个关于a标签的
rel='noopener'

原因是使用target=_blank打开新的窗口时,赋予了新的窗口一些权限可以操作原tab页,
其中window.location就是一个。
不使用 rel=noopener就是让用户暴露在钓鱼攻击上。
关于a标签target_blank使用rel=noopener

学习内容

  1. camera.updateProjectionMatrix();

    如果相机对象与投影矩阵相关的属性发生了变化,就需要手动更新相机的投影矩阵
    Three.js更新机制

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    init()
    window.addEventListener('resize', onWindowResize);

    //根据视图调整比例
    function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;

    // 矩阵变换(Matrix transformations)
    camera.updateProjectionMatrix();

    renderer.setSize(window.innerWidth, window.innerHeight);

    labelRenderer.setSize(window.innerWidth, window.innerHeight);
    }
  2. import { OrbitControls } from ‘../jsm/controls/OrbitControls.js’;

    控制摄像机 - 实现物体选择,缩放,平移 - 移动的都是摄像机
    可以实现方向键漫步效果
    可以设置禁止缩放等,控制缩放范围等
    可以修改相机的窗口作用范围
    使用change监听,控制何是渲染 - 不需要周期性渲染 - 节省性能
    Three.js相机控件OrbitControls

    1
    2
    3
    const controls = new OrbitControls(camera, labelRenderer.domElement);
    controls.minDistance = 5;
    controls.maxDistance = 100;
  3. import { CSS2DRenderer, CSS2DObject } from

    SS2DRenderer会递归遍历scene 去找到CSS2DObject 来进行渲染得到标签内容信息。CSS2DObject可以添加进入你想要展示其的mesh当中。
    给三维物体绑定标签
    CSS2DRenderer是CSS3DRenderer(CSS 3D渲染器)的简化版本,唯一支持的变换是位移。
    Three.js中的CSS2DObject和CSS2DRenderer
    CSS 2D渲染器(CSS2DRenderer)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    const moonDiv = document.createElement('div');
    //style 中定义的
    moonDiv.className = 'label';
    moonDiv.textContent = 'Moon';
    moonDiv.style.marginTop = '-1em';

    const moonLabel = new CSS2DObject( moonDiv );
    moonLabel.position.set(0, MOON_RADIUS, 0);
    // moon 是三维物体
    moon.add( moonLabel );

    //CSS2DObject之后CSS2DRenderer()
    labelRenderer = new CSS2DRenderer();

    labelRenderer.setSize(window.innerWidth, window.innerHeight);
    labelRenderer.domElement.style.position = 'absolute';
    // 相对鼠标的相对偏移 ?????
    labelRenderer.domElement.style.top = '0px';
    document.body.appendChild(labelRenderer.domElement);

    const controls = new OrbitControls(camera, labelRenderer.domElement);
    controls.minDistance = 5;
    controls.maxDistance = 100;
  4. const earthMaterial = new THREE.MeshPhongMaterial

    该材料使用 非基于物理 的Blinn-Phong模型来计算反射系数。
    与在MeshLambertMaterial中使用的Lambertian模型不同,
    它可以模拟带有高光的闪亮表面(如漆木)。
    学习链接的代码值得参考↓
    Three.js - MeshPhongMaterial 用于光亮表面的材质

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    const earthGeometry = new THREE.SphereGeometry(EARTH_RADIUS, 16, 16);
    const earthMaterial = new THREE.MeshPhongMaterial({
    //材质的高光颜色。默认值是0x111111
    specular: 0x333333,

    //高亮的程度,越高的值越闪亮。默认值为30
    shininess: 5,

    //颜色贴图,默认null.纹理贴图颜色由漫反射颜色.color调节
    map: textureLoader.load('../textures/planets/earth_atmos_2048.jpg'),

    //镜面反射贴图值会影响 镜面高光 以及 环境贴图对表面的影响程度。默认null
    specularMap: textureLoader.load('../textures/planets/earth_specular_2048.jpg'),

    // 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,
    // 并更改颜色照亮的方式。
    // 法线贴图不会改变曲面的实际形状,只会改变光照。
    normalMap: textureLoader.load('textures/planets/earth_normal_2048.jpg'),

    //法线贴图对材质的影响程度。典型范围是0-1 ,默认值是Vector2 设置(1,1)
    normalScale: new THREE.Vector2(0.85, 0.85)

    });

    // const earth = new THREE.Mesh(earthGeometry, earthMaterial);
    earth = new THREE.Mesh(earthGeometry, earthMaterial);
    //添加进场景
    scene.add(earth);

interactive_voxelpainter

描述: 鼠标移入,有一个预加载的盒子跟着移动
点击创建一个实体盒子,按住shift可以删除盒子,

内容:创建、删除、随鼠标移动、预加载、按键配合

学习内容

  1. 创建时候把要用到的一起创建
    1
    2
    3
    4
    5
    let camera, scene, renderer;
    let plane;
    let pointer, raycaster, isShiftDown = false;
    let rollOverMesh, rollOverMaterial;
    let cubeGeo, cubeMaterial;
  1. const gridHelper = new THREE.GridHelper(1000, 20);
    Three.js 坐标网格 GridHelper

  2. raycaster = new THREE.Raycaster();
    ThreeJS中的点击与交互——Raycaster的用法
    场景坐标、屏幕坐标、视点坐标
    主要方法 - setFromCamera、intersectObject
    Three.js - 通过 THREE.Raycaster 实现模型选中与信息显示
    HTML DOM addEventListener() 方法

  3. 添加灯光
    ambientLight - 环境光
    directionalLight - 平行光

  4. keyCode
    Keycode对照表

    1
    2
    3
    4
    5
    6
    7
    function onDocumentKeyDown(event) {
    switch (event.keyCode) {
    case 16:
    isShiftDown = true;
    break;
    }
    }
  5. render()
    在合适的时候,节约资源

  • 初始化的时候
  • 鼠标移动的时候
  • 鼠标点击的时候
    1
    2
    3
    function render() {
    renderer.render(scene, camera);
    }
  1. 未解之处。。。
    threejs 之 复制删除正方体
    1
    2
    3
    rollOverMesh.position.copy(intersect.point).add(intersect.face.normal);
    rollOverMesh.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25);

loader_gltf

描述:加载gltf

学习内容

  1. OrbitControls - 控制摄像机
  2. GLTFLoader - 加载gltf - setPath - load
  3. RGBELoader - 加载hdr
  4. RoughnessMipmapper - 未解。。。
  5. 运行在手机上 - 修改live-server的地址
  6. renderer - 重点!!!
    这个链接包含renderer里面的参数,
    three.js学习(5):Renderer

Github博客学习01

系统跟着学习一下!!!
Three.js达人课相关案例

01

scene - 添加
camera - 画面
render - 渲染

几何体 - 材质 - 网格

这一句值得学习!!!
<body onload="init()">

02

性能检测框 - 可以显示fps

1
2
3
4
5
6
7
8
9
10
11
<script src="../js/stats.min.js"></script>
var state

在animate()里面
stats.update(); //更新性能检测框

//性能检测框 - 放入init()
function initStats() {
stats = new Stats();
document.body.appendChild(stats.dom);
}

03

学习使用dat.GUI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script src="../js/dat.gui.min.js"></script>

var gui;

//创建调试框 - 放入init()
function initGui() {
controls = {
positionX:0,
positionY:0,
positionZ:0
};

gui = new dat.GUI();
// 控制按钮 + k v + 方法
gui.add(controls, "positionX", -1, 1).onChange(updatePosition);
gui.add(controls, "positionY", -1, 1).onChange(updatePosition);
gui.add(controls, "positionZ", -1, 1).onChange(updatePosition);

function updatePosition() {
// 这个mesh就是方块网格
mesh.position.set(controls.positionX, controls.positionY, controls.positionZ);
}
}

04

创建各种几何图形,旋转暂停gui

若有所思。。
图解WebGL&Three.js工作原理
three.js初探,立体几何入手(一)
在animate()里面判断条件,是否旋转
旋转的标记来自gui

1
2
3
4
5
6
7
8
9
10
11
12
13
// 创建调试框
function initGui() {
controls = {
rotate: true
};

// 这里创建和物体的关联性
gui = new dat.GUI(); //实例化
gui.add(controls, 'rotate').name('旋转').onChange(function(e) {
rotate = e;
console.log('e',e);
}) ;
}

05

学习了创建线和曲线

  • 先有基础的点,给一个几何物体,几何物体移动

geometry在运行的时候也会解析成bufferGeometry
BufferGeometry和Geometry有什么不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 添加直线
var pointsArr = [
new THREE.Vector3(-10, 0, -5),
new THREE.Vector3(-5, 15, -5),
new THREE.Vector3(20, 15, -5),
new THREE.Vector3(10, 0, 5)
];
//实例化几何体
var lineGeometry = new THREE.Geometry();
//使用当前点的属性配置几何体
lineGeometry.setFromPoints(pointsArr);

var lineMaterial = new THREE.LineBasicMaterial({
color: 0x00ff00
});

line = new THREE.Line(lineGeometry, lineMaterial);
// 整体移动!!!
line.position.set(-65, -30, 0);
scene.add(line);

// 添加曲线
var curve = new THREE.CatmullRomCurve3(pointsArr);

//使用getPoints获取当前曲线分成50段后的所有顶点
var points = curve.getPoints(50)
// 使用定点生成几何体
var curveGeometry = new THREE.BufferGeometry().setFromPoints(points)

var curveMaterial = new THREE.LineDashedMaterial({
color: 0xff0000
});

// 使用THREE.Line创建线
curveLine = new THREE.Line(curveGeometry, curveMaterial);
//需要重新计算位置才能显示出虚线
curveLine.computeLineDistances();
curveLine.position.set(-65, -30, 0);
scene.add(curveLine);

06

学习灯光操作,配合gui,cool,光照辅助-方便查看光线,阴影
script可以放到body下面。。。。

  • 灯光
  • 渲染投影
  • 投掷投影
  • 接收投影
  • 投影密度

Three.js - 使用阴影效果 shadowMap 和 设置阴影分辨率
Three.js - HemisphereLight 光源
Three.js - SpotLight 光源

GUI使用方法总结:
0. 创建 数据对象

  1. 创建 dat.GUI() 实例
  2. 添加参数 addColor/ add - 对象 名字 方法
  3. var camera = datGui.addFolder('阴影设置'); 折叠参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 修改球体位置的方法,平行光的target就是球
function changeSpherePosition() {
// 把gui里面的值放到世界坐标
sphere.position.set(gui.targetX, gui.targetY, gui.targetZ);
}

function updateShadow() {
directionalLight.shadow.camera.near = gui.near;
directionalLight.shadow.camera.far = gui.far;
directionalLight.shadow.camera.left = gui.left;
directionalLight.shadow.camera.right = gui.right;
directionalLight.shadow.camera.top = gui.top;
directionalLight.shadow.camera.bottom = gui.bottom;

directionalLight.shadow.camera.updateProjectionMatrix();
}

//这两个值决定生成阴影密度 默认512
directionalLight.shadow.mapSize.height = 1024;
directionalLight.shadow.mapSize.width = 1024;
//告诉平行光需要开启阴影投射
directionalLight.castShadow = true;

cube.castShadow = true; //开启投影
plane.receiveShadow = true; //可以接收阴影

// 光线辅助 --方便查看光线,阴影
debug = new THREE.CameraHelper(directionalLight.shadow.camera);
debug.name = 'debug';
scene.add(debug);

07

通过鼠标控制camera的运动,,点击物体,可以移动摄像机
一堆公式,暂略。。。。

08

学习创建精灵

Sprite是一个永远面向相机的平面 - 可做提示用
Sprite和points
HTML DOM getContext() 方法
HTML canvas createRadialGradient() 方法

09

orbitControls
TrackballControls

10

加载模型 + OrbitControls
加载器:

ColladaLoader
FBXLoader
GLTFLoader
JSONLoader
ObjectLoader
OBJLoader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<script src="../js/loaders/ColladaLoader.js"></script>

//创建collada加载器
var loader = new THREE.ColladaLoader();
loader.load('../js/models/collada/elf.dae', function (collada) {

//添加阴影
collada.scene.traverse(function (item) {
if(item instanceof THREE.Mesh){
item.castShadow = true;
item.receiveShadow = true;
}
});
//缩放
collada.scene.scale.set(5,5,5);
scene.add(collada.scene);
});


//创建fbx加载器
var loader = new THREE.FBXLoader();
loader.load('../js/models/fbx/file.fbx', function (fbx) {
fbx.scale.set(.1,.1,.1);
fbx.traverse(function (item) {
if(item instanceof THREE.Mesh){
item.castShadow = true;
item.receiveShadow = true;
}
});
scene.add(fbx);
});

//创建gltf加载器
var loader = new THREE.GLTFLoader();
loader.load('../js/models/gltf/scene.gltf', function (gltf) {
gltf.scene.scale.set(.1,.1,.1);
scene.add(gltf.scene);
});

JSONLoader -

  • 加载模型
  • 导出模型 - 文件操作
  • 导入模型

gui里面可以放方法。
JavaScript encodeURIComponent() 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//创建模型
createScene: function() {
//首先先删除掉当前场景所含有的立方体
deleteGroup('group');
//创建一个新的模型组
let group = new THREE.Group();
group.name = 'group';
let geometry = new THREE.BoxGeometry(10, 10, 10);
for (let i = 0; i < 30; i++) {
let material = new THREE.MeshLambertMaterial({color: randomColor()});
let mesh = new THREE.Mesh(geometry, material);

//随机位置
mesh.position.set(THREE.Math.randFloatSpread(200), THREE.Math.randFloatSpread(200), THREE.Math.randFloatSpread(200));
// 循环30次
group.add(mesh);
}
scene.add(group);
},

//随机颜色
function randomColor() {
var arrHex = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'],
strHex = '#',
index;

for(var i = 0; i < 6; i++) {
//直接渲染16进制。。
index = Math.round(Math.random()*15);
strHex += arrHex[index];
}
return strHex;
}

// 保存文件
function download(filename, text) {

var pom = document.createElement('a');
pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
pom.setAttribute('download', filename);
if(document.createEvent) {
var event = document.createEvent('MouseEvents');
event.initEvent('click', true, true);
pom.dispatchEvent(event);
} else{
pom.click();
}
}

// 删除group
function deleteGroup(name) {
let group = scene.getObjectByName(name);
if(!group) return;
//删除掉所有的模型组内的mesh
group.traverse(function (item) {
if(item instanceof THREE.Mesh) {
item.geometry.dispose(); //删除几何体
item.material.dispose(); //删除材质
}
});
scene.remove(group);
}

//创建MTL加载器 - 加载obj模型
var mtlLoader = new THREE.MTLLoader();
//设置文件路径
mtlLoader.setPath('../js/models/obj/');
//加载mtl文件
mtlLoader.load('female02.mtl', function (material) {
//创建OBJ加载器
var objLoader = new THREE.OBJLoader();
//设置当前加载的纹理
objLoader.setMaterials(material);
objLoader.setPath('../js/models/obj/');
objLoader.load('female02.obj', function (object) {
//添加阴影
object.traverse(function (item) {
if(item instanceof THREE.Mesh){
item.castShadow = true;
item.receiveShadow = true;
}
});
//缩放
object.scale.set(.3,.3,.3);
scene.add(object);
})
});

11

加载动画

  • 变形动画 - 通过变形目标morphTargets,让所有顶点从一个位置变化到另一个位置,并重复该过程。
  • 骨骼动画 - 骨骼即是网格的骨头,把所有顶点绑定到特定的骨头上

morphTargets 是制作动画的最直接的方法,
但是这种方法有一个不足,就是对于大型的模型和大型动画,
模型的文件会变得很大,因为每个变形都需要储存一下所有的顶点,示例是一匹马在奔跑。
Three.js - 用 morphTargets 制作变形动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
loader.load("../js/models/json/horse.js", function (geometry) {
mesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
vertexColors: THREE.FaceColors,
morphTargets: true
}));
mesh.castShadow = true;
mesh.scale.set(0.1, 0.1, 0.1);
scene.add(mesh);
// 创建场景合成器,用来在特定的场景中的象实现动画的合成,
// 当场景中有很多对象的时候,可以为每个对象都指定一个
mixer = new THREE.AnimationMixer(mesh);
// 是一组可以重复使用的关键帧,每一帧组合起来就是一个动画
var clip = THREE.AnimationClip.CreateFromMorphTargetSequence('gallop', geometry.morphTargets, 30);
// 执行动画并设置 fps 值
mixer.clipAction(clip).setDuration(1).play();
});


// 完成以上步骤之后,还需要调用在循环函数中,来更新动画的位置。
if (mixer) {
mixer.update(time);
}

定义两个变形目标,把定点放入立方体的morphTargets里面,

是几何体, 不是Mesh
这两个目标添加进gui

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 gui = {
influence1:0.01,
influence2:0.01,
update : function () {
cube.morphTargetInfluences[0] = gui.influence1;
cube.morphTargetInfluences[1] = gui.influence2;
}
};

var datGui = new dat.GUI();
//将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)
//onChange里面的方法可以在gui里面定义,也可以在外面定义
datGui.add(gui, 'influence1', 0, 1).onChange(gui.update);
datGui.add(gui, 'influence2', 0, 1).onChange(gui.update);

// 创建显示的立方体

var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
var cubeMaterial = new THREE.MeshLambertMaterial({morphTargets: true, color: 0x00ffff});

// 创建两个影响立方体的变形目标
var cubeTarget1 = new THREE.BoxGeometry(2, 10, 2);
var cubeTarget2 = new THREE.BoxGeometry(8, 2, 8);

// 将两个geometry的顶点放入到立方体的morphTargets里面
cubeGeometry.morphTargets[0] = {name: 'target1', vertices: cubeTarget1.vertices};
cubeGeometry.morphTargets[1] = {name: 'target2', vertices: cubeTarget2.vertices};
cubeGeometry.computeMorphNormals();

cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.set(0, 10, 0);

// 将立方体添加到顶点当中
scene.add(cube);

骨骼动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function createMesh(geometry, bones) {
var material = new THREE.MeshPhongMaterial({
skinning: true,
color: 0x156289,
emissive: 0x072534,
side: THREE.DoubleSide
});

var lineMaterial = new THREE.MeshBasicMaterial({
skinning: true,
wireframe: true
});

mesh = new THREE.SkinnedMesh(geometry, [material, lineMaterial]);
var skeleton = new THREE.Skeleton(bones); //创建骨架

mesh.add(bones[0]); //将骨骼添加到模型里面

mesh.bind(skeleton); //模型绑定骨架

//添加骨骼辅助标记
skeletonHelper = new THREE.SkeletonHelper(mesh);
skeletonHelper.material.linewidth = 2;
scene.add(skeletonHelper);

return mesh;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var loader = new THREE.GLTFLoader();
loader.load('../js/models/gltf/marie/scene.gltf', function (gltf) {
console.log(gltf);
gltf.scene.scale.set(.1, .1, .1);
gltf.scene.traverse(function (child) {
if (child.isMesh) {
child.frustumCulled = false;
child.castShadow = true;
}
});
scene.add(gltf.scene);
var obj = gltf.scene; //获取到模型对象
meshHelper = new THREE.SkeletonHelper(obj);
//scene.add(meshHelper);
mixer = new THREE.AnimationMixer(obj);
action = mixer.clipAction(gltf.animations[0]);
action.play();
});

12

tween

tweenmax官网

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<script src="../js/Tween.js"></script>
var tween;

//声明一个保存需求修改的相关数据的对象
gui = {
start:function () {
tween.start();
}
};

var datGui = new dat.GUI();
//将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)
datGui.add(gui, "start").name("开始动画");

//直接链式实现tween
tween = new TWEEN.Tween(cube.position).to({x:40, y:30, z:30}, 2000);

var tween2 = new TWEEN.Tween(cube.position).to({x:40, y:30, z:-30}, 2000);

var tween3 = new TWEEN.Tween(cube.position).to({x:-40, y:0, z:-30}, 2000);

tween.chain(tween2);
tween2.chain(tween3);
tween3.chain(tween);


//更新Tween
TWEEN.update();

tween 循环

1
2
//直接链式实现tween
tween = new TWEEN.Tween(cube.position).to({x:40, y:30, z:30}, 2000).repeat(Infinity).yoyo(true);

13

框选界面元素
getClientRects() 和 getBoundingClientRect() 的用法和区别

//声明一个显示的拖拽框的div
// 赋值css语句 也可以应用stlye里面的。
定义一个框,用来选中,确定左上距离和宽高,定义一个数组,保存原始元素数据(材料,位置)
循环全部元素,通过位置来判断是否要改变材质,
框选结束后,整体恢复材质

点击交互

//通过鼠标点击的位置计算出射线所需要的点的位置,以屏幕中心为原点,值的范围为-1到1.
//根据在屏幕的二维位置以及相机的矩阵更新射线的位置
// 获取射线直线和所有模型相交的数组集合

Github博客学习02

01

博客学习03

Three.js零基础入门教程(郭隆邦)


官方案例链接

各种材质
webgl_loader_texture_dds
各种材质+融球效果
webgl_marchingcubes
透明材质
webgl_materials_cubemap_refraction
球面反射
webgl_materials_envmaps
可以隐形。。遮挡?
webgl_materials_envmaps_parallax
名画滤镜
webgl_materials_texture_manualmipmap
材质球
webgl_multiple_elements
全景空间
webgl_panorama_equirectangular
渐变移动的点
webgl_points_billboards
移动的人形的点
webgl_points_dynamic
雪花精灵
webgl_points_sprites
岩浆。。
webgl_shader_lava
很真实的材质。。。
webgl_shading_physical
全景video,可以移动
webgl_video_panorama_equirectangular
迷雾效果。。
webgl_postprocessing_godrays
遮罩
webgl_postprocessing_masking
辉光
webgl_postprocessing_unreal_bloom

webgl_buffergeometry_drawrange
千纸鹤
webgl_gpgpu_birds
闪电
webgl_lightningstrike
动画组
misc_animation_groups
框选盒子
misc_boxselection
用手机测试,不开摄像头,能旋转画面
misc_controls_deviceorientation
可以wasd,鼠标,qr等移动画面
misc_controls_fly
上下左右空格跳跃,鼠标控制画面
misc_controls_pointerlock
给物体添加标签
css2d_label
卡片动画
css3d_periodictable


codepen链接

都是使用了three.js

蝴蝶飞舞
蝴蝶飞舞02

电影开头动画效果

真实草地效果

太空水晶球

霓虹隧道

变色龙-变色

线立体球

鲜花绽放

银河系

无尽走廊

轮播切换

叠砖块小游戏

魔方-可以动

低边建模旋转星球

迷之小鸡

飞行小鱼

遛猫

点击喷火龙

绿色迷雾

博客学习