【SSD】掘金的抽奖,“拆穿她“,而后实现一个,顺便封装一个库

这是我参与8月更文挑战的第12天,活动详情查看:8月更文挑战css

前言

关于关于【SSD系列】
前端一些有意思的内容,旨在3-10分钟里, 500-1500字,有所获,又不为所累。前端

掘金抽奖,不中大奖,本身复原UI, 中一个大奖知足本身,顺便封装一个库。css3

若是点赞破100,再写一篇转盘抽奖的相关文章,并顺便封装一个库。git

效果演示

PC端

luckDraw_d.gif

模拟移动端

luckDraw_m.gif

源码

luckDraw 源码github

  1. 包含封装库
  2. 包含UI

抽奖简析

抽奖嘛,简单说就是障眼法。 前先后后的动画都是加强一些体验,寻求一点刺激罢了,幻想本身能成为那个大奖得到者。web

常见表现形式

常见的抽奖表现有两种,九宫格转盘,转盘又有转动指针转动转盘两种。 从实现难度上来讲, 转盘大于九宫格。chrome

通常的实现方式

  1. 九宫格
    间隔的设置背景色或者蒙层,越日后间隔越大。
  2. 转盘
    1. 纯脚本控制:每一个一段时间,转动转盘或者指针,越日后,转动越少。
    2. css动画: 提早计算旋转角度好,配合css3, 利用好贝塞尔函数,梭哈。

通常逻辑处理

  1. 动画先行
    就是先执行动画,期间去获取结果,而后决定定格在何处。
  2. 结果先行
    先获取结果,而后启动动画。

掘金站点技术浅析

这里就客串分析下掘金的技术栈,推荐一款 BuiltWith Technology Profiler的chrome建立,其能分析出网站的采用哪些技术构建。 咱们一看看看掘金的。api

image.png

看看DOm节点熟悉的__nuxtdata-v, 还真是那么回事。 image.png微信

掘金抽奖简析

掘金的抽奖属于典型的九宫格,中间是抽奖的按钮。markdown

布局

典型的flex布局,九个格子,九个turntable-itemdiv,抽奖按钮采用单独的lottery样式标记。

image.png

动画先行仍是结果先行?

抽奖接口是https://api.juejin.cn/growth_api/v1/lottery/draw,咱们打开控制面板, Network板块,输入draw过滤请请求。

执行一次,而后block抽奖请求。

image.png

再次执行,能够明显的看到先执行了动画,因此我推断是动画先行,至于真相,他重要吗?不重要,反正我也抽不中!!!!!!

luckDraw_block.gif

实现思路

咱们采用动画先行方案,先启动动画,中途请求结果,获得结果后,执行命中动画。

基本思路

1. 编号
0-n个坑位,九宫格的话,就是0-7个坑位,坑位的东西能够重复。

image.png

2.启动动画
匀速的切换格子,同时请求服务接口。

3. 中奖动画
收到结果后,计算出命中奖品的编号,并执行减速逻辑。

分离逻辑

基本思路就是这样子的,为了通用性,咱们须要多思考一些,抽奖重要的是逻辑,表面的形式重要吗? 其实并不过重要,因此咱们这里把抽奖逻辑封装,提供可变性,并对外提供事件通知。

可变性
可变性通常是经过参数和对外暴露方法来实现的,咱们也不例外。

  1. 格子数,不单单是九宫格,10宫格,12宫格都支持
  2. 起始位置,不必定是从0开始
  3. 起始的时间间隔,以后会愈来愈慢
  4. 至少转动的次数, 若是接口太快,可能感受没开始就结束了。
  5. 获得结果后,咱们的减速动画逻辑,应该是内置,同时能够被覆写。

事件通知

整个过程可能存在的事件:

  1. onStart: // 当开始
  2. onUpdate: // 旋转一次
  3. onEnded: // 结束
  4. onError: // 异常

咱们把这些整个起来, 大概就是这个样子了,都很简单。

var defaultOption = {
        startIndex: 0, // 初始位置
        pits: 8,  // 格子数
        interval: 100, // 初始间隔
        rate: 2.5,  // 系数
        cycle: 5,  //转动基本次数:即至少须要转动多少次再进入抽奖环节
        getInterval: null // 自定义旋转间隔函数
        //onStart: null, // 当开始
        //onUpdate: null, // 旋转一次
        //onEnded: null, // 结束
        //onError: null // 异常, 好比转动次数已经达到设定值, 可是没有设置奖项
    };
复制代码

使用代码

工具方法

先封装两个添加方法,一个添加选中的class,一个删除选中的class。

function removeChosenClass() {
    var el = lotteryEl.querySelector('.turntable-item.chosen');
    if (el) {
        el.classList.remove('chosen');
    }
}

function addChosenClass(index){
    lotteryEl.querySelector('.turntable-item.turntable-item-' + index).classList.add('chosen');
}
复制代码

实例化

Lottery是咱们封装的逻辑类。

var options = {
};
var lottery = new Lottery(options);
复制代码

注册启动事件和模拟中奖

4号坑位是大奖

var btnStart = document.querySelector(".turntable-box .turntable-item.lottery");
btnStart.addEventListener('click', function () {
    lottery.start();
    setTimeout(() => {
        setPrize();
    }, 800)
})

function setPrize() {
    lottery.setPrize([4]) // 4号坑位是大奖
}

复制代码

监听抽奖事件

lottery.onUpdate = function (ins, index, times) {
    removeChosenClass();
    addChosenClass(index);
}

lottery.onEnded = function (ins, index, prizeIndexes) {
    removeChosenClass();
    addChosenClass(index);

    setTimeout(function () {
        dialogEl.classList.remove("hide");
    }, 500)
}
复制代码

到此为止,使用代码完毕,与框架无关。

逻辑库封装

逻辑库的完整代码位于 抽奖逻辑Lottery.js , 我就不全贴出来,否则违背我500-1500字的原则了,就贴一张简单的属性图吧。

image.png

小结

是否是很简单,一切都看起来没那么难。

写在最后

不忘初衷,【SSD系列】,3-5分钟,500-1000字,有所得,而不为所累,若是你以为不错,你的一赞一评就是我前行的最大动力。

技术交流群请到 这里来。 或者添加个人微信 cloud-dirge,一块儿学习。

相关文章
相关标签/搜索