开发H5项目,有时会遇到一个需求,需要制作抢红包,或者下红包雨的网页,这个实现步骤,如果拿现成的改来做是容易的,但是想着全靠自己做是不容易的,接下来开始讲,想不想自己做,有把握学到吗

目录一览

  • 1. 设计网页
  • 2. 编写脚本
  • 3. 编写模块
  • 4. 实现方法
    • 1. 绘制红包和钱袋子
    • 2. 下红包雨
    • 3. 移动钱袋子
  • 5.运行效果

1. 设计网页


首先创建一个网页文件,例如index.html,制作下红包雨的页面,源代码如下,通过修改样式<style>里设置好背景色,还有组件要填充到全屏,再加一个开始按钮(按钮可以不要,自动开始吧),写好大概逻辑,还有需要调用的一些方法

<!DOCTYPE html>
<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Red packet rain</title><style>html{height: 100%;}body{margin: 0;height: 100%;}#box{width: 100%;height: 100%;background: linear-gradient(#f00,#fff);}.float-box{position: absolute;left: 0;top: 0;right: 0;color: #fff;text-align: center;padding: 20px;}</style></head><body><div class="float-box"><span id="timer"></span></div><div id="box"></div><script type="module">import RedPacketRain from './red_packet_rain.js';window.onload=()=>{//加载脚本的处理逻辑...}</script></body>
</html>

2. 编写脚本

接着,写一个加载脚本的处理逻辑,代码如下,使用RedPacketRain对象创建前,需要先引用一个模块

