热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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), &#39;openRedpacket&#39;)
          
          let open = game.add.sprite(rfuc(130), rfuc(300), &#39;open&#39;)
          open.inputEnabled = true;
        
          let result = game.add.sprite(rfuc(0), rfuc(120), &#39;redpacketResult&#39;)
          result.visible = false

          let userTicket = game.add.sprite(rfuc(78), rfuc(445), &#39;buttonUseTicket&#39;)
          userTicket.visible = false

          let goOn = game.add.sprite(rfuc(198), rfuc(445), &#39;buttonContinue&#39;)
          goOn.visible = false

          let ticketText = {};
          let link = &#39;&#39;
          
          //拆红包
          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(&#39;audioOpen&#39;).play()
                let text = redpackets[redpacketId[0]]
                ticketText=game.add.text(0, rfuc(338),text,{fill:&#39;#ffe67d&#39;,fontSize:&#39;46px&#39;,fontWeight: &#39;bolder&#39;})
                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, &#39;Linear&#39;, 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 = &#39;#FFF&#39;;
        game.state.start(&#39;preload&#39;);
    };
  };
  states.preload = function(game) {
      this.preload = function(game) {
          //加载图片
          game.load.spritesheet(&#39;daojishi&#39;, imgjishi, 250,120, 4)
          game.load.image(&#39;bgPlan&#39;, bgPlan)
          game.load.image(&#39;bgRainer&#39;, bgRainer)
          game.load.spritesheet(&#39;redpacket&#39;, redpacket, 144, 173, 2)
          game.load.image(&#39;close&#39;, close)
          game.load.image(&#39;dialogExit&#39;, dialogExit)
          game.load.image(&#39;buttonExit&#39;, buttonExit)
          game.load.image(&#39;buttonCancel&#39;, buttonCancel)
          game.load.image(&#39;openRedpacket&#39;, openRedpacket)
          game.load.image(&#39;open&#39;, open)
          game.load.image(&#39;redpacketResult&#39;, redpacketResult)
          game.load.image(&#39;buttonContinue&#39;, buttonContinue)
          game.load.image(&#39;buttonUseTicket&#39;, buttonUseTicket)
          game.load.spritesheet(&#39;cursorAnimation&#39;, cursorAnimation, 74, 108, 2)
      };
      this.create = function() {
          game.state.start(&#39;main&#39;);
      };
  };
  states.main = function(game) {
      this.create = function() {
          // 物理系统
          game.physics.startSystem(Phaser.Physics.ARCADE);

          // 背景图
          var bgPlan = game.add.sprite(0, 0, &#39;bgPlan&#39;);
          bgPlan.width = game.width;
          bgPlan.height = game.height;

          var cursorPointer = game.add.sprite(game.world.centerX - 36, game.world.centerY + 86, &#39;cursorAnimation&#39;);
          var anim = cursorPointer.animations.add(&#39;cursorAnimation&#39;);
          cursorPointer.play(&#39;cursorAnimation&#39;, 2, true);

          document.getElementById(&#39;audioCountDown&#39;).play()

          // 开始游戏倒计时
          var daojishi = game.add.sprite(game.world.centerX - 140, game.world.centerY - 400, &#39;daojishi&#39;);
          var anim = daojishi.animations.add(&#39;daojishi&#39;);
          daojishi.play(&#39;daojishi&#39;, 1, false);
          anim.onComplete.add(this.startGame, this, daojishi);
      };
      
      this.startGame = function(daojishi){
          this.leftTime = time
          let bgRainer = game.add.sprite(0, 0, &#39;bgRainer&#39;);
          bgRainer.width = game.width;
          bgRainer.height = game.height;
          daojishi.visible = false;
          this.createQingLv();

          //添加按钮,并绑定事件
          let closeImg = game.add.button(rfuc(20), rfuc(20), &#39;close&#39;, 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: &#39;#FFF&#39;, fontSize: &#39;40px&#39;, fontWeight: &#39;bolder&#39;})
          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), &#39;dialogExit&#39;)
          exitDialog.visible = false;

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

          let isExit = false
          let cancelButton = game.add.button(rfuc(200), rfuc(315), &#39;buttonCancel&#39;)
          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(&#39;gameScreen&#39;));
    game.state.add(&#39;boot&#39;, states.boot.bind(game));
    game.state.add(&#39;preload&#39;, states.preload.bind(game));
    game.state.add(&#39;main&#39;, states.main.bind(game));
    game.state.start(&#39;boot&#39;);
  }

3. 疑难问题

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

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

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

let userTicket = game.add.sprite(rfuc(78), rfuc(445), &#39;buttonUseTicket&#39;)        
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), &#39;我想居中&#39;, 
{fill: &#39;#ffe67d&#39;, fontSize: &#39;46px&#39;, fontWeight: &#39;bolder&#39;})
ticketText.left = game.world.centerX - ticketText.width / 2    //文字相对于屏幕左右居中

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

总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。更多相关教程请访问 HTML视频教程,Html5视频教程,bootstrap视频教程!

以上就是html5仿淘宝,京东实现红包雨效果(代码实例)的详细内容,更多请关注 第一PHP社区 其它相关文章!


推荐阅读
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • MACElasticsearch安装步骤及验证方法
    本文介绍了MACElasticsearch的安装步骤,包括下载ZIP文件、解压到安装目录、启动服务,并提供了验证启动是否成功的方法。同时,还介绍了安装elasticsearch-head插件的方法,以便于进行查询操作。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 本文介绍了Linux系统中正则表达式的基础知识,包括正则表达式的简介、字符分类、普通字符和元字符的区别,以及在学习过程中需要注意的事项。同时提醒读者要注意正则表达式与通配符的区别,并给出了使用正则表达式时的一些建议。本文适合初学者了解Linux系统中的正则表达式,并提供了学习的参考资料。 ... [详细]
  • Netty源代码分析服务器端启动ServerBootstrap初始化
    本文主要分析了Netty源代码中服务器端启动的过程,包括ServerBootstrap的初始化和相关参数的设置。通过分析NioEventLoopGroup、NioServerSocketChannel、ChannelOption.SO_BACKLOG等关键组件和选项的作用,深入理解Netty服务器端的启动过程。同时,还介绍了LoggingHandler的作用和使用方法,帮助读者更好地理解Netty源代码。 ... [详细]
author-avatar
萧阳
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有