Enseñarle cómo desarrollar una animación de lotería de Jiugongge

fondo

Hay un dicho que dice: "Cuando tienes un martillo en la mano, ves clavos por todo el mundo". Siguiendo el desarrollo desarrolló un componente de lista virtual con una altura fija de los elementos de la lista y el componente de desarrollo se volvió adicto. En el proyecto reciente, se realizará una animación de lotería giratoria de nueve cuadrados. Parece que esta función se puede reutilizar. También está destinado a convertirse en un componente. Con el paradigma de desarrollo explorado en el último componente de desarrollo, esta vez el componente de desarrollo tiene menos trabas de problemas que el componente de desarrollo. Ahora vayamos al tema de hoy.

Demostración de efectos

Primero mire el efecto final. Después de hacer clic en el botón de lotería, la lotería comienza a girar. La animación de la lotería cambia de lento a rápido, y luego mantiene una velocidad constante. Cuando se detiene, se ralentiza, lo que es más adecuado para el efecto de rotación de los objetos del mundo real. Por cierto, la función de lotería en este artículo se desarrolla vue3 + vite + tsadoptando el método de desarrollo. Si usa otras pilas de tecnología, debe modificarlo para usarlo.

canal.gif

Ideas de implementación

La animación de marquesina de sorteo de lotería de Jiugongge es el núcleo de la función de sorteo de lotería de Jiugongge. Como se muestra en la siguiente figura: Por lo general, la animación de marquesina de Jiugongge gira en el sentido de las agujas del reloj y la secuencia de rotación es [1, 2, 3, 6, 9, 8, 7, 4]. Al pasar a qué cuadrícula, agregue un estilo de resaltado a esta cuadrícula, y parece que tiene un efecto de parpadeo. Además, la velocidad de rotación variará. Al principio, acelera desde la velocidad inicial hasta la velocidad más alta, y luego sigue girando a una velocidad constante. Cuando llega a la parrilla ganadora, la velocidad debe reducirse. ¿Cómo controlar la velocidad de rotación de la marquesina? Se puede juzgar en función de la cantidad de pasos para llegar a la posición actual y la cantidad total de pasos que deben girarse. Por ejemplo, en el primer tercio del viaje, deje que el cronómetro acelere, y en el último sexto del viaje, deje que el cronómetro acelere y mantenga una velocidad constante en medio del viaje, y establezca el valor de tiempo de el temporizador a un valor fijo.

imagen.png

Hazlo tu mismo

Dibujar una página estática

Encontré tres imágenes de Internet, a saber, la imagen de oro con descuento instantáneo de 10 yuanes, gracias por participar en la imagen y la imagen del botón de lotería. Use estas tres imágenes para generar una lista de datos de materiales de 9 cuadrículas. ¿Por qué usar 9 imágenes en lugar de una imagen completa? La razón principal es que si usa una imagen completa, el efecto de resaltado no es fácil de lograr al configurar la cuadrícula por la que pasa la marquesina.


  import { reactive } from 'vue';
  import { NineGridLottery } from '@lib/core';
  import RMBImg from '@/assets/10rmb.png';
  import LotteryBtnImg from '@/assets/lottery-btn.png';
  import ThankImg from '@/assets/thank.png';

  // 奖品列表
  const lotteryList = reactive([
    { name: '10元立减金', pic: RMBImg },
    { name: '谢谢参与', pic: ThankImg },
    { name: '10元立减金', pic: RMBImg },
    { name: '谢谢参与', pic: ThankImg },
    { name: '抽奖', pic: LotteryBtnImg },
    { name: '谢谢参与', pic: ThankImg },
    { name: '10元立减金', pic: RMBImg },
    { name: '谢谢参与', pic: ThankImg },
    { name: '10元立减金', pic: RMBImg },
  ]);

网页结构如下: index=4 时,这个位置是抽奖按钮,抽奖按钮一般交互比较多,所以用插槽的方式暴露给父组件,让父组件去定制。因为slot上不能绑定事件,所以需要在外层加个div,把点击事件绑定在外层的div上。考虑到不同的抽奖活动外观展示都不一样,所以抽奖的样式要允许父组件自定义。这里把抽奖组件的样式类名前缀交给父组件去配置。

<template>
  <div :class="`${props.classPrefix}-box`">
    <div
      v-for="(item, index) in props.lotteryList"
      :class="[`${props.classPrefix}-item`, { active: state.curIndex === index }]"
    >
      <template v-if="index !== 4">
        <img v-if="item.pic" :src="item.pic" class="pic" alt="" />
        <!-- <p class='text'>{{ item.name }}</p> -->
      </template>
      <div v-else @click="start()">
        <slot name="lotteryBtn" :itemData="item"> </slot>
      </div>
    </div>
  </div>
</template>

九宫格抽奖组件的样式是在父组件定义的,九宫格抽奖容器采用flex布局,需要注意的是 flex-wrap默认属性是不换行的,要将属性值设置成wrap。另外下载的png图片不太标准,有色彩的部分并不在png图片背景的正中央,需要向左偏移1px, 看起来左右才对称。转动高亮的效果使用区别于静止状态的背景图和阴影效果实现。

