pixijs H5游戏开发入门(六)利用 GSAP 实现动画指定时间运动到指定位置

本系列文章

本文编写时 pixijs 版本: v7.3.2
本文编写时 GSAP 版本: v3.12.2

问题

前面文章介绍了 PIXI 精灵如何实现动画,该方法可以利用 ticker 循环调用函数实现精灵运动。

思考一个问题: PIXI 自带的 ticker 有没有办法让一个精灵在指定时间运动到指定位置?

比如有这么一个需求:需要精灵 3 秒旋转 4 圈,并在3秒结束之后停止运动,还需要使用一个贝塞尔曲线实现线性运动。

如果利用自带的 ticker 有办法实现上述需求吗?答案:不行。当然也能自己写 js 算法实现此需求!

本着不要重复造轮子的理念,本文使用 GSAP 实现上述需求。

GSAP 相关文档

github 地址: https://github.com/greensock/GSAP

文档地址: https://gsap.com/docs/v3/

pixi 插件: https://gsap.com/docs/v3/Plugins/PixiPlugin/

本文使用官方模块实现动画,有兴趣的同学可以研究下 pixi 插件。

PIXI.Ticker 实现缓慢停止的动画效果

缓慢停止效果:

上述例子已经可以利用 Ticker 实现缓慢停止效果,但是不能方便的实现指定时间停止运动。

源码:

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
88
89
90
91
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>pixijs入门示例缓慢停止的运动</title>
<script src="https://pixijs.download/v7.3.2/pixi.js"></script>
<style>
html,
body,
div {
padding: 0;
margin: 0;
}
body,
canvas {
width: 100%;
}
</style>
</head>
<body>
<div style="margin: 15px 0;">
<button id="stop_1">暂停动画</button>
<button id="start_1">播放动画</button>
<button id="restart_1">重新开始</button>
</div>
<script>
async function init() {
// 创建一个 pixi 实例
let app = new PIXI.Application({
antialias: true, // 消除锯齿
width: 300,
height: 300,
backgroundColor: 0x223355,
});

// 插入到 body 中
document.body.appendChild(app.view);

let line1 = new PIXI.Graphics();
line1.lineStyle(4, 0xFFFFFF, 1);
line1.moveTo(0, 0);
line1.lineTo(0, 120);
line1.position.set(app.renderer.width / 2, app.renderer.height / 2); // 设置位置偏移
line1.pivot.set(0, line1.height / 2); // 设置中心点
// Sprite.anchor.set(0.5, 0.5); // 精灵的旋转中心需要通过 anchor 设置
app.stage.addChild(line1);

var angleStep = 40;
let rotateSpeed = Math.floor(Math.random() * 300);

function animate() {
line1.angle += angleStep;

angleStep = angleStep - angleStep / rotateSpeed;

if (angleStep.toFixed(1) <= 0.0) {
console.log('stopped rotation');
line1.angle = line1.angle;
// 停止动画
ticker.remove(animate);
}
}

// 使用独立的 ticker 控制动画
const ticker = PIXI.Ticker.shared;
ticker.add(animate);

document.querySelector('#stop_1').addEventListener('click', () => {
// 停止动画
ticker.stop();
})

document.querySelector('#start_1').addEventListener('click', () => {
// 播放动画
ticker.start();
})

document.querySelector('#restart_1').addEventListener('click', () => {
// 重新开始动画
ticker.remove(animate);
angleStep = 40;
ticker.add(animate);
ticker.start();
})
}

init();
</script>
</body>
</html>

GSAP 实现指定时间运动到指定位置

本例子实现了精灵 3 秒钟从 angle=0 运动到 angle=360*4 ,简单说就是 3 秒钟旋转了 4 圈,并且运动效果使用 power1.inOut 曲线。

