第115期:转盘抽奖活动带跑马灯的实现方案

这里记录工作中遇到的技术点,以及自己对生活的一些思考,周三或周五发布。

封面图

image.png

在复兴号列车

转盘抽奖前端实现方案

需求

前几天有个朋友让我帮他写一个转盘抽奖的效果,大体的要求有这么两个:

  • 未点击抽奖按钮时,转盘外围有一圈交替明暗的灯珠
  • 抽奖过程中转盘外围的灯珠变成跑马灯的效果
  • 奖品的数量可以配置为6或8个
  • 按钮点击要有一个按下后弹起的动作

示意图:

image.png

分析

用图片实现

要实现这个几个功能,最简单的方式是使用图片。比方说,明暗交替的灯珠采用gif来实现,这种使用图片的方式实现起来比较方便,但是在网络情况不好的条件下,图片的切换过程中,图片加载需要一定的时间,转盘的盘面会出现一段时间的空白,整体的体验就会差了一些。

用css实现

毫无疑问,按钮点击有一个弹起的动作以及明暗交替的灯珠是可以用css来进行实现的。

按钮点击弹起

按钮点击弹起,这个效果可以用:active这个伪类进行实现。很多人都知道:active这个伪类可以用在<a>标签上,但是其实它也可以用在button按钮上。具体可以查看它的使用方式

:active 伪类一般被用在 <a> 和 <button> 元素中。这个伪类的一些其他适用对象包括包含激活元素的元素,以及可以通过他们关联的<label>标签被激活的表格元素。

所以这个按钮点击的效果实现起来就比较简单:

button::active{
    tarnsform:scale(0.98);
}
复制代码

大致就这么简单。

灯珠明暗交替

灯珠的效果需要我们先把灯珠按照相应的布局画到页面上。绘制的过程通常是根据转盘的容器进行定位,然后旋转相应的角度。

比如这里有8个奖品,24颗灯珠,单个旋转的角度就是360/24=15度。然后根据每个(灯珠的下标+1)*15就是每个灯珠具体需要旋转的角度。

灯珠的位置固定好以后,就可着手实现明暗交替的效果,这个效果可以用css的animation来实现,具体方案是的解释如下:

  1. 先根据灯珠的奇偶,分别着不同的颜色
  2. 设置动画,根据灯珠的奇偶(下标)设置动画
 <View className={styles.lightItemActive}
                          style={{
                            width: '117px',
                            transform: `translateX(-50%) rotate(${(360 / (activeDetail.prize.length * 3)) * item}deg)`
                            '--color-white':(item+1)%2?'#fff':'#93b3ff',
                            '--color-blue':(item+1)%2?'#93b3ff':'#fff',
                            '--char-index':item
                          }}
                        >
                          <View
                            className={styles.bubble}
                            style={{
                              background: item % 2 == 0 ? colorCircleFirst : colorCircleSecond,
                              boxShadow:
                                item % 2 == 0
                                  ? `0 0 5rpx ${filterOne},
                              0 0 10rpx ${filterOne},
                              0 0 20rpx ${filterOne},
                              0 0 40rpx ${filterOne},
                              0 0 80rpx ${filterOne}`
                                  : `0 0 5rpx ${filterTwo},
                              0 0 10rpx ${filterTwo},
                              0 0 20rpx ${filterTwo},
                              0 0 40rpx ${filterTwo},
                              0 0 80rpx ${filterTwo}`
                              //  filter:((item)%2==0)?'drop-shadow(0px 0px 10px'+ filterOne+') brightness(3)':'drop-shadow(0px 0px 10px '+filterTwo+') brightness(3)',
                            }}
                          ></View>
                        </View>
复制代码

我这dom 没有参考性,只是举个例子。

然后设置动画

.bubble{
    animation:flash 1s linear infinite;
}

