三方库
# gsap (opens new window)
// 配置数据
GSAP CSS
x: 100 transform: translateX(100px)
y: 100 transform: translateY(100px)
rotation: 360 transform: rotate(360deg)
rotationX: 360 transform: rotateX(360deg)
rotationY: 360 transform: rotateY(360deg)
skewX: 45 transform: skewX(45deg)
skewY: 45 transform: skewY(45deg)
scale: 2 transform: scale(2, 2)
scaleX: 2 transform: scaleX(2)
scaleY: 2 transform: scaleY(2)
xPercent: -50 transform: translateX(-50%)
yPercent: -50 transform: translateY(-50%)
delay 延迟
ease 速度
id 适用于 GSDevTools ,学习这个再了解
invalidateOnRefresh: true 实例后立即执行,默认false
paused true 创建动画后暂停
repeat 重复次数
repeatDelay 两次重复之间等待的时间
repeatRefresh 重复刷新
reversed 动画反转
startAt 定义任何属性的起始值,这个有时候不好理解,就是执行动画的时候设置自身的属性
例如 {x: -100, opacity: 0}
yoyo 如果为true,则其他所有repeat迭代将以相反的方向运行,以便补间看起来像是来回走动。 [开始] 1-2-3-3-2-1-1-2-3 [结束]
yoyoEase 可以yoyo: true在您定义any时自动设置yoyoEase 设置速度
keyframes: [{x:100, duration:1}, {y:100, duration:0.5}]
关键帧动画
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
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
// 例:threejs中使用
import gsap from "gsap";
// 设置动画
var animate1 = gsap.to(cube.position, {
x: 5,
duration: 5,
ease: "power1.inOut",
// 设置重复的次数,无限次循环-1
repeat: -1,
// 往返运动
yoyo: true,
// delay,延迟2秒运动
delay: 2,
onComplete: () => {
console.log("动画完成");
},
onStart: () => {
console.log("动画开始");
},
});
gsap.to(cube.rotation, { x: 2 * Math.PI, duration: 5, ease: "power1.inOut" });
// 监听鼠标双击事件
window.addEventListener("dblclick", () => {
// console.log(animate1);
if (animate1.isActive()) {
// 暂停
animate1.pause();
} else {
// 恢复
animate1.resume();
}
});
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
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
# 相对值 (opens new window)
使用+=
or-=
前缀表示相对值
# targets (opens new window)
targets
可以是:
- 一个普通对象
- 一个 DOM selector 字符串,比如 '.class'
- DOM 元素本身
- 以上三项中某一项的一个数组
gsap.to(cubeGroup.rotation, {
x: "+=" + Math.PI * 2,
y: "+=" + Math.PI * 2,
duration: 10,
ease: "power2.inOut",
repeat: -1,
});
1
2
3
4
5
6
7
2
3
4
5
6
7
比如在threejs中使用,传入的就是普通对象了,那x、y就不是dom配置了,对应的就是对象属性了。
但有些属性是gasp内部定义的特殊属性,如duration、delay、ease、onStart等,
所以,如果传入的是dom,那设置的x、y等属性对应的就是相应css样式映射了。
# fromTo
gsap.fromTo(targets, fromVars, toVars)
从 fromVars 中定义的属性 变化到 toVars 中定义的属性
参考:
# dat.gui (opens new window)
- 可视编辑器
# 数字类型
gui.add(object, key, min, max, step);
- object: 控件展示对象;key:当前展示控件名称; min:最小值; max:最大值; step:最小单位;
- min(),max(),step()也是gui控件的方法
import * as dat from "dat.gui";
const gui = new dat.GUI();
// 每个方法都是返回Controller实例对象,所以能一直追加写
gui
.add(cube.position, "x")
.min(0)
.max(5)
.step(0.01)
.name("移动x轴")
.onChange((value) => {
console.log("值被修改:", value);
})
.onFinishChange((value) => {
console.log("完全停下来:", value);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 颜色类型
// 修改物体的颜色
const params = {
color: "#ffff00",
fn: () => {
// 让立方体运动起来
gsap.to(cube.position, { x: 5, duration: 2, yoyo: true, repeat: -1 });
},
};
gui.addColor(params, "color").onChange((value) => {
console.log("值被修改:", value);
cube.material.color.set(value);
});
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 选项框
// 设置选项框
gui.add(cube, "visible").name("是否显示");
1
2
2
# 分组
var folder = gui.addFolder("设置立方体");
folder.add(cube.material, "wireframe");
1
2
2
# 触发事件
// 设置按钮点击触发某个事件
folder.add(params, "fn").name("立方体运动");
1
2
2
最终效果
# stats.js (opens new window)
- 显示实时帧数
# cannon-es (opens new window)
cannon-es (opens new window)是物理引擎,使用这个库,可以模拟three创建不同的物体,然后在物理环境下运行,物理环境下运行过程中,产生的不同效果在程序中的表现就是拥有不同的值,映射给threejs创建的物体,作为物体的配置项,这样每帧有不同的效果,就动起来了。
# World (opens new window)
该方法初始化物理世界,里面包含着物理世界的相关数据(如刚体数据,世界中所受外力等等)
- gravity
world.gravity.set(0,-9.8,0);
设置物理世界的重力为沿y轴向上-9.8米每二次方秒 - addBody() 向物理世界添加刚体
- step() 时间推进
world.step(dt , timeSinceLastCalled , maxSubSteps )
:
我们的物理引擎是用来模拟物理世界的,比如自由落体运动,最终还是要将运动结果反应给threejs的,用这个结果值,去改变threejs创建物体的位置等属性。
我们物理世界也是需要时间的,比如9.8m/s,一秒下落9.8米,我们浏览器如果是120帧(一秒渲染120次),那么我们物理世界每帧要推进多长时间呢,答案是1/120秒,这样我们才能做到物理世界与我们threejs创建的3d世界保持同步。
在物理世界如果我们固定每帧往前推进1/120秒,那如果我们换到了30帧的运行环境,运行环境中的1秒,才会在物理环境推进(1/120)*30,即物理环境只会往前推进0.25秒,如何保持一致呢,每帧,调用4次step()
,这样就又可以保持一致了。
为了保持一致,就需要到了第二个参数timeSinceLastCalled
了,代表距离上一帧的时间,30帧的环境下,也就是timeSinceLastCalled = 1/30
,(1/120)*4 = 1/30,这一步方法内会自动完成计算,每帧去掉用4次step(),所以第二个参数还是要配置的。
第三个参数是最多迭代多少次step(),上面我们迭代了4次,如果在1帧环境下呢,要迭代120次了,我们就可以用第三个参数做限制,默认是10。
.注意: 该方法要在每帧渲染都调用的,要不然物理世界就得不到推进了
// 看源码,可以看作是这样一个方法,timeSinceLastCalled,默认0,maxSubSteps,默认10
function step(dt:number, timeSinceLastCalled?:number=0, maxSubSteps?:number=10)
// dt: step方法执行的时间间隔,单位秒,通常取值为游戏帧频的倒数;
// timeSinceLastCalled: 当游戏帧频降低时计算两帧之间的时间差作为参数值,此时P2会在一次step()中进行count= timeSinceLastCalled/dt次计算,以保证物理模拟的真实性,默认值为0;
// maxSubSteps: 单次step()进行物理模拟计算的最大次数,当timeSinceLastCalled不等于0时,单次step()中进行计算的次数count最大为maxSubSteps,默认值为10。
1
2
3
4
5
2
3
4
5
.参考:
1.物理引擎 (opens new window)
2.创建P2物理项目一p2.js物理引擎详细教程 (opens new window)
- addContactMaterial 向世界添加联系材料
- defaultContactMaterial 设置世界碰撞的默认材料,如果材料没有设置,都用这个
# Sphere (opens new window)
用来创建一个球形
# Material (opens new window)
创建一种物理材质
# Body (opens new window)
创建物体
- shape 形状
- position 位置
- mass 质量
- material 材质
- quaternion 方向
- setFromAxisAngle (opens new window) 在给定轴和角度的情况下设置四元数分量。
- applyLocalForce 添加一个外部力
# Plane (opens new window)
创建平面
# EventTarget (opens new window)
事件目标
- addEventListener 事件监听
# ContactMaterial (opens new window)
定义当两种材料相遇时会发生什么。
# Box (opens new window)
创建一个盒子形状
# 参考
编辑 (opens new window)
上次更新: 2022/09/26