前端动效入门,使用PIXI,GSAP来模仿vanmoof电商页面的刹车视觉动效 | 猿创营

4,664 阅读3分钟

刹车视觉动效效果展示:

shache.gif

1、设计到的技术:

PIXI:是一个非常快的2D sprite渲染引擎。这是什么意思?这意味着它可以帮助你显示、动画和管理交互式图形,这样你就可以轻松地使用JavaScript和其他HTML5技术制作游戏和应用程序。它有一个合理的,整洁的API,并包括许多有用的功能,如支持纹理地图集和提供一个精简的系统,为动画精灵(交互式图像)。它还为您提供了一个完整的场景图,这样您就可以创建嵌套精灵(精灵中的精灵)的层次结构,并允许您将鼠标和触摸事件直接附加到精灵上。而且,最重要的是,Pixi可以让您自由的使用,使其适应您的个人编码风格,并与其它框架无缝集成。

GSAP:(GreenSock Animation Platform)是一个从flash时代一直发展到今天的专业动画库。

2、实现步骤:

(1)、创建PIXI应用:

<body>
    <div id="brakebanner"></div>
</body>
 window.onload = init;
 function init() {
   let banner = new BrakeBanner("#brakebanner");
 }
 class BrakeBanner {
	constructor(selector) {
		// 使用PIXI,初始化PIXI的应用,创建画布并显示在页面上
		this.app = new PIXI.Application({
			width: window.innerWidth,
			height: window.innerHeight,
			// backgroundColor: 0xffffff,
			backgroundColor:0xf1cf54,
			resizeTo: window
		})
		//添加PIXI应用到页面中
		document.querySelector(selector).appendChild(this.app.view)
	}
}

这是开始使用Pixi所需要编写的最基本的代码。它会在你的HTML页面上生成一个黄色canvas元素。下面是在浏览器中运行这段代码时的情况。

yellow.png

没错,就是一个黄色方块!

(2)、创建加载器把所有图片加载到画布中:

 class BrakeBanner {
	constructor(selector) {
            ............//此处省略上面所写代码
            this.stage = this.app.stage;
            // 创建加载器
            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()
     }
}

(3)、加载控制刹车的按钮,下面是在浏览器中运行这段代码时的情况:

 class BrakeBanner {
	constructor(selector) {
            ............//此处省略上面所写代码
           // 添加侦听器,侦听加载资源完成的情况
            this.loader.onComplete.add(() => {
                    this.show()
            })            
     }
        //加载资源
        show() {
                let actionButton = this.createActionButton()
                actionButton.x = 400;
                actionButton.y = 400;
                this.stage.addChild(actionButton);

        }
        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,repeat: -1 无限循环
        gsap.to(btnCircle.scale, { duration: 1, x: 1.3, y: 1.3, repeat: -1 });
        // alpha设置透明度
        gsap.to(btnCircle, { duration: 1, alpha: 0, repeat: -1 });
        return actionButton;
        }
}

buttondongxiao.gif

(4)、加载车架以及车把手:

show() {
        ............//此处省略上面所写代码
        // 加载车架
        const bikeContainer = new PIXI.Container();
        this.stage.addChild(bikeContainer);
        let bikeImage = new PIXI.Sprite(this.loader.resources["brake_bike.png"].texture);
        // 缩放车架的大小
        bikeContainer.scale.x = bikeContainer.scale.y = .3
        bikeContainer.addChild(bikeImage);
        // 刹车的把手
        let bikeLeverImage = new PIXI.Sprite(this.loader.resources["brake_lever.png"].texture);
        bikeContainer.addChild(bikeLeverImage);
        bikeLeverImage.pivot.x = bikeLeverImage.pivot.y = 455
        bikeLeverImage.x = 722;
        bikeLeverImage.y = 900;
        // 车把手
        let bikeHandlerbarImage = new PIXI.Sprite(this.loader.resources["brake_handlerbar.png"].texture);
        bikeContainer.addChild(bikeHandlerbarImage);
        this.stage.addChild(actionButton);

	}

下面是在浏览器中运行这段代码时的情况:

chejia.png

(5)、刹车把手的触发事件:

show(){
         ............//此处省略上面所写代码
        // 设置按住的触发事件
        actionButton.interactive = true;
        // 鼠标移动到按住按钮上显示小手
        actionButton.buttonMode = true;
        actionButton.on("mousedown", () => {
        // 旋转刹车把手
        gsap.to(bikeLeverImage, { duration: 0.6, rotation: Math.PI / 180 * -30 })
         })
        actionButton.on("mouseup", () => {
        // 旋转刹车把手
        gsap.to(bikeLeverImage, { duration: 0.6, rotation: 0 })
        })
    }

下面是在浏览器中运行这段代码时的情况:

anzhushache_.gif

(6)、添加粒子的动效并与刹车结合起来展示:

show(){
    ............//此处省略上面所写代码
    // 设置自行车的位置一直在页面右下角
    let resize = () => {
        bikeContainer.x = window.innerWidth - bikeContainer.width
        bikeContainer.y = window.innerHeight - bikeContainer.height
    }
    window.addEventListener("resize", resize)
    resize()

    // 创建粒子容器
    let partcleContainer = new PIXI.Container();
    this.stage.addChild(partcleContainer);
    partcleContainer.pivot.x = window.innerWidth / 2;
    partcleContainer.pivot.y = window.innerHeight / 2;
    ;
    partcleContainer.x = window.innerWidth / 2;
    partcleContainer.y = window.innerHeight / 2;

    partcleContainer.rotation = 35 * Math.PI / 180;
    let partcles = [];
    let 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;
            partcleContainer.addChild(gr);
            partcles.push(pItem);
    }

    let speed = 0;
    function loop() {
        speed += 0.1;
        speed = Math.min(speed, 20)
        for (let i = 0; i < partcles.length; i++) {
                let pItem = partcles[i];
                pItem.gr.y += speed;
                if (speed >= 20) {
                        pItem.gr.scale.x = 0.03;
                        pItem.gr.scale.y = 40;
                }
                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 < partcles.length; i++) {
                    let pItem = partcles[i];
                    pItem.gr.scale.x = 1;
                    pItem.gr.scale.y = 1;
                    gsap.to(pItem.gr, { duration: .6, x: pItem.sx, y: pItem.sy, easy: "elastic.out" })
            }
	}
  start();
}

下面是在浏览器中运行这段代码时的情况:

all_.gif

3、以上就是实现刹车动效的全部步骤及代码,喜欢的小伙伴快行动起来吧。

项目源码:github.com/jianghongsh…

4、最后

公众号里搜 大帅老猿,在他这里可以学到很多东西!