网站开发 ,经常需要用到登录注册,签到抽奖等模块,虽然每次都要写,但是把这个记录下来会很方便下次再用。。。
这边刚写了一个签到抽奖,放到这边来分享记录一下。 项目地址
首先根据设计图 需要这样的样式与效果
这样的抽奖页面无非就是样式当前类切换的效果, 那基本逻辑就是点击抽奖后,需要做一个跑马灯的效果,并且一开始加速然后减速到出中奖结果, 这边会用到定时器
每切换一下调用定时器,直到出来结果后清除定时器。。。展示中奖
那面贴上代码
// 调用是这样的 // 声明这个函数 用来传入后台请求获取中奖结果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 = ``; // 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)签到抽奖
X
{ title }
{ title }
{ title }
谢谢参与
开始抽奖
免费次数:1次{ title }
{ title }
{ title }
{ title }
X 再抽一次抽奖说明:
1、 每个用户每天签到一次可获得一次抽奖机会( 抽奖机会当天有效 )
2、 10积分抽奖一次
上面两段是样式效果, 下面是逻辑代码了。
;(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还是没有放下。。。 不用框架写原生真的不想尝试。。。
就一个前端,我当然是想咋样咋样啦~