您现在的位置是:群英 > 开发技术 > web开发
如何用html5写个类似淘宝红包雨的效果
Admin发表于 2022-06-24 17:50:23942 次浏览
这篇文章给大家介绍了“如何用html5写个类似淘宝红包雨的效果”的相关知识,讲解详细,步骤过程清晰,对大家进一步学习和理解“如何用html5写个类似淘宝红包雨的效果”有一定的帮助,希望大家阅读完这篇文章能有所收获。下面就请大家跟着小编的思路一起来学习一下吧。

本篇文章就给大家分享html5仿淘宝,京东实现红包雨效果的实例代码。有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助。

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

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

1. 效果展示

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

2.代码展示

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

  
  //初始化图片
  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

            game.input.onDown.add(buttonClick, this)
          }.bind(this))
          
          // 剩余时间
          this.leftTimeText = game.add.text(0, 0, this.leftTime, {fill: '#FFF', fontSize: '40px', fontWeight: 'bolder'})
          this.leftTimeText.scale.setTo(rfuc(1))
          this.leftTimeText.fixedToCamera = true;
          this.leftTimeText.cameraOffset.setTo(game.camera.width - rfuc(80), rfuc(20));

          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())
          pausedMask.visible = false;

          let exitDialog = game.add.sprite(rfuc(62), rfuc(150), 'dialogExit')
          exitDialog.visible = false;

          let exitButton = game.add.button(rfuc(80), rfuc(315), 'buttonExit')
          exitButton.visible = false;

          let isExit = false
          let cancelButton = game.add.button(rfuc(200), rfuc(315), 'buttonCancel')
          cancelButton.visible = false;

          game.time.events.repeat(Phaser.Timer.SECOND, this.leftTime, this.refreshTime, this)

          let buttonClick = function() {
            let cancelRect = new Phaser.Rectangle(rfuc(200), rfuc(315), 194, 66).copyFrom(cancelButton);
            if (cancelRect.contains(game.input.x, game.input.y)) {
              game.input.onDown.remove(buttonClick, this)
              game.paused = false
              pausedMask.visible = false
              exitDialog.visible = false
              exitButton.visible = false
              cancelButton.visible = false
            }
          }
      };

      this.createQingLv = function(){
          this.qinglv = new QingLv(config, game);
          this.qinglv.init();
          this.qinglv = new QingLv(config, game);
          this.qinglv.init();
      };
      
      this.refreshTime = function(){
          this.leftTime--;
          var tem = this.leftTime;
          this.leftTimeText.text = tem;
          if(this.leftTime === 0) {
              game.paused = true;
          }
      }
  };

  //生成游戏
  let game = null
  if (game == null) {
    game = new Phaser.Game(document.documentElement.clientWidth, document.documentElement.clientHeight + 2, Phaser.AUTO, document.getElementById('gameScreen'));
    game.state.add('boot', states.boot.bind(game));
    game.state.add('preload', states.preload.bind(game));
    game.state.add('main', states.main.bind(game));
    game.state.start('boot');
  }

3. 疑难问题

1. 游戏暂停时,点击事件无效,需要点击,怎么解决

答: 通过全局事件画热点的形式绑定事件,一定要记得移除事件,一定一定要记得

game.input.onDown.add(clickOpen, this)   //给游戏绑定全局事件

let userTicket = game.add.sprite(rfuc(78), rfuc(445), 'buttonUseTicket')        
let userTicketRect = new Phaser.Rectangle(78, 445, 194, 66).copyFrom(userTicket);  //获得button的区域

//如果点击的位置为button的位置就执行下一步
if (userTicketRect.contains(game.input.x, game.input.y)) {
  //移除全局事件
   game.input.onDown.remove(clickButton, this);
}

2. 文字或图片相对于屏幕居中(暂时只能做屏幕居中)

答: 添加文字到游戏中,文字向左的偏移量等于游戏屏幕的宽度减去文字宽度的一般,就能达到居中的效果

ticketText = game.add.text(0, rfuc(338), '我想居中', 
{fill: '#ffe67d', fontSize: '46px', fontWeight: 'bolder'})
ticketText.left = game.world.centerX - ticketText.width / 2    //文字相对于屏幕左右居中

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


关于“如何用html5写个类似淘宝红包雨的效果”的内容就介绍到这,感谢各位的阅读,相信大家对如何用html5写个类似淘宝红包雨的效果已经有了进一步的了解。大家如果还想学习更多知识,欢迎关注群英网络,小编将为大家输出更多高质量的实用文章!

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

标签: 红包雨
相关信息推荐
2022-01-19 18:20:23 
摘要:这篇文章我们来了解Java内存泄漏和内存溢出的相关内容,内存泄漏和内存溢出分别是什么,两者有什么关系,及如何解决内存泄漏和内存溢出的问题?下面我们来详细的了解看看。
2022-05-13 17:46:25 
摘要:这篇文章主要给大家介绍了关于如何利用PHP实现上传图片功能的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2022-05-06 18:09:43 
摘要:本篇文章给大家介绍一下微信小程序自动跳转页面的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。
云活动
推荐内容
热门关键词
热门信息
群英网络助力开启安全的云计算之旅
立即注册,领取新人大礼包
  • 联系我们
  • 24小时售后:4006784567
  • 24小时TEL :0668-2555666
  • 售前咨询TEL:400-678-4567

  • 官方微信

    官方微信
Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
微信公众号
返回顶部
返回顶部 返回顶部