源码:

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
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>pixijs入门示指定时间运动到指定位置</title>
<script src="https://pixijs.download/v7.3.2/pixi.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12/dist/gsap.min.js"></script>
<style>
html,
body,
div {
padding: 0;
margin: 0;
}
body,
canvas {
width: 100%;
}
</style>
</head>
<body>
<div style="margin: 15px 0;">
<button id="stop_1">暂停动画</button>
<button id="start_1">播放动画</button>
<button id="restart_1">重新开始</button>
</div>
<script>
async function init() {
// 创建一个 pixi 实例
let app = new PIXI.Application({
antialias: true, // 消除锯齿
width: 300,
height: 300,
backgroundColor: 0x223355,
});

// 插入到 body 中
document.body.appendChild(app.view);

let line2 = new PIXI.Graphics();
line2.lineStyle(4, 0xFF00FF, 1);
line2.moveTo(0, 0);
line2.lineTo(0, 120);
line2.position.set(app.renderer.width / 2, app.renderer.height / 2); // 设置位置偏移
line2.pivot.set(0, line2.height / 2); // 设置中心点
// Sprite.anchor.set(0.5, 0.5); // 精灵的旋转中心需要通过 anchor 设置
app.stage.addChild(line2);

// 使用GSAP创建一个tween,使精灵在3秒后停在指定位置
const tl = gsap.timeline();
tl.to(line2, { duration: 3, angle: 360 * 4, ease: "power1.inOut" });

document.querySelector('#stop_1').addEventListener('click', () => {
// 停止动画
tl.pause();
})

document.querySelector('#start_1').addEventListener('click', () => {
// 播放动画
tl.resume();
})

document.querySelector('#restart_1').addEventListener('click', () => {
// 重新开始动画
tl.progress(0);
tl.resume();
})
}

init();
</script>
</body>
</html>

常用控制方法

  • tween.pause(); 暂停
  • tween.resume(); 恢复
  • tween.reverse(); 反向播放
  • tween.seek(0.5); 跳到0.5s
  • tween.progress(0.25); 跳到4分之1处
  • tween.timeScale(0.5); 速度减慢
  • tween.timeScale(2); 速度翻倍
  • tween.kill(); 删除动画

更多方法参考官方文档:https://gsap.com/docs/v3/GSAP/Tween

关于 ease 支持

1
2
3
4
5
6
7
8
9
10
11
type EaseString = "none"
| "power1" | "power1.in" | "power1.out" | "power1.inOut"
| "power2" | "power2.in" | "power2.out" | "power2.inOut"
| "power3" | "power3.in" | "power3.out" | "power3.inOut"
| "power4" | "power4.in" | "power4.out" | "power4.inOut"
| "back" | "back.in" | "back.out" | "back.inOut"
| "bounce" | "bounce.in" | "bounce.out" | "bounce.inOut"
| "circ" | "circ.in" | "circ.out" | "circ.inOut"
| "elastic" | "elastic.in" | "elastic.out" | "elastic.inOut"
| "expo" | "expo.in" | "expo.out" | "expo.inOut"
| "sine" | "sine.in" | "sine.out" | "sine.inOut" | string;

效果演示:

可以参考官方文档说明:https://gsap.com/docs/v3/Eases

许可证

如果你仅用于免费用途,那么 GSAP 没有任何商业风险。

如果出现以下情况,那么需要付费购买许可证:

  1. 您的网站或产品需要付费才能使用或加入。
    示例:NetFlix.com、Ancestry.com eHarmony.com - 具有使用 GSAP 的付费会员专区的电子商务网站
  1. 您在销售给多个最终用户的游戏、产品或主题中使用 GSAP
    示例:横幅广告、在创意市场上出售的主题模板、付费 Webflow 克隆物
  1. 您的游戏或应用已付费或使用微交易来获取可选功能/升级
    微交易的一个例子是,用户可以选择付费以解锁免费游戏/应用程序或赌博网站中的某个功能,用户在技术上可以免费访问,但他们可以选择付费下注或玩游戏。

参考官方文档:https://gsap.com/licensing/

本文由 linx(544819896@qq.com) 创作,采用 CC BY 4.0 CN协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。本文链接为: https://blog.jijian.link/2023-11-28/js-pixi-timeline/

如果您觉得文章不错,可以点击文章中的广告支持一下!