这居然是你做的第一个动效|猿创营

1,835 阅读2分钟

前言

灵感来自国外一个自行车的刹车动效,利用PIXIJS性能比较好的HTML5创意引擎,还有图形渲染引擎gsap的老牌引擎用于实现丝滑的动效。下面是我在制作流程: 代码地址

bcd55d1e2395432cbb5024e8b80ec61b_tplv-k3u1fbpfcp-zoom-crop-mark_3024_3024_3024_1702.webp

初始化一个PIXI应用场景并加载图片资源


class BrakeBanner{
	constructor(selector){
		this.app = new PIXI.Application({
			widtd: window.innerWidth,
			height: window.innerHeight,
			backgroundColor: 0xffffff,
			resizeTo: window
		})
		document.querySelector(selector).appendChild(this.app.view)
		this.stage = this.app.stage
		// create PIXI loader
		this.loader = new PIXI.Loader();
		// load more static images
		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.add("malu_line.png", "images/malu_line.png");
		
		// load
		this.loader.load();
		// add monitor when static files load completed 
		this.loader.onComplete.add(() =>{
			this.show();
		})
	}
     }

创建一个动效的按钮

createActionButton(){
    // create container
    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)

    // add sence
    actionButton.addChild(btnImage);
    actionButton.addChild(btnCircle);
    actionButton.addChild(btnCircle2);
    
    // get center of circle
    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.scale, { duration: 1, alpha: 0, repeat: -1})
    return actionButton;
}

添加刹车把手,单车架

actionButton.x = actionButton.y = 300;
const bikeContainer = new PIXI.Container();
this.stage.addChild(bikeContainer)

bikeContainer.scale.x = bikeContainer.scale.y = 0.3;

// bikeContainer.scale.x = bikeContainer.scale.y = 0.3;
const bikeImage = new PIXI.Sprite(this.loader.resources['brake_bike.png'].texture);
bikeContainer.addChild(bikeImage)

const bikeLeverImage = new PIXI.Sprite(this.loader.resources['brake_lever.png'].texture);
bikeContainer.addChild(bikeLeverImage)

bikeLeverImage.pivot.x = 455;
bikeLeverImage.pivot.y = 455;
		
bikeLeverImage.x = 722;
bikeLeverImage.y = 900;
const bikeHandbarImage = new PIXI.Sprite(this.loader.resources['brake_handlerbar.png'].texture);
bikeContainer.addChild(bikeHandbarImage)

添加刹车把手动效并使用GSAP加入动效

actionButton.on("mousedown", ()=>{
    // bikeLeverImage.rotation = Math.PI/180*-30;
    gsap.to(bikeLeverImage,{ duration:.6, rotation:Math.PI/180*-30})
    // gsap.to(bikeLeverImage,{duration:.6,rotation : Math.PI/180*-35});
    
});
actionButton.on("mouseup", ()=>{
    // bikeLeverImage.rotation = 0;
    gsap.to(bikeLeverImage, {duration: .6, rotation: 0})
    
});

需要将车体固定位置

let resize = () =>{
    bikeContainer.x = window.innerWidth - bikeContainer.width;
    bikeContainer.y = window.innerHeight - bikeContainer.height;
}
window.addEventListener('resize', resize)
resize();

接下来实现速度的粒子效果

首先创建粒子的容器并填充颜色

let particles = [];
const colors = [0xf1cf54, 0xb5cea8, 0xf1cf54, 0x818181, 0x000000];
for(let i=0;i<10;i++){
    let gr = new PIXI.Graphics();
    let randomColor = Math.floor(Math.random()*colors.length)
    gr.beginFill(colors[randomColor]);
    gr.drawCircle(0, 0, 6);
    gr.endFill();

    let pItem = {
        sx: Math.random()*window.innerWidth,
        sy: Math.random()*window.innerHeight,
        gr: gr
    }

    gr.x = pItem.sx;
    gr.y = pItem.sy;

    particleContainer.addChild(gr);
    particles.push(pItem)
}

接着实现粒子的移动添加一个速度

let speed = 0;
function loop(){
    speed += .5;
    speed = Math.min(speed, 20);
    for(let i=0; i< particles.length;i++){
        let pItem = particles[i];
        // pItem.gr.y += 10;
        pItem.gr.y +=speed;
        if(speed>=20) { // since slow to fast
            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;
    // gasp.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.y += 10;
        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:'eelastic.out'})

    }
}

actionButton.on("mousedown", ()=>{
    // bikeLeverImage.rotation = Math.PI/180*-30;
    gsap.to(bikeLeverImage,{ duration:.6, rotation:Math.PI/180*-30})
    // gsap.to(bikeLeverImage,{duration:.6,rotation : Math.PI/180*-35});
    pause();
});
actionButton.on("mouseup", ()=>{
    // bikeLeverImage.rotation = 0;
    gsap.to(bikeLeverImage, {duration: .6, rotation: 0})
    start();
});

总结

跟着大帅老猿学习这个动画效果其实蛮有趣的,也学习到除工作以外的其他知识点,加油!!!

公众号里搜 大帅老猿,他做技术外包很靠谱