本红包雨项目是基于HTML5的游戏框架Phaser写的,最终形成的是一个canvas,所以性能很好,但是必须要说的是这个框架比较大,压缩后也有700K左右,所以请慎用.

代码地址: https://github.com/AmosXu/red-packet-rain

1. 效果展示

万码学堂,电脑培训,计算机培训,Java培训,JavaEE开发培训,青岛软件培训,软件工程师培训  万码学堂,电脑培训,计算机培训,Java培训,JavaEE开发培训,青岛软件培训,软件工程师培训   万码学堂,电脑培训,计算机培训,Java培训,JavaEE开发培训,青岛软件培训,软件工程师培训  万码学堂,电脑培训,计算机培训,Java培训,JavaEE开发培训,青岛软件培训,软件工程师培训

  

 图片依次是倒计时页面,抢红包页面,拆红包页,红包展示页,这些页面都是写在一个canvas里面的,无刷新的切换效果,性能超级棒

 

2.代码展示

  贴上主要的代码js代码和注释

万码学堂,电脑培训,计算机培训,Java培训,JavaEE开发培训,青岛软件培训,软件工程师培训

  
  //初始化图片
  let imgjishi = 'assets/img/daojishi.png'
  let bgPlan = 'assets/img/bg-plan.jpg'
  let bgRainer = 'assets/img/bg-rainer.jpg'
  let redpacket = 'assets/img/redpacket.png'
  let close = 'assets/img/close.png'
  let dialogExit = 'assets/img/dialog-exit.png'
  let buttonCancel = 'assets/img/button-cancel.png'
  let buttonExit = 'assets/img/button-exit.png'
  let openRedpacket = 'assets/img/open-redpacket.png'
  let open = 'assets/img/open.png'
  let redpacketResult = 'assets/img/redpacket-result.png'
  let buttonUseTicket = 'assets/img/button-use-ticket.png'
  let buttonContinue = 'assets/img/button-continue.png'
  let cursorAnimation = 'assets/img/cursor-animation.png'

  let states = {}
  let QingLvGroup;
  let hitNum = 0;
  let config = {
      selfPool:40,
      selfPic:'redpacket',
      rate:0.5,
      maxSpeed:1200,
      minSpeed:400,
      max:95
  }

  let ids = [0, 1, 2, 3, 4, 5]
  let redpackets = ['全场优惠50元', '20元代金券', '全场优惠50元', '20元代金券', '全场优惠50元', '20元代金券']
  let time = 25;
  let getIds = []
  let radio = document.documentElement.clientWidth/375;  let e;  function rfuc(n){    return n*radio;
  }  //初始化红包
  function QingLv(config, game){    this.init = function(){        this.config = config;
        QingLvGroup = game.add.group();
        QingLvGroup.enableBody = true;
        QingLvGroup.createMultiple(config.selfPool, config.selfPic); //初始化多个红包
        QingLvGroup.setAll('anchor.y',1)
        QingLvGroup.setAll('outOfBoundsKill', true);
        QingLvGroup.setAll('checkWorldBounds', true);        this.maxWidth = game.width + 300;

        game.time.events.loop(Phaser.Timer.SECOND * config.rate, this.createQL, this);
    };    this.createQL = function(){
        e = QingLvGroup.getFirstExists(false);        
        if(e) {            if(hitNum >= config.max) {                return;
            }
            hitNum++;
            e.events.onInputDown.removeAll();            var ram= Math.random();
            ram =ram<0.5?ram+=0.5: ram;
            e.loadTexture(this.config.selfPic)
            e.alpha = 1;
            e.angle = 30            // e.scale.setTo(rfuc(ram));
            e.reset(game.rnd.integerInRange(100, this.maxWidth), 100)  //红包生成的位置
            e.body.velocity.x = game.rnd.integerInRange(-300, -150);   //红包移动的速度
            e.body.velocity.y = game.rnd.integerInRange(config.minSpeed, config.maxSpeed);
            e.inputEnabled = true;
            e.events.onInputDown.add(this.hitted, this)
        }
    };    this.hitted = function(sprite){        if(Math.random() < 1/4 && ids.length > 0) {          sprite.kill();          
          //点击获得红包,游戏暂停
          game.paused = true;          //背景
          let hexGraphics = new Phaser.Graphics().beginFill(0x000000, 0.5).drawRect(0,0,document.documentElement.clientWidth,document.documentElement.clientHeight + 2);
          let pausedMask = game.add.sprite(0, 0, hexGraphics.generateTexture())
          
          let openDialog = game.add.sprite(rfuc(62), rfuc(150), 'openRedpacket')
          
          let open = game.add.sprite(rfuc(130), rfuc(300), 'open')
          open.inputEnabled = true;
        
          let result = game.add.sprite(rfuc(0), rfuc(120), 'redpacketResult')
          result.visible = false

          let userTicket = game.add.sprite(rfuc(78), rfuc(445), 'buttonUseTicket')
          userTicket.visible = false

          let goOn = game.add.sprite(rfuc(198), rfuc(445), 'buttonContinue')
          goOn.visible = false

          let ticketText = {};
          let link = ''          
          //拆红包
          let clickOpen = function() {            //游戏暂停时,点击事件无效,只能通过这种画热点的形式来绑定事件
            let openRect = new Phaser.Rectangle(rfuc(130), rfuc(315), 239, 239).copyFrom(open);            if (openRect.contains(game.input.x, game.input.y)) {
              let currentWidth = open.width              //拆红包动画
              let tempArr = [2, 4, 8, 4, 2, 1]
              let index = 0;
              let timer = setInterval(function() {                if (index > tempArr.length-1) { index = 0 }
                open.width = currentWidth / tempArr[index]
                open.height = open.height
                open.left = game.world.centerX - open.width / 2
                ++index
              }, 200)
              game.input.onDown.remove(clickOpen, this);
              let arrIndex = Math.floor(Math.random() * ids.length)
              let redpacketId = ids.splice(arrIndex, 1)
              getIds.push(redpacketId[0])

              setTimeout(()=> {
                timer && clearInterval(timer)
                document.getElementById('audioOpen').play()
                let text = redpackets[redpacketId[0]]
                ticketText = game.add.text(0, rfuc(338), text, {fill: '#ffe67d', fontSize: '46px', fontWeight: 'bolder'})
                ticketText.left = game.world.centerX - ticketText.width / 2    //文字相对于屏幕左右居中
                openDialog.visible = false
                open.visible = false
                result.visible = true
                userTicket.visible = true
                goOn.visible = true
                game.input.onDown.add(clickButton, this)
              }, 1000)
            } 
          };

          let clickButton = function() {
            let userTicketRect = new Phaser.Rectangle(rfuc(78), rfuc(445), 194, 66).copyFrom(userTicket);
            let continueRect = new Phaser.Rectangle(rfuc(198), rfuc(445), 194, 66).copyFrom(goOn);            if (userTicketRect.contains(game.input.x, game.input.y)) {
              window.location.replace(link)
              game.input.onDown.remove(clickButton, this);

            } else if (continueRect.contains(game.input.x, game.input.y)) {
              result.visible = false
              userTicket.visible = false
              goOn.visible = false
              pausedMask.visible = false
              ticketText.visible = false
              game.paused = false
              game.input.onDown.remove(clickButton, this);
            }
          }

          game.input.onDown.add(clickOpen, this)
        } else {
          sprite.inputEnabled = false;          var anim = sprite.animations.add(config.selfPic);
          sprite.play(config.selfPic, 40, false);
          anim.onComplete.add(this.fade, this, sprite)  
        }
    };    this.fade = function(sprite){        var tween = game.add.tween(sprite).to({alpha:0}, 300, 'Linear', true)
        tween.onComplete.add(this.killed, this, sprite);
    };    this.killed = function(sprite){
        sprite.kill();
    }
  }
  states.boot = function(game) {    this.preload = function() {        if (typeof(GAME) !== "undefined") {            this.load.baseURL = GAME + "/";
        }        if (!game.device.desktop) {            this.scale.scaleMode = Phaser.ScaleManager.EXACT_FIT;            this.scale.forcePortrait = true;            this.scale.refresh();
        }
    };    this.create = function() {
        game.stage.backgroundColor = '#FFF';
        game.state.start('preload');
    };
  };
  states.preload = function(game) {      this.preload = function(game) {          //加载图片
          game.load.spritesheet('daojishi', imgjishi, 250,120, 4)
          game.load.image('bgPlan', bgPlan)
          game.load.image('bgRainer', bgRainer)
          game.load.spritesheet('redpacket', redpacket, 144, 173, 2)
          game.load.image('close', close)
          game.load.image('dialogExit', dialogExit)
          game.load.image('buttonExit', buttonExit)
          game.load.image('buttonCancel', buttonCancel)
          game.load.image('openRedpacket', openRedpacket)
          game.load.image('open', open)
          game.load.image('redpacketResult', redpacketResult)
          game.load.image('buttonContinue', buttonContinue)
          game.load.image('buttonUseTicket', buttonUseTicket)
          game.load.spritesheet('cursorAnimation', cursorAnimation, 74, 108, 2)
      };      this.create = function() {
          game.state.start('main');
      };
  };
  states.main = function(game) {      this.create = function() {          // 物理系统          game.physics.startSystem(Phaser.Physics.ARCADE);          // 背景图
          var bgPlan = game.add.sprite(0, 0, 'bgPlan');
          bgPlan.width = game.width;
          bgPlan.height = game.height;          var cursorPointer = game.add.sprite(game.world.centerX - 36, game.world.centerY + 86, 'cursorAnimation');          var anim = cursorPointer.animations.add('cursorAnimation');
          cursorPointer.play('cursorAnimation', 2, true);

          document.getElementById('audioCountDown').play()          // 开始游戏倒计时
          var daojishi = game.add.sprite(game.world.centerX - 140, game.world.centerY - 400, 'daojishi');          var anim = daojishi.animations.add('daojishi');
          daojishi.play('daojishi', 1, false);
          anim.onComplete.add(this.startGame, this, daojishi);
      };      
      this.startGame = function(daojishi){          this.leftTime = time
          let bgRainer = game.add.sprite(0, 0, 'bgRainer');
          bgRainer.width = game.width;
          bgRainer.height = game.height;
          daojishi.visible = false;          this.createQingLv();          //添加按钮,并绑定事件
          let closeImg = game.add.button(rfuc(20), rfuc(20), 'close', function(){
            game.paused = true
            pausedMask.visible = true
            exitDialog.visible = true
            exitButton.visible = true
            cancelButton.visible = true

 代码地址: https://github.com/AmosXu/red-packet-rain

http://www.cnblogs.com/mianbaodaxia/p/7095782.html