签到抽奖功能——常见前端抽奖需求
程序员文章站
2023-01-14 21:06:32
网站开发 ,经常需要用到登录注册,签到抽奖等模块,虽然每次都要写,但是把这个记录下来会很方便下次再用。。。 这边刚写了一个签到抽奖,放到这边来分享记录一下。 首先根据设计图 需要这样的样式与效果 这样的抽奖页面无非就是样式当前类切换的效果, 那基本逻辑就是点击抽奖后,需要做一个跑马灯的效果,并且一开 ......
网站开发 ,经常需要用到登录注册,签到抽奖等模块,虽然每次都要写,但是把这个记录下来会很方便下次再用。。。
这边刚写了一个签到抽奖,放到这边来分享记录一下。
首先根据设计图 需要这样的样式与效果
这样的抽奖页面无非就是样式当前类切换的效果, 那基本逻辑就是点击抽奖后,需要做一个跑马灯的效果,并且一开始加速然后减速到出中奖结果, 这边会用到定时器
每切换一下调用定时器,直到出来结果后清除定时器。。。展示中奖
那面贴上代码
// 调用是这样的 // 声明这个函数 用来传入后台请求获取中奖结果id的 function getid() { return math.ceil(math.random(1,8)*10) + 7; // 线下测试 随机数结果 // return ' ' // 这里是如果用户没有权限抽奖 返回的字符串 }; const lettery = new lottery(getid); //创建实例 ,传入获取中奖id的函数,前面还可以传入一个对象,里面是控制抽奖转的最低圈数与速度 //模拟后台奖品数据 const prize = [{"id":9,"title":"10个积分","type":1},{"id":10,"title":"5元优惠券","type":2}, ....] 共七组奖品 lettery.init(prize); // 初始化 , 传入奖品数据 prize
上面是如何调用这个功能 ,下面h+c实现样式,但并未做注释,样式可以自己根据需要去写,也是简单的东西,最后是js逻辑代码,有我的理解与注释
// 这边是html 字符串,放在js中,初始化的时候处理并加入页面 let lotteryhtml = ` <div id="lottery"> <div class="lottery-box"> <div class="lottery-head"> <h1><img src="../images/sign/sign-box.png" width="40" height="40">签到抽奖</h1> <div class="prize-close">x</div> </div> <div class="lottery-content"> <div class="left-light sider-light"> <i></i><i></i><i></i><i></i><i></i><i></i><i></i> </div> <div class="top-light sider-light"> <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> </div> <div class="right-light sider-light"> <i></i><i></i><i></i><i></i><i></i><i></i><i></i> </div> <div class="bottom-light sider-light"> <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> </div> <div class="prize-content"> <ul class="clearfix"> <li class="lottery-0" data-id="{ id }" data-index="0"> <img src="{ src }" alt=""> <p>{ title }</p> </li> <li class="lottery-1" data-id="{ id }" data-index="1"> <img src="{ src }" alt=""> <p>{ title }</p> </li> <li class="lottery-2" data-id="{ id }" data-index="2"> <img src="{ src }" alt=""> <p>{ title }</p> </li> <li class="lottery-7" data-index="7"> <p class="thank">谢谢参与</p> </li> <li class="lottery"> <p class="title">开始抽奖</p> <span>免费次数:<em>1</em>次</span> </li> <li class="lottery-3" data-id="{ id }" data-index="3"> <img src="{ src }" alt=""> <p>{ title }</p> </li> <li class="lottery-6" data-id="{ id }" data-index="6"> <img src="{ src }" alt=""> <p>{ title }</p> </li> <li class="lottery-5" data-id="{ id }" data-index="5"> <img src="{ src }" alt=""> <p>{ title }</p> </li> <li class="lottery-4" data-id="{ id }" data-index="4"> <img src="{ src }" alt=""> <p>{ title }</p> </li> </ul> <div class="prize-reason"> <div> <span class="close-res">x</span> <p class="res-title"></p> <img src=""> <p class="res-con"></p> <span class="res-btn">再抽一次</span> </div> </div> </div> </div> <div class="prize-bottom"> <div> <h4>抽奖说明:</h4> <p>1、 每个用户每天签到一次可获得一次抽奖机会( 抽奖机会当天有效 )</p> <p>2、 10积分抽奖一次</p> </div> </div> </div> </div> `; // css 可根据自己的需求修改 我这边是stylus 语法 // 抽奖 #lottery position fixed left 0px top 0px right 0px bottom 0px background-color rgba(0,0,0,.6) z-index 999 display none .lottery-box width 440px height 620px position absolute left 0px top 0px right 0px bottom 0px margin auto .lottery-head width 250px height 40px line-height 40px border-radius 20px background-color #353535 text-align center margin 0 auto h1 font-size 24px margin 0 color #e97424 height 40px line-height 40px img vertical-align middle margin-right 10px margin-top -20px .prize-close position absolute right -60px top -20px width 40px height 40px background-color #3f3f3f line-height 40px border-radius 50% text-align center color #fff font-size 20px cursor pointer .lottery-content position relative width 100% height 388px margin-top 20px border-radius 20px overflow hidden background-color #222 .sider-light position absolute background-color #353535 font-size 0 i display inline-block width 10px height 10px border-radius 50% box-shadow 0 0 20px rgba(204,255,255,.8) vertical-align middle animation light 1s alternate infinite; &:nth-child(2n) animation light 1s linear 1s alternate infinite; .left-light,.right-light width 24px top 24px height 332px left 0px text-align center i display block background-color #e97424 margin 0 auto 38px &:first-child margin-top 17px &:last-child margin-bottom 0 &:nth-child(2n) background-color #fdbd40 .right-light left auto right 0px .top-light,.bottom-light left 0px top 0px height 24px line-height 24px width 100% i margin-right 38px background-color #fdbd40 &:first-child margin-left 23px &:last-child margin-right 0 &:nth-child(2n) background-color #e97424 .top-light border-radius 20px 20px 0 0 .bottom-light top auto bottom 8px border-radius 0 0 20px 20px .prize-content padding 34px li float left width 120px height 100px border-radius 10px margin-right 6px margin-top 6px background-color #fff2da border 2px solid transparent box-sizing border-box cursor default text-align center &.active border-color #e97424 &:nth-child(-n+3) margin-top 0 &:nth-child(3n) margin-right 0 &:nth-child(5) background-color #e97424 cursor pointer user-select none .title font-size 23px color #fff margin-top 20px span color #ffcc00 img width 50px margin-top 10px p color #e97424 .thank line-height 100px .prize-reason position absolute width 300px height 300px left 0px top 0px right 0px bottom 0px margin auto border-radius 20px background-color #353535 overflow hidden color #fff text-align center display none &>div position relative z-index 2 &:before content "" position absolute width 200% height 200% border-radius 50% left 50% margin-left -100% top -160% background-color #222222 .close-res position absolute right 5px top 5px width 30px height 30px border-radius 50% color #fff text-align center line-height 30px background-color rgba(0,0,0,.8) cursor pointer .res-title font-size 24px line-height 60px img margin-top 20px .res-con line-height 50px height 50px font-size 22px font-weight bold &.no font-size 16px font-weight normal .res-btn display block margin 25px auto 0 width 120px height 34px line-height 34px font-size 16px color #fff background-color #fecc32 border-radius 5px cursor pointer user-select none .prize-bottom margin-top 24px background-color #222222 width 100% height 148px border-radius 20px position relative &::after,&::before content "" position absolute width 10px height 24px background-color #353535 top -24px left 130px &::after left auto right 130px div width 100% height 140px border-radius 20px background-color #353535 box-sizing border-box padding 10px 20px color #ddd line-height 2 h4 font-size 16px color #e97424 @keyframes light 0% box-shadow 0 0 5px rgba(204,255,255,.8) 100 box-shadow 0 0 20px rgba(204,255,255,.8)
上面两段是样式效果, 下面是逻辑代码了。
;(function(win, $) { //这边是用到的三张图片地址 变量没有大写。。 const pointimgsrc = '../images/sign/point.png'; const couponimgsrc = '../images/sign/coupon.png'; const thanksimgsrc = '../images/sign/thanks.png'; /** opts => object * speed 转动速度 数值越小速度越快 * cycle 最少转圈数 fn => function * return id (number) */ class lottery { constructor(fn = 0, opts = {}) { this.opts = opts; this.callbackid = fn; } //初始化 init(data = []) { // 传入奖品数据数组对象 数组长度为7 奖品id, 奖品title, 奖品类型 1,2 this.options = object.assign({}, { speed: 40, cycle: 5, }, this.opts); // 合并默认参数 // 初始一些变量 this._index = 0; // 当前转动位置 this._timer = null; // 计时器 this._count = 8; // 抽奖转动的长度 this._prize = -1; // 中奖的位置 this._times = 0; // 转动的次数 this._curid = 0; // 中奖的id 后台提供 this._speed = this.options.speed; this._cycle = this.options.cycle * 8; this._isclick = false; this._prizetype = 0; // 中奖类型 this._prizetitle; this.data = data; // 奖品数据 后台提供 this._render(); // 渲染抽奖模块 this._initevent(); //初始事件 } _render() { let html = '', i = 0, j = 0, k = 0; // 数组赋值索引参数 html += lotteryhtml .replace(/{ src }/g, (v)=>{ return prize[i++].type == 1? pointimgsrc: couponimgsrc; }) .replace(/{ title }/g, (v)=>{ return prize[j++].title; }) .replace(/{ id }/g, (v)=>{ return prize[k++].id; }) $('body').append(html); this.lotterydom = $('#lottery'); //声明dom对象 } _initevent() { this.lotterydom .on('click', '.prize-close', ()=> { this.lotterydom.hide(); }) .on('click', '.close-res', ()=> { this.lotterydom.find('.prize-reason').fadeout(); }) .on('click', '.lottery, .res-btn', this.startgame.bind(this)) } startgame() { this.lotterydom.find('.prize-reason').fadeout(); // 开始时候隐藏上次中奖结果弹出层 // 后台请求中奖id 简单处理非id 直接警告 if (typeof(this.callbackid()) == 'number') { this._curid = this.callbackid(); } else { alert(this.callbackid()); return; }; // if(this.lotterydom.find('.lottery em').text() == 1) { // 免费抽奖次数清零。 // this.lotterydom.find('.lottery em').text(0) // } if(!this._isclick) { // 抽奖动画没结束 不能再次触发 this._roll(); } } _getprizeindex() { // 这里过滤获取当前中奖结果索引 let dom = this.lotterydom.find('li').filter((i,v)=>{ return $(v).data('id') == this._curid; }) this._prizetype = dom.find('p').text().indexof('积分') > 0? 1: dom.find('p').text().indexof('优惠券') > 0? 2: 0; if(this._prizetype) { this._prizetitle = dom.find('p').text(); }; if(!dom.length) return 7; // 全都不符合返回谢谢惠顾的索引 return dom.data('index')/1; } _roll() { this._isclick = true; // 控制暴力点击 this.lotterydom.find('.lottery-'+ this._index).removeclass('active'); //每次调用 去除当前选中 this._index++; if(this._index > this._count - 1) { // 循环添加 this._index = 0; } this.lotterydom.find('.lottery-'+ this._index).addclass('active'); // 下一个添加选中 this._times ++; if(this._times > this._cycle + 10 && this._prize == this._index) { // 转动圈数超过基数+10 并且当前位置等于中奖结果位置 cleartimeout(this._timer); // 清除定时器 this._showprize(); // 展示中奖结果 } else { if(this._times < this._cycle) { // 圈数小于设置的基数 速度边快 this._speed -= 10; } else if(this._times == this._cycle) { this._prize = this._getprizeindex(); // 转动到达基数时候 获取中奖结果的索引 } else { if (this._times > this._cycle + 10 && (this._prize == 0 && this._index == 7 || this._prize == this._index + 1)) { this._speed += 110; } else { this._speed += 20; } } if (this._speed < 40) { // 设置最快速度 this._speed = 40 } this._timer = settimeout(()=>{ // 重复执行 this._roll(); }, this._speed) } } _showprize() { //展示中奖结果 // 直接dom操作 展示结果文案了 let reizedon = this.lotterydom.find('.prize-reason'); reizedon.fadein(); if(this._prizetype) { reizedon.find('img').attr('src', this._prizetype == 1? pointimgsrc: couponimgsrc); reizedon.find('.res-title').text('恭喜获得'); reizedon.find('.res-con').text(this._prizetitle).removeclass('no'); } else { reizedon.find('.res-title').text('谢谢参与'); reizedon.find('.res-con').text('哎呀,没抽中, 换个姿势,再来一次吧~').addclass('no'); reizedon.find('img').attr('src', thanksimgsrc); } // 初始点击与动画 this._isclick = false; this._prize = -1; this._times = 0; this._speed = this.options.speed; } } win.lottery = lottery; })(window, jquery);
最后抽奖就是这个结果啦
上面展示了如何完成一个抽奖功能, 如果有更好的,希望指出, 因为在练习es6, 所有就混合成这样的四不像了, jq还是没有放下。。。 不用框架写原生真的不想尝试。。。
就一个前端,我当然是想咋样咋样啦~ 哎。
上一篇: 是她有病