const elemTimer = document.getElementById('timer');new RedPacketRain({id:'box',success:res=>{                       res.onStart();let time=10;//这个是倒计时,单位slet timer = setInterval(()=>{elemTimer.innerText = `距离结束还有${time--}s`;if (time<0){clearInterval(timer);res.onStop({success:(res)=>{alert('游戏结束,\n钱袋有¥'+res.money)}});}},1000);}
},window);

3. 编写模块

接下来,看上面有引用的一个模块文件red_packet_rain.js,没有的就把它新建好,在一个模块中去实现上面未实现的调用方法,代码如下

export default class RedPacketRain{constructor(conf,window){// 这里做一些初始化的工作...}
}

4. 实现方法

接下来,在初始化中去写方法的实现细节要复杂得多,如果看着比较吃力,就先收藏好,以后有时间慢慢摸索,边学边做

1. 绘制红包和钱袋子

在构造方法constructor()里做初始化,可以先把需要的东西,就是红包和钱袋子两个,都绘制出来,代码如下

export default class RedPacketRain{// 定义需要用到的一些私有属性#canvasCtx;#imgBg;#drawImgPurse;#drawImgRedPacket;#isContinue=false;constructor(conf,window){// 这里做一些初始化的工作...const { document } = context;if(conf.id==undefined) throw new Error('not find element id');Object.assign(conf,{redPackW:50,//红包的宽度//...});let box = document.getElementById(conf.id);let canvas = document.createElement('canvas');canvas.width = box.offsetWidth;canvas.height = Math.max(box.offsetHeight,canvas.width);const ctx = canvas.getContext('2d');ctx.textAlign = 'center';ctx.font = ctx.font.replace(/\d+/,23);//红包数据const redPack = {w: conf.redPackW,h: conf.redPackW*1.4,absX: 10,absY: 10};//钱袋子数据const purse = {w: conf.redPackW*2,h: conf.redPackW*2,x: 0,y: 0,absX: 100,absY: 10,count: 0,money: 0};//清空画布方法const drawClearEmpty = ()=>{ctx.clearRect(0,0,canvas.width,canvas.height);};//绘制红包方法const drawRedPacket = (x,y)=>{//绘制红包形状let r = redPack.w*0.1;ctx.fillStyle='#f00';ctx.strokeStyle='#333';ctx.beginPath();ctx.arc(x+r,y+r,r,Math.PI,-0.5*Math.PI);let x2 = x+redPack.w;ctx.lineTo(x2-r,y);ctx.arc(x2-r,y+r,r,-0.5*Math.PI,0);let y2 = y+redPack.h;ctx.lineTo(x2,y2-r);ctx.arc(x2-r,y2-r,r,0,0.5*Math.PI);ctx.lineTo(x+r,y2);ctx.arc(x+r,y2-r,r,0.5*Math.PI,Math.PI);ctx.closePath();ctx.fill();//绘制盖子let centerX = x+redPack.w/2;let centerY = y-redPack.w*0.6;ctx.save();ctx.clip();ctx.arc(centerX,centerY,redPack.w,-0.5*Math.PI,1.5*Math.PI);ctx.stroke();ctx.restore();//绘制盖子纽扣centerY = y+redPack.w*0.4;ctx.fillStyle='#991';ctx.beginPath();ctx.arc(centerX,centerY,redPack.w*0.15,0,2*Math.PI);ctx.fill();ctx.stroke();//绘制纽扣中间r = redPack.w*0.05;ctx.fillStyle='#000';ctx.beginPath();ctx.rect(centerX-r,centerY-r,2*r,2*r);ctx.fill();};//绘制钱袋子方法const drawPurse = (x,y)=>{let r = purse.w/2;let centerX = x + r;let centerY = y + purse.h-conf.redPackW*0.8;//绘制袋子容器形状ctx.fillStyle='#f55';ctx.beginPath();ctx.arc(centerX,centerY,r,0,2*Math.PI);ctx.fill();ctx.stroke();//绘制袋口ctx.beginPath();ctx.save();ctx.translate(-centerX*0.6,0);ctx.scale(1.6,1);ctx.arc(centerX,centerY-r*0.62,r*0.6,0,2*Math.PI);ctx.fill();ctx.stroke();ctx.beginPath();ctx.fillStyle='#333';ctx.arc(centerX,centerY-r*0.62,r*0.5,0,2*Math.PI);ctx.fill();ctx.stroke();ctx.restore();purse.h = purse.h+conf.redPackW*0.2;};//绘制袋子图片方法this.#drawImgPurse = (isSaved)=>{if(!isSaved) drawClearEmpty();ctx.drawImage(this.#imgBg,purse.absX,purse.absY,purse.w,purse.h,purse.x,purse.y,purse.w,purse.h);ctx.fillStyle='#ff5';let r = purse.w/2;ctx.fillText('¥'+purse.money.toFixed(2),purse.x+r,purse.y+(purse.h+r)*0.55,purse.w);};//绘制红包图片方法this.#drawImgRedPacket = (x,y)=>{ctx.drawImage(this.#imgBg,redPack.absX,redPack.absY,redPack.w,redPack.h,x,y,redPack.w,redPack.h);};//其它逻辑省略...//重绘方法const redraw = () => {//...};//封装上下文,开始和结束方法通过初始化完成后返回给外部调用const Context = {onStart:()=>{if(this.#isContinue) return;this.#isContinue=true;redraw();//开始时,调用重绘方法},onStop:(conf={})=>{if(!this.#isContinue) return;this.#isContinue=false;//停止后,将钱袋子的数据传给外部调用者if(typeof conf.success=='function') conf.success({count: purse.count,money: purse.money})}};//加载图片...(new Promise((resolve,reject)=>{drawRedPacket(redPack.absX,redPack.absY);drawPurse(purse.absX,purse.absY);let img = new Image();img.onload = ()=>resolve(img);img.onerror = reject;img.src = canvas.toDataURL();})).then(res=>{this.#imgBg=res;//绘制好后生成图片purse.x=(canvas.width-purse.w)/2;purse.y=canvas.height-purse.h;//接下来我们会以这个图片作为素材来绘制动画this.#drawImgPurse();if(typeof conf.success=='function') conf.success(Context);//传给外部}).catch(err=>{throw new Error(err)});this.#canvasCtx = ctx;box.appendChild(canvas); }
}

2. 下红包雨

绘制搞定了,接下来,就在重绘方法redraw()中实现红包雨效果,代码如下

export default class RedPacketRain{//...constructor(conf,window){//...Object.assign(conf,{redPackW:50,//红包的宽度refreshDelay:60,//刷新延迟 msspeedDown:10,//下落速度waitTime:20,//60*60mswaitTimeRadom:5,//紧密度moneyRadom:0.05,//随机金额最大值});//...//生成随机位置的红包const createRedPacket = () => {let padding = 10;return {x: padding + Math.trunc(Math.random()*(canvas.width-redPack.w-padding)),y: 0-redPack.h,money: 0.01 + Math.trunc(Math.random()*100*conf.moneyRadom)/100,}};//存放所有红包数据的集合const redPackets = [];redPackets.push(createRedPacket());let i=0;//重绘方法const redraw = () => {if(!this.#isContinue) return;//考虑到性能,建议每次调用window.requestAnimationFrame(()=>{this.#drawImgPurse();let outIndex=[];let x = purse.x+purse.w;let y = purse.y+purse.h;redPackets.forEach((p,index)=>{this.#drawImgRedPacket(p.x,p.y);p.y+=conf.speedDown;//判断红包是否在钱袋子上面,收红包处理一下if(p.x>purse.x && p.x+redPack.w<x && p.y>purse.y && p.y+redPack.h<y) {purse.count++;purse.money+=p.money;//将收到的红包金额加到钱袋子中outIndex.push(index);} else if(p.y>canvas.height) {outIndex.push(index);//将不再出现的红包加入标记}});outIndex.forEach(i=>redPackets.splice(i,1));//删除被标记的红包setTimeout(redraw,conf.refreshDelay);if (i>conf.waitTime){if (conf.waitTimeRadom>0) {if (Math.random()*conf.waitTimeRadom>conf.waitTimeRadom/2) {i=0;i++;return;}}redPackets.push(createRedPacket());//再生成随机红包i=0;}i++;})};//...}
}

3. 移动钱袋子

这样红包雨就能开始下了,还差个游戏互动,要实现移动钱袋子,玩家会在画布Canvas元素上按下鼠标健,我们只需要在这里加上监听事件做处理即可,代码如下

export default class RedPacketRain{//...constructor(conf,window){//...//鼠标左键按下时监听事件做处理canvas.addEventListener('mousedown',(event)=>{const { x, y } = event;if (x>purse.x && x<purse.x+purse.w) {if (y>purse.y && y<purse.y+purse.h) {purse.touch={ x:x-purse.x, y:y-purse.y };}}});//鼠标左键按下并移动时监听事件做处理canvas.addEventListener('mousemove',(event)=>{if(!purse.touch) return;const { x, y } = event;if (!(y>purse.y && y<purse.y+purse.h)) return;else if (x<purse.touch.x) return;else if (x>=canvas.width-(purse.w-purse.touch.x)) return;purse.x = x-purse.w/2;//如果是合法的左右移动,就改变钱袋子的坐标});//鼠标左键松开时监听事件做处理canvas.addEventListener('mouseup',(event)=>{if(!purse.touch) return;purse.touch=null;});//...}
}

5.运行效果

讲到最后,用浏览器打开网页index.html浏览看看,正常的话,运行效果图如下

【JavaScript】制作一个抢红包雨页面相关推荐

  1. 【web前端特效源码】使用HTML5+CSS3+JavaScript制作一个扁平化风格css螃蟹图形~~适合初学者~超简单~ |前端开发|IT软件

    b站视频演示效果: [web前端特效源码]使用HTML5+CSS3+JavaScript制作一个扁平化风格css螃蟹图形~~适合初学者~超简单~ |前端开发|IT软件 效果图: 完整代码: <! ...

  2. 【web前端特效源码】使用HTML5+CSS3+JavaScript制作一个电风扇动画效果~适合初学者~超简单~ |前端开发|IT软件

    b站视频演示效果: [web前端特效源码]使用HTML5+CSS3+JavaScript制作一个电风扇动画效果~适合初学者~超简单~ |前端开发|IT软件 效果图: 完整代码: <!DOCTYP ...

  3. 【web前端特效源码】使用HTML5+CSS3+JavaScript制作一个可拖动的拼图游戏动画效果~适合初学者~超简单~ |it前端开发

    b站视频演示效果: [web前端特效源码]使用HTML5+CSS3+JavaScript制作一个可拖动的拼图游戏动画效果~适合初学者~超简单~ |前端开发|IT软件 效果图: 完整代码: <!D ...

  4. 【web前端特效源码】使用HTML5+CSS3+JavaScript制作一个影子~~适合初学者~超简单~ |前端开发|IT软件

    b站视频演示效果: [web前端特效源码]使用HTML5+CSS3+JavaScript制作一个影子特效~~适合初学者~超简单~ |前端开发|IT软件 效果图: 完整代码: <!DOCTYPE ...

  5. html登录页面用idea,利用IDEA怎么制作一个登录注册页面

    利用IDEA怎么制作一个登录注册页面 发布时间:2020-12-19 14:02:09 来源:亿速云 阅读:186 作者:Leah 利用IDEA怎么制作一个登录注册页面?很多新手对此不是很清楚,为了帮 ...

  6. 【前端代码实例】使用HTML5+CSS3+JavaScript制作一个响应式的后台管理系统~带侧边导航栏仪表盘功能

    bilibili在线视频演示地址: [前端代码实例]使用HTML5+CSS3+JavaScript制作一个响应式的后台管理系统~带侧边导航栏仪表盘功能 效果图: 完整代码: <!DOCTYPE ...

  7. 【web前端特效源码】使用HTML5+CSS3+JavaScript制作一个果冻导航标签栏图标按钮效果~~适合初学者~超简单~ |前端开发|IT软件

    b站视频演示效果: [web前端特效源码]使用HTML5+CSS3+JavaScript制作一个果冻导航标签栏图标按钮效果~~适合初学者~超简单~ |前端开发|IT软件 效果图: 完整代码: < ...

  8. 【JavaScript】制作一个老虎机抽奖页面

    开发H5项目,有时会遇到一个需求,需要制作仿制老虎机游戏抽奖的网页,这个实现步骤,如果拿现成的改来做是容易的,但是想着全靠自己做是不容易的,接下来开始讲,想不想自己做,有把握学到吗 目录一览 1. 设 ...

  9. 用html制作一个音乐排行榜,使用原生JavaScript制作一个漂亮的音乐播放器

    简单介绍 起初在简书上发现了这篇博客--[html.css.jq]制作一个简洁的音乐播放器.这是一个用jQuery库实现的音乐播放器,界面简约大气. 我在这个基础上,反其道而行,使用原生JavaScr ...

最新文章

  1. Linux -- ***检测系统(IDS)介绍及应用(1)
  2. hdu 3449 有依赖性的01背包
  3. cannot be found on object of type xx.CacheExpressionRootObject
  4. QQ空间说说的表情添加的代码
  5. 26岁!年入100万,两周把 Github 项目推向全球榜首,他是怎么做的?
  6. 图像学习-HOG特征
  7. 小米不加入鸿蒙,是华为不给小米用鸿蒙,还是小米拒绝使用鸿蒙?
  8. Atlassian是怎样进行持续交付的?且听 Steve Smith一一道来
  9. 云南省电子计算机高级,计算机基础知识-云南省电子信息高级技工学校.ppt
  10. PAT-乙级-1031. 查验身份证(15)
  11. 苹果Mac侧边栏笔记工具:​​​​​​​​SideNotes
  12. sort()函数——C++
  13. python图像分类实验总结_第4章 图像分类(image classification)基础
  14. 如何系统的学习linux
  15. MySQL8版本 Win10忘记密码
  16. 注册跨境电商需要多少钱?还需要办理哪些事项?
  17. SQL Server 连接字符串和身份验证
  18. Java 特殊回文。123321是一个非常特殊的数,它从左边读和从右边读是一样的。输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n 。
  19. Gazebo仿真进阶教程之传感器高斯噪声(二)
  20. OVM-V1.3正式发布,新增三大功能 ,采用全新UI界面

热门文章

  1. 公司内部员工抽奖活动小工具
  2. vscode - 修改字体 、 合并字符、 使用连体字(Fira Code)
  3. cyq.data mysql_CYQ.Data 轻量数据层之路 V4.3 版本发布[增加对SQLite,MySQL数据库的支持]...
  4. 微信小程序二维for循环
  5. 员工犯错被公司开除还会发放工资吗
  6. 网络安全web方向入门题合集
  7. 学习开放而不变成陶醉的鸡
  8. 用python写一个用驼峰法来命名变量脚本
  9. 光大证券:智能家居 “双网”引擎共同驱动
  10. PDF转word、excel、PPT软件---------Adobe Acrobat DC 2019