canvas动效开发,PIXI+GSAP仿写vanmoof刹车动效|猿创营

926 阅读2分钟

一.前言

hello,大家好,我是嬛,一位技术平平无奇的程序媛.前公司做营销活动也接触过一点canvas动效,canvas画海报,phaser写过简单的小游戏...最近2年一直在做后台管理系统,这块基本上就丢了 ...恰好大帅老师组织这个全员实训活动,借着这个机会重新学习下canvas动效

如果觉得这篇文章对您有帮忙,小伙伴们点个赞吧.笔芯~

二.最终实现效果

MYXJ_20220713175411381_fast.gif

三.相关资料

四.动手实现

1.创建一个html,引入pixi和gsap
<html>
  <head>
    <title>猿创营</title>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width,minimum-scale=1.0,user-scalable=no"
    />
    <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>
2.创建画布
//设置画布宽高以及颜色,将其插入到Dom节点brakebanner上
this.app = new PIXI.Application({
  width: window.innerWidth,
  height: window.innerHeight,
  backgroundColor: 0xffffff,
  resizeTo: window,
});
document.querySelector(selector).appendChild(this.app.view);
3.加载图片资源
 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() //资源加载完成后的回调事件
 })
4.加入按钮容器,实现按钮特效

等待资源文件加载完成后我们需要在show的方法里面添加回调事件。

首先我们需要实现按钮的特效。如图:

MYXJ_20220713175648747_fast.gif

  creatActionButton() {
    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: 0, repeat: -1 });
    
    actionButton.x = actionButton.y = 300;
    return actionButton;
  }
5.加入车身和把手
   //创建bikeContainer容器
    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)
    bikeImage.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 bikeHandlerbarImage = new PIXI.Sprite(this.loader.resources['brake_handlerbar.png'].texture)
​
    bikeContainer.addChild(bikeHandlerbarImage)
    
    //设置bikeContainer容器始终在可视窗口内
    let resize = () => {
        bikeContainer.x = window.innerWidth - bikeContainer.width
        bikeContainer.y = window.innerHeight - bikeContainer.height
    }
​
    window.addEventListener('resize', resize)
    resize()
6.创建粒子,实现粒子特效
    //创建粒子
        let particleContainer = new PIXI.Container()
        this.stage.addChild(particleContainer)
​
        particleContainer.pivot.x = window.innerWidth / 2
        particleContainer.pivot.y = window.innerHeight / 2particleContainer.x = window.innerWidth / 2
        particleContainer.y = window.innerHeight / 2particleContainer.rotation = 35*Math.PI /180
​
        let particles = []
        const colors = [0xf1cf54, 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() * 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 += 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;
            }
​
        }
7.实现点击按钮的动画效果
    //interactive - 可交互的
    actionButton.interactive = true
    //buttonMode设置为true时,cursor会设置为pointer 鼠标会设置为小手指的样子
    actionButton.buttonMode = true
    
    actionButton.on('mousedown', ()=> {
      //设置车把手反方向旋转30度
      gsap.to(bikeLeverImage, {duration: .6, rotation: Math.PI/180* -30})
       pause()
    })
    actionButton.on('mouseup',()=>{
      //设置车把手角度重置为0
       gsap.to(bikeLeverImage,{duration: .6,rotation: 0})
        start()
    })
        
     function start(){
        speed = 0;
        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:.6,x:pItem.sx,y:pItem.sy,ease:'elastic.out'});
        }       
    }
    start();
​

五.最后

最终代码实现:地址

最后给大家安利下大帅老师,一个热爱编程、喜欢分享的技术大佬

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