<style lang="less">
  .lottery-box {
    width: 375px;
    height: 375px;
    background: #ea0019;
    margin: 100px auto;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;
    align-items: center;
    .lottery-item {
      width: 125px;
      height: 125px;
      position: relative;

      &.active {
        box-shadow: 2px 2px 30px #ffe4c0;
        background-color: #ffe4c0;
      }

      &:nth-of-type(5) {
        cursor: pointer;
      }

      .pic {
        width: 100%;
        height: 100%;
        position: absolute;
        left: -1px;
      }

      .text {
        width: 100%;
        height: 20px;
        background: rgba(0, 0, 0, 0.5);
        color: #fff;
        font-size: 12px;
        text-align: center;
        line-height: 20px;
        position: absolute;
        left: 0;
        bottom: 0;
      }
    }
  }
</style>

让抽奖转盘转起来

首先确定一下九宫格转盘的跑动顺序。顺时针转动时,每个格子的下标为:

 // 跑动顺序
  const lotterySort = [0, 1, 2, 5, 8, 7, 6, 3];

每跑一圈,需要跑八步。到达中奖格子位置跑马灯动画需要跑动的总步数=基本圈数*8+中奖格子在跑动数组中的位置。中奖的id在未跑动前,要先调用后端接口,确定下来。

  // 总执行步数
  const totalSteps = computed(() => {
    return props.baseCircles * 8 + lotterySort.indexOf(props.winId);
  });

跑动时,需要动态设置跑动速率。每次跑动时,清除上一次的速率。每前进一步,重新创建定时器,调整速率。并对到达位置的格子进行高亮显示。当跑动的步数大于等于总步数时,给父组件发消息。

 const timer: Ref<ReturnType<typeof setTimeout> | null> = ref(null);
 const startRun = () => {
    // 延时器的速度要动态调节
    timer.value && clearTimeout(timer.value);

    // console.log(`已走步数=${state.curStep}, 执行总步数=${totalSteps.value}`);

    // 已走步数超过要执行总步数, 则停止
    if (state.curStep >= totalSteps.value) {
      state.isRunning = false;
      return emit('end');
    }

    // 高亮抽奖格子序号
    state.curIndex = lotterySort[state.curStep % 8];
    // 速度调整
    state.speed = calcSpeed(state.speed);

    timer.value = setTimeout(() => {
      state.curStep++;
      startRun();
    }, state.speed);
  };

跑动速率的计算方法,前三分之一的路程,从初始速率加速到最快速率,然后保持最快速率,匀速跑动,到了总路程最后的六分之一时,开始减速,犹如刹车一样,慢慢停下来。

  // 需要加速的前段步数
  const frontSteps = Math.floor(props.baseCircles * 8 * (1 / 3));
  // 需要减速的后段步数
  const midSteps = Math.floor(totalSteps.value * (5 / 6));

  // 计算速度
  const calcSpeed = (speed: number) => {
    // 最快最慢速度
    const { fastSpeed, slowSpeed } = props;
    // 前段加速,中段匀速,后段减速
    if (state.curStep < frontSteps && speed > fastSpeed) {
      speed = speed - Math.floor((props.initSpeed - fastSpeed) / frontSteps);
    } else if (state.curStep > midSteps && speed < slowSpeed) {
      speed = speed + Math.floor((slowSpeed - fastSpeed) / frontSteps / 5);
    }
    return speed;
  };

使用方法

组件有 7 个配置参数:

组件属性名 含义
lotteryList 抽奖列表
winId 中奖 id
classPrefix 九宫格容器和奖项的样式类名前缀
initSpeed 初始转动速度 单位 ms (可选)
baseCircles 基本转动圈数 (可选)
fastSpeed 最快转动速度 单位 ms (可选)
slowSpeed 最慢转动速度 单位 ms (可选)
@end 转动结束事件
<template>
  <NineGridLottery
    :lotteryList="lotteryList"
    :winId="options.winId"
    :initSpeed="options.initSpeed"
    :baseCircles="options.baseCircles"
    @end="handleEnd"
    classPrefix="lottery"
  >
    <template #lotteryBtn="{ itemData }">
      <img :src="itemData.pic" class="pic" alt="" />
    </template>
  </NineGridLottery>
</template>

<script setup lang="ts">
  import { reactive } from 'vue';
  import { NineGridLottery } from '@lib/core';
  import RMBImg from '@/assets/10rmb.png';
  import LotteryBtnImg from '@/assets/lottery-btn.png';
  import ThankImg from '@/assets/thank.png';

  // 奖品列表
  const lotteryList = reactive([
    { name: '10元立减金', pic: RMBImg },
    { name: '谢谢参与', pic: ThankImg },
    { name: '10元立减金', pic: RMBImg },
    { name: '谢谢参与', pic: ThankImg },
    { name: '抽奖', pic: LotteryBtnImg },
    { name: '谢谢参与', pic: ThankImg },
    { name: '10元立减金', pic: RMBImg },
    { name: '谢谢参与', pic: ThankImg },
    { name: '10元立减金', pic: RMBImg },
  ]);

  // 后台配置的奖品数据
  const options = reactive({
    // 中奖id
    winId: 6,
    // 基本圈数 
    baseCircles: 4,
    // 抽奖转动速度
    initSpeed: 300,
    fastSpeed: 100,
    slowSpeed: 600,
  });

  const handleEnd = () => {
    alert('恭喜你中奖了');
  };
</script>

// 样式参照上文
<style lang="less"></style>

结语

Este es el final de la realización de los principales puntos de función de la versión vue3+vite4+ts del sorteo de lotería rotativa de Jiugongge. Si desea obtener el código completo del ejemplo de este artículo, haga clic aquí para descargarlo . Además, este componente también se cargó en el sitio web oficial de npm, puede hacer clic aquí para verlo , instalarlo y usarlo.

Supongo que te gusta

Origin juejin.im/post/7248168880572694588
Recomendado
Clasificación