前言
事情是这样的,最近加入了创业、兼职、学习氛围浓厚的群。看到了很多有趣的案例,跟着大佬学习了一些有意思的东西,所以呢,想着来分享这个使用PIXI+GSAP实现的刹车动效案例。
最终效果
那咋们直接上图看效果
基础环境
准备好两个库,一个就是PixiJS,是一个非常优秀的2d WebGL 渲染引擎,官网链接:pixijs.com/。另一个就是动画引擎库Gsap,官网链接:greensock.com/docs/v3/GSA…。话不多说,接下来开始上代码。
初始化页面,创建PIXI应用
<html>
<html>
<head>
<title>猿创营</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,user-scalable=no">
<style type="text/css">
html, body { margin: 0;padding: 0; }
div { width: 100%; }
</style>
<script src="https://pixijs.download/release/pixi.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.10.4/gsap.min.js"></script>
<script src="./js/brakebanner.js"></script>
<script>
window.onload = init;
function init() {
let banner = new BrakeBanner("#brakebanner");
}
</script>
</head>
<body>
<div id="brakebanner"></div>
</body>
</html>
//brakebanner.js
class BrakeBanner {
constructor(selector) {
this.app = new PIXI.Application({
width: window.innerWidth,
height: window.innerHeight,
backgroundColor: 0xf0f0f0,
resizeTo: window
})
document.querySelector(selector).appendChild(this.app.view)
//创建舞台
this.stage = new PIXI.Container();
}
}
加载静态资源
//创建加载器
this.loader = new PIXI.Loader()
this.loader.add('btn.png', 'images/btn.png')
this.loader.add('brake_bike.png', 'images/brake_bike.png')
this.loader.add('brake_handlerbar.png', 'images/brake_handlerbar.png')
this.loader.add('brake_lever.png', 'images/brake_lever.png')
this.loader.add('btn_circle.png', 'images/btn_circle.png')
this.loader.load()
//加载完成
this.loader.onComplete.add(() => {
this.show()
})
绘画出车架和刹车把手
先把给个部位画出来,这里面有个小小点:谁最后addchild到容器中,谁的层级相对较高。
//创建容器
const bikeContainer = new PIXI.Container()
bikeContainer.scale.x = bikeContainer.scale.y = 0.3
//加载车架资源并且添加进容器中
const bikeImage = new PIXI.Sprite(
this.loader.resources['brake_bike.png'].texture
)
bikeContainer.addChild(bikeImage)
//加载刹车并且添加进容器中
const bikeLeverBarImage = new PIXI.Sprite(
this.loader.resources['brake_lever.png'].texture
)
bikeContainer.addChild(bikeLeverBarImage)
//修改刹车的中心点和x,y轴的位置
bikeLeverBarImage.pivot.x = 455
bikeLeverBarImage.pivot.y = 455
bikeLeverBarImage.x = 722
bikeLeverBarImage.y = 900
//加载车把手并且添加进容器中
const bikeHanderBarImage = new PIXI.Sprite(
this.loader.resources['brake_handlerbar.png'].texture
)
bikeContainer.addChild(bikeHanderBarImage)
//设置容器的位置
const resize = () => {
bikeContainer.x = window.innerWidth - bikeContainer.width
bikeContainer.y = window.innerHeight - bikeContainer.height
}
resize()
window.addEventListener('resize', resize)
this.stage.addChild(bikeContainer)
实现按钮效果
仔细上面动图,按钮是有一个波纹弹出的效果,并且点击的时候也会触发刹车,接下来我们实现一下。
createActionButton() {
/** 创建一个按钮容器 */
let actionButton = new PIXI.Container()
/** 获取到按钮容器里面的元素 */
let btnImage = new PIXI.Sprite(this.loader.resources['btn.png'].texture)
let btnCircle = new PIXI.Sprite(
this.loader.resources['btn_circle.png'].texture
)
let btnCircle2 = new PIXI.Sprite(
this.loader.resources['btn_circle.png'].texture
)
/** 在按钮容器添加元素 */
actionButton.addChild(btnImage)
actionButton.addChild(btnCircle)
actionButton.addChild(btnCircle2)
/** 按钮容器里面的元素设置位置 */
btnImage.pivot.x = btnImage.pivot.y = btnImage.width / 2
btnCircle.pivot.x = btnCircle.pivot.y = btnCircle.width / 2
btnCircle2.pivot.x = btnCircle2.pivot.y = btnCircle2.width / 2
/** 按钮容器里面元素设置动画 */
btnCircle.scale.x = btnCircle.scale.y = 0.8
gsap.to(btnCircle.scale, { duration: 1, x: 1.3, y: 1.3, repeat: -1 })
gsap.to(btnCircle, { duration: 1, alpha: 1, alpha: 0, repeat: -1 })
this.stage.addChild(actionButton)
return actionButton
}
}
给按钮添加事件,加入刹车片的动效,这就有刹车的感觉了
actionButton.on('mousedown', () => {
gsap.to(bikeLeverBarImage, {
duration: 0.1,
rotation: (Math.PI / 180) * -30
})
})
actionButton.on('mouseup', () => {
gsap.to(bikeLeverBarImage, {
duration: 0.3,
rotation: 0
})
})
车辆启动的粒子效果
接下来就到了最有意思的环节,先看看上面动图,看看那些线条是如何动的。
- 粒子 有多个颜色
- 向某一个角度持续移动
- 超出边界后回到顶部继续移动
- 按住鼠标停止的时候会有一点回弹的效果
- 松开鼠标继续
创建🌰(粒子)容器和对象数组
//创建粒子容器
let particleContainer = new PIXI.Container()
this.stage.addChild(particleContainer)
//对象数组
let particles = []
//粒子颜色
const colors = [0xf1cf54, 0xb5cea8, 0xf1cf54, 0x818181, 0x000000]
//遍历创建多个
for (let i = 0; i < 20; i++) {
let gr = new PIXI.Graphics()
//随机🌰颜色
gr.beginFill(colors[Math.floor(Math.random() * colors.length)])
gr.drawCircle(0, 0, 6)
gr.endFill()
//存储到对象数组中
let pItem = {
sx: Math.random() * window.innerWidth,
sy: Math.random() * window.innerHeight,
gr
}
gr.x = pItem.sx
gr.y = pItem.sy
particleContainer.addChild(gr)
particles.push(pItem)
}
让🌰(粒子)动起来
我们只需要旋转粒子的容器,控制粒子y轴向下移动就可以了。
//设置容器
particleContainer.pivot.x = window.innerWidth / 2
particleContainer.pivot.y = window.innerHeight / 2
particleContainer.x = window.innerWidth / 2
particleContainer.y = window.innerHeight / 2
particleContainer.rotation = (35 * Math.PI) / 180
容器的位置和角度调好了,接下来就是想办法让粒子一直动,根本停不来的那种~。设置一个速度初始值,这样就能感受到由快到慢的感觉了。还有大家发现没,粒子刚开始是圆体慢慢的变成线条,是怎么实现的,其实非常简单,我们只需要球体的y轴拉长,x轴变扁就实现了。
let speed = 0 //初始值
function loop() {
speed += 0.5
speed = Math.min(speed, 20)
for (let i = 0; i < particles.length; i++) {
let pItem = particles[i]
pItem.gr.y += speed
if (speed >= 20) {
//y轴拉长,x轴变扁
pItem.gr.scale.y = 20
pItem.gr.scale.x = 0.05
}
//超出屏幕,回到顶部,继续动
if (pItem.gr.y > window.innerHeight) pItem.gr.y = 0
}
}
function start() {
speed = 0
gsap.ticker.add(loop)
}
gsap.ticker.add(loop)
让🌰(粒子)暂停
让粒子暂停,回到圆体状态,并且有回弹效果
function pause() {
gsap.ticker.remove(loop)
for (let i = 0; i < particles.length; i++) {
let pItem = particles[i]
//回到圆体状态
pItem.gr.scale.y = 1
pItem.gr.scale.x = 1
//回弹效果
gsap.to(pItem.gr, {
duration: 0.6,
x: pItem.sx,
y: pItem.sy,
ease: 'elastic.out'
})
}
}
🌰(粒子)效果加入按钮事件中
actionButton.on('mousedown', () => {
pause()
})
actionButton.on('mouseup', () => {
start()
})
好了,这样就完成了,是不是发现很简单也很有意思。
demo地址:github.com/qwerlp/YCY-…
在公众号里搜 大帅老猿,在他这里可以学到很多东西