自制掘金抽奖!

942 阅读2分钟

最近掘金的抽奖永远都是 66矿石Bug,实在是对不起自己,为了满足自己不要再抽中 66矿石Bug,决定自己写一个抽奖列表,抽奖,过程绝对公平公正公开有效

让我们先来看下玩法(怎么又是66矿石)

文末笔者将整个抽奖流程都抽离出封装成了对应的Vue版本组件,方便大家使用(本文是用Vue版本作为例子)

hI3Z11.gif

这里来看下怎么写一个不再是矿石Bug的抽奖

第一步:正反面卡片

先生成掘金抽奖模拟的卡牌数据

const list = ref([
      {
        name: "66矿石",
        img:
          "https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/32ed6a7619934144882d841761b63d3c~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp",
      },
      ... 
      {
        name: "Switch",
        img: 'https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4decbd721b2b48098a1ecf879cfca677~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp'
      },
    ]);

由于需要做成组件,我们需要通过

Vue2:props.sync="list"

Vue3v-model:list="list"

修改父组件传来的list,为每一个卡牌添加turn属性,为之后通过先后顺序给点中的奖牌先翻奖动效添加属性

我们需要先把正反面的样式写好

样式这里不作简述

需要注意的是正、反两面用的是不同的样式

通过transform: rotateY(180deg)transform: rotateY(0)来控制卡牌的正反面,且给对应的正反面写相应的样式,这里就不放代码了,有兴趣的可直接上github查看源码

得到正面卡牌

hjyb7R.png

和反面卡牌

hjyXh6.png

第二步:翻转卡牌

完成正反面样式编写后,我们需要添加一个function来控制翻转所有卡牌样式

/**
 * 翻转所有卡牌
 */
const turnAllPrizes = (turn: boolean) => {
    const list = props.list;
    const newList = list.map((item: IPrize) => {
        item.turn = turn;
        return item;
    });
    context.emit("update:list", newList);
};

hj2MHH.gif

第三步:居中洗牌回位

洗牌

首先我们需要将所有的卡牌居中

这里我们用 scss 将样式写好

通过scss的计算方法,我们很快就能写好卡片居中的样式

通过transition属性,使我们添加对应移动的class的时候会默认添加过渡效果

@use "sass:math";

$card-height: 220px;
$half-width: 50;

@function moveTranslateY($i) {
  @return if($i < 4, math.div($card-height, 2), -(math.div($card-height, 2)));
}

@function moveTranslateX($i) {
  @return if(
    $i < 4,
    (calc(#{$half-width - $i * 25}vw - 50%)),
    (calc(#{$half-width - ($i - 4) * 25}vw - 50%))
  );
}

@for $i from 0 through 7 {
  .move-#{$i} {
    transform: translate(moveTranslateX($i), moveTranslateY($i));
  }
}

4PENVJ.gif

回位

回位也很简单,只需要把对应的class移除即可

4PQBRJ.gif

第四步:翻牌

思路也很简单,点击对应的卡牌的时候,将其turn属性修改回false,500ms后再将其他所有的卡牌统一翻转

/**
 * 抽奖
 */
const lottery = debounce(
    (click: number) => {
        // 执行动画时,不许点击
        if (lock) return;

        click_index.value = click;
        dealPrizes();
    },
    500,
    {
        leading: true,
        trailing: false,
    }
);

/**
* 处理奖品
*/
const dealPrizes = () => {
    const list = props.list;

    // 点击的 index 先翻转
    list[click_index.value].turn = false;

    context.emit("update:list", list);

    // 其余的 0.5s 后翻转
    setTimeout(() => {
        turnAllPrizes(false);
        turning.value = !turning.value;
    }, 500);
    isFirst.value = false;

    // 去掉一次抽奖机会
    context.emit("update:drawNumber", props.drawNumber - 1);
};

hI3Z11.gif

这样子就实现完成了,其实实现的流程不算复杂,更多的是思路和动画效果的流程思考。

Demo

本文只展示了部分代码,Demo示例已上传至github

Vue3 版本:vue-flop-draw

其他

看得不过瘾?这里还有别的文章