博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
签到抽奖功能——常见前端抽奖需求
阅读量:5287 次
发布时间:2019-06-14

本文共 14855 字,大约阅读时间需要 49 分钟。

网站开发 ,经常需要用到登录注册,签到抽奖等模块,虽然每次都要写,但是把这个记录下来会很方便下次再用。。。

这边刚写了一个签到抽奖,放到这边来分享记录一下。 项目地址

首先根据设计图 需要这样的样式与效果

1583226-20190117164201928-1519724774.png

这样的抽奖页面无非就是样式当前类切换的效果, 那基本逻辑就是点击抽奖后,需要做一个跑马灯的效果,并且一开始加速然后减速到出中奖结果, 这边会用到定时器

每切换一下调用定时器,直到出来结果后清除定时器。。。展示中奖

那面贴上代码

// 调用是这样的 // 声明这个函数 用来传入后台请求获取中奖结果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 = `        

签到抽奖

X
  • { title }

  • { title }

  • { title }

  • 谢谢参与

  • 开始抽奖

    免费次数:1
  • { title }

  • { title }

  • { title }

  • { title }

X

再抽一次

抽奖说明:

1、 每个用户每天签到一次可获得一次抽奖机会( 抽奖机会当天有效 )

2、 10积分抽奖一次

`; // 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);

1583226-20190117170838912-1592533924.png

最后抽奖就是这个结果啦,项目地址在,效果可以自己在网站中看到哦~

上面展示了如何完成一个抽奖功能, 如果有更好的,希望指出, 因为在练习es6, 所有就混合成这样的四不像了, jq还是没有放下。。。 不用框架写原生真的不想尝试。。。

就一个前端,我当然是想咋样咋样啦~

转载于:https://www.cnblogs.com/mrzll/p/10283272.html

你可能感兴趣的文章
树上的路径
查看>>
问题总结
查看>>
软件随笔
查看>>
Linux下SVN自动更新web [转]
查看>>
Openstack api 学习文档 & restclient使用文档
查看>>
poj100纪念
查看>>
NetWork——关于TCP协议的三次握手和四次挥手
查看>>
An easy problem
查看>>
MauiMETA工具的使用(一)
查看>>
LeetCode: Anagrams 解题报告
查看>>
Qt 中获取本机IP地址
查看>>
070102_赌博设计:概率的基本概念,古典概型
查看>>
IT人生的价值和意义 感觉真的有了
查看>>
JS DOM对象
查看>>
OGR – Merging Multiple SHP files
查看>>
创业公司该不该被收购?(转)
查看>>
sqlserver 行转列、列转行[转]
查看>>
【IScroll深入学习】解决IScroll疑难杂症
查看>>
python 数据类型
查看>>
108-PHP类成员protected和private成员属性不能被查看数值
查看>>