用PIXI+GSAP仿写刹车动画效果| 猿创营

1,106 阅读3分钟

完成效果图

bike.gif 动效分三部分(开头好潦草啊,后面补吧)

  1. 水波纹效果
  2. 刹车
  3. 粒子运动

什么是PIXIJS

PixiJS是一个轻量级的2D渲染引擎,它能自动侦测使用WebGL还是Canvas来创建图形。开发者无需专门学习 WebGL 就能感受到强大的硬件加速的力量。
pixi应用对象的成员

成员类型描述
app.loaderPIXI.Loader加载器实例用于资源加载,用于加载静态资源。
app.resizeToWindow|HTMLElement元素或窗口尺寸更改
app.screenPIXI.Rentangle渲染器的屏幕矩形对象
app.stagePIXI.Container根显示容器,舞台,pixi创建的根容器。游戏中的精灵或容器都要添加到舞台上才能显示。
app.tickerPIXI.Ticker计时器,可理解为每次渲染一帧前执行。
app.viewHTMLCanvasElement渲染器的canvas元素,pixi创建的DOM元素即用于渲染游戏的canvas。

BrakeBanner类的构建

创建画布,将画布加入dom中

        //创建一个PIXI应用程序
	this.app = new PIXI.Application({
			width: window.innerWidth,
			height: window.innerHeight,
			backgroundColor: 0xffffff,
			resizeTo: window
		})
        document.querySelector(selector).appendChild(this.app.view)

预加载图片

                this.stage = this.app.stage;
		this.loader = new PIXI.Loader()

		this.loader.add("btn.png", "images/btn.png");
		this.loader.add("btn_circle.png", "images/btn_circle.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.load();

加载完成后

                this.loader.onComplete.add(() => {
			this.show()
		})

按钮水波纹

加载素材(按钮,水波纹)

                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);
  • 通过pivot设置远点,这里将原点设置在图片的中心位置
  • scale 将图片等比缩放
  • alpha 设置视图的透明度

gsap.to(targets, vars)

产生从初始位置(或状态)到目标位置(或状态)的动画
targets: 产生动画的对象
vars: 目标状态参数

	        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;
		actionButton.x = actionButton.y = 400;

		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: 0, repeat: -1 });

完成按钮的创建

               this.stage.addChild(actionButton)

添加刹车效果

添加自行车其他部分素材

                const bikeContainer = new PIXI.Container();
		this.stage.addChild(bikeContainer);
                
		bikeContainer.scale.x = bikeContainer.scale.y = 0.3
		const bikeImage = new PIXI.Sprite(this.loader.resources["brake_bike.png"].texture)
		bikeContainer.addChild(bikeImage);
                
		const bikeLeverlImage = new PIXI.Sprite(this.loader.resources["brake_lever.png"].texture)
		bikeContainer.addChild(bikeLeverlImage);
		bikeLeverlImage.pivot.x = 455
		bikeLeverlImage.pivot.y = 455
		bikeLeverlImage.x = 722
		bikeLeverlImage.y = 900
                //刹车
		const bikeHandlerBarImage = new PIXI.Sprite(this.loader.resources["brake_handlerbar.png"].texture)
		bikeContainer.addChild(bikeHandlerBarImage);
  • interactive有交互的元素一定要设interactive属性为true,否则[监听]的事件都将无反应。
  • buttonMode属性,默认为false,设置为true时,鼠标悬浮会变成手型。或者可以直接设置cursor来修改光标样式
                actionButton.interactive = true;
		//小手
		actionButton.buttonMode = true;
		//刹车
		actionButton.on("mousedown", () => {
			// bikeLeverlImage.rotation = Math.PI / 180 * - 30
			gsap.to(bikeLeverlImage, { duration: 0.6, rotation: Math.PI / 180 * - 30 })
			pause()
		})
		actionButton.on("mouseup", () => {
			// bikeLeverlImage.rotation = 0;
			gsap.to(bikeLeverlImage, { duration: .6, rotation: 0 })
			start()
		})

对应的开始,暂停

app.ticker PIXI.Ticker 计时器,可理解为每次渲染一帧前执行。

               function start() {
			speed = 0		
		}
		function pause() {
			gsap.ticker.remove(loop)		
		}

粒子运动效果

粒子运动特点:

  • 粒子的粒子有多个颜色
  • 粒子向某个角度持续移动
  • 超出边界后回到顶部持续移动
  • 按住鼠标停止
  • 停止的时候还有回弹效果
  • 松开鼠标继续

创建一块画布,粒子的运动轨迹是某个角度的持续运动,可以设置画布旋转一定的角度,从而实现粒子的固定角度运动

                let particleContainer = new PIXI.Container()
		this.stage.addChild(particleContainer)

		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
		let particles = []
		let colors = [0xf1c54, 0xb5cea8, 0xf1cf54, 0x818181, 0x000000]
		for (let i = 0; i < 10; 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() * innerWidth,
				sy: Math.random() * innerHeight,
				gr: gr
			}
			gr.x = pItem.sx;
			gr.y = pItem.sy;
			particleContainer.addChild(gr)
			particles.push(pItem);
		}
  • 粒子的运动轨迹
  • 下面就是粒子如何运动
  • 初始速度为0
  • 粒子开始运动时不是无限加速,加速到一定上限后,不再加速
  • 运动超出显示区域后,粒子回归初始位置0

tip
pItem.gr.scale.y = 40
pItem.gr.scale.x = 0.03 通过设置高速模式下粒子的运动样式,展示动态情况下的效果

                let speed = 0
		function loop() {
			speed += .5
			speed = Math.min(speed, 20)
			for (let i = 0; i < particles.length; i++) {
				const pItem = particles[i];
				pItem.gr.y += speed;

				if (speed >= 20) {
					pItem.gr.scale.y = 40
					pItem.gr.scale.x = 0.03
				}


				if (pItem.gr.y > window.innerHeight) {
					pItem.gr.y = 0
				}

			}
		}

修改开始和暂停函数,实现点击刹车的速度动画

                function start() {
			speed = 0
			gsap.ticker.add(loop)
		}
		function pause() {
			gsap.ticker.remove(loop)
			for (let i = 0; i < particles.length; i++) {
				const pItem = particles[i];
				// pItem.gr.y += speed;

				pItem.gr.scale.y = 1
				pItem.gr.scale.x = 1


				gsap.to(pItem.gr, { duration: .6, x: pItem.sx, y: pItem.sy, ease: 'elastice.out' })

			}
		}

结尾:

附上源码地址YCY-TrainingCamp-S1
公众号里搜 大帅老猿,他做技术外包很靠谱