@keyframes flash {
    0%   {background: var(--color-white);}
    25%  {background: var(--color-blue);}
    50%  {background: var(--color-white);}
    100% {background: var(--color-blue);}
复制代码

灯珠的跑马灯效果

跑马灯用css实现可以参考下面的效果:

其方案也可以理解为是用下标,设置不同的元素的颜色,然后通过延时动画,设置元素的背景,以及drop-shadow来实现,其关键代码如下:

.showcase__text .char {
  -webkit-animation-delay: calc(((var(--char-index) + 1) * var(--step)) * 1s);
          animation-delay: calc(((var(--char-index) + 1) * var(--step)) * 1s);
  -webkit-animation-duration: calc(var(--duration) * 1s);
          animation-duration: calc(var(--duration) * 1s);
  -webkit-animation-iteration-count: infinite;
          animation-iteration-count: infinite;
  -webkit-animation-name: flash;
          animation-name: flash;
  background: #000;
  text-shadow: 0 4px 0 #000;
}

@keyframes flash {
  0%, 30%, 50%, 100% {
    background: #000;
  }
  40% {
    background: var(--color);
    -webkit-filter: drop-shadow(0 0 calc(var(--font-size) * 1rem) var(--color)) blur(2px) brightness(5);
            filter: drop-shadow(0 0 calc(var(--font-size) * 1rem) var(--color)) blur(2px) brightness(5);
  }
}
复制代码

注意:它使用了-animation-delay属性,如果不设置这个属性,则没有跑马灯的效果。

需要考虑的问题

  • 小程序端

因为我这次写的这个效果的场景运行在小程序上。前期整体的效果采用css来实现,由于animation的间歇调用,加上时间动画时间比较短,所以整体上会有一个非常明显的闪顿的效果,不是卡顿。比如我设置的动画时长是1s,则每一秒动画完成后,整体会有个非常明显的闪的效果,这种体验非常不好。

采用js方案实现

基于上面说的原因。整体的方案又重新改成了js来实现,js实现起来非常简单。

灯珠交替明暗

灯珠交替明暗这个效果用定时器设置两种不同的颜色,当灯珠颜色为a时设置为b,为b时设置为a即可。

 <View
                            className={styles.bubble}
                            style={{
                              background: item % 2 == 0 ? colorCircleFirst : colorCircleSecond,
                              boxShadow:
                                item % 2 == 0
                                  ? `0 0 5rpx ${filterOne},
                              0 0 10rpx ${filterOne},
                              0 0 20rpx ${filterOne},
                              0 0 40rpx ${filterOne},
                              0 0 80rpx ${filterOne}`
                                  : `0 0 5rpx ${filterTwo},
                              0 0 10rpx ${filterTwo},
                              0 0 20rpx ${filterTwo},
                              0 0 40rpx ${filterTwo},
                              0 0 80rpx ${filterTwo}`
                              //  filter:((item)%2==0)?'drop-shadow(0px 0px 10px'+ filterOne+') brightness(3)':'drop-shadow(0px 0px 10px '+filterTwo+') brightness(3)',
                            }}
                          ></View>
复制代码
//灯珠交替
   setTimeout(function () {
    
    if (colorCircleFirst === 'linear-gradient(-17deg, #fff, #FFFFFF)') {
      setColorCircleFirst('linear-gradient(-17deg, #9DD6FF, #EFF9FF)')
      setColorCircleSecond('linear-gradient(-17deg, #fff, #FFFFFF)')
     
      setFilterOne('#3091FF')
      setFilterTwo('#fff')
    } 
    if(colorCircleFirst === 'linear-gradient(-17deg, #9DD6FF, #EFF9FF)'){
      setColorCircleFirst('linear-gradient(-17deg, #fff, #FFFFFF)')
      setColorCircleSecond('linear-gradient(-17deg, #9DD6FF, #EFF9FF)')
      setFilterOne('#fff')
      setFilterTwo('#3091FF')
    }
  }, 500)
复制代码

跑马灯

跑马灯用js实现起来也很简单,给灯珠设置一个颜色,然后设置一个数字,当灯珠下标等于这个数字时,设置灯珠颜色即可。

我们需要做的就是通过定时器控制这个数字变化的速度,然后在转盘动画结束后清除定时器。

<View className={styles.bubble}
                            style={{
                              background:
                                (item + 1) % 2
                                  ? 'linear-gradient(-17deg, #fff, #fff)'
                              boxShadow:
                                selectLightIndex === item
                                  ? `0 0 10rpx #fff,
                              0 0 20rpx #fff,
                              0 0 40rpx #fff,
                              0 0 80rpx #fff,
                              0 0 100rpx #fff`
                                  : ''
                            }}
                          ></View>
复制代码
let i = 0;
      var timer = setInterval( ()=> {
        selectLightIndex++;
        i += 40;
       
        selectLightIndex = selectLightIndex%24
        setSelectLightIndex(selectLightIndex)
         //获奖提示
      }, times*1 + i);
      setTimeout(() => {
       
        clearInterval(timer)
        roateEnd(awardSettingNumber);
      }, 5150);
复制代码

selectLightIndex%24根据灯珠数量取余这个运算可以控制当前哪个灯珠亮起。

i += 40; 则可以控制转动的速度。

这样,转盘的整体效果就基本完成了。

点击抽奖按钮前,灯珠明暗交替。

点击抽奖按钮后,灯珠则是跑马灯效果。

其他问题

在写这个效果的是遇到一个多图片的marquee效果。

使用css的transform:translate(x)进行实现,当图片数量大于一定数量的时候,可以看到有非常明显的卡顿。

查了一些文档,说是需要使用translate3d()开启硬件加速,但是不起作用,这个似乎暂时无解。

最后

以上就是写这个转盘抽奖效果的所有收获,希望能对有需要的同学有所帮助。

近期的事情有点多,暂时先写到这里吧~

如果喜欢。

请点赞和"在看"吧,最好也加个"关注",或者分享到朋友圈。

分享两张个人觉的不错的图片

WeChata8508a70e6cbc1867ad285fe3abcd8ca.png

暴雨之前的郑州(一)

image.png

暴雨之前的郑州(二)

猜你喜欢

转载自juejin.im/post/7129557111826022431
今日推荐