• 抽奖动画


    1. 需求

    开宝箱在一些商家营销活动中也很常见,这个需求简单,产品经理说就是做个动画就好,那我们就可以自由发挥了。高保图如下图1.
    image
    图1
    开局一张图,剩下的全靠自己编了,动作怎么动,先看看UI给的素材,看米下锅。一张关闭的箱子图片,如下图2
    image
    图2
    一张打开的箱子,如下图3
    image
    图3
    一张奖品背景图片,是光芒,可以作为奖品的背景图,如下图4
    image
    图4

    虽然需求文档中没有给出这个动画的具体需求,但可以根据产品的描述,可以把需求归纳一下,如下:

    1. 点击“立即开启”,先显示半透明的蒙版,再显示关闭的箱子,并且从小变大
    2. 请求接口,同时从关闭变成打开的箱子,在打开箱子的空白处显示中奖结果
    3. 用光芒图片作为奖品图片的背景,并且光芒不断地旋转起来
    4. 点击关闭,关闭整个中奖弹框

    2. 思路

    这个动画相对简单,可以直接使用css中的animation动画,通过keyframe定义动画帧来让图片从小变大,同时切换上面的图2和图3可以让宝箱状态从关闭变成打开,然后显示奖品就有了。然后还有一个地方,就是奖品的背景是一个圆形光芒,可以让它旋转,或者不断地变大变小,这样看起来更加的生动。

    3. 实现过程

    3.1 蒙版

    点击按钮首先弹出蒙版,这就没啥好说的了,使用fix定位 + background + opacity可以做一个简单的蒙版,代码如下:

    <!-- 抽奖按钮 -->
    <img class="treasure" src="./../assets/images/treasurebox.gif" @click="openBox" alt=""/>
    <!-- 弹出层 -->
    <div v-if="showBox" class="pop-up">
    <div class="prize-box"></div>
    

    css代码如下:

    .pop-up {
      position: fixed;
      z-index: 4;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
       100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.4);
    }
    

    注意上面代码中使用rgba作为背景色,最后一个参数是opacity,规定不透明度。从 0.0 (完全透明)到 1.0(完全不透明)。

    3.2 开宝箱

    宝箱图片有2个,一个是关闭的,一个是打开的,要用一个动画控制二者切换,并且还要掌握好他们的显示时间这样看起来是一个打开的过程,不过这里只有两张图片,无法看到打开过程,只能稍微模拟一下。如果要有整个过程的话,就要提供很多个中间状态的宝箱图片了。html代码如下:

    <div v-if="showBox" class="pop-up">
      <div class="prize-box">
      </div>
    </div>
    

    css代码如下:

    $aniDuration: 2s;
    .prize-box {
      position: relative;
       548px;
      height: 739px;
      margin: 81px auto auto auto;
      animation: openBox $aniDuration ease-out 1s 1 forwards;
      background: top/5% no-repeat url("./../assets/images/box@2x.png");
    }
    @keyframes openBox {
      from {
          background-position: center;
          -webkit-background-size: calc(548px * 0.1) calc(739px * 0.1);
          background-size: 5%;
           calc(548px * 0.1);
          height: calc(739px * 0.1);
          background-image: url("./../assets/images/box@2x.png");
          background-position: top;
      }
      50% {
          background-position: center;
          background-size: 50%;
           calc(548px * 0.5);
          height: calc(739px * 0.5);
          background-image: url("./../assets/images/box@2x.png");
          background-position: top;
      }
      80% {
          background-position: center;
          background-size: 110%;
           calc(548px * 1.1);
          height: calc(739px * 1.1);
          background-position: top;
      }
      to {
          background-position: center;
          background-size: 548px 739px;
           548px;
          height: 739px;
          background-image: url("./../assets/images/boxopen@2x.png");
          background-position: top;
      }
    }
    

    代码中给class为prize-box的容器定义了一个动画openBox,用变量$aniDuration纪录动画持续时长,1秒后开始执行,最后停留在终态,时间函数(animation-timing-function)使用easy-out。在keyframe关键帧中修改了背景图片大小,dom容器大小等css属性,都是从小到大,并且在动画的0%80%部分是显示关闭宝箱,最后80%100%显示开启的宝箱。在动画的80%处背景稍微变大一下,看起来有膨胀的效果。可以想想一下,这个动画的整个过程是,关闭宝箱从小到大,变成开启的宝箱,并且膨胀一下,最后恢复到原始大小。

    animation的第三个属性animation-timing-function是一个贝塞尔时间函数,可用的取值如下:

    1. linear
      动画以恒定速度运行。此关键词表示缓冲函数 cubic-bezier(0.0, 0.0, 1.0, 1.0)。如下图5。
      image
      图5
    2. ease
      动画缓慢开始,然后突然加速,最后缓慢移向目标。此关键词表示缓冲函数cubic-bezier(0.25, 0.1, 0.25, 1.0)。它与 ease-in-out 类似,但它在开始时加速更快。如下图6。
      image
      图6
    3. ease-in
      动画缓慢开始,然后逐渐加速直到结束,在结束点时突然停止。此关键词表示缓冲函数 cubic-bezier(0.42, 0.0, 1.0, 1.0),如下图7。
      image
      图7
    4. ease-in-out
      动画缓慢开始,然后加速,最后减速直至结束。此关键词表示缓冲函数 cubic-bezier(0.42, 0.0, 0.58, 1.0)。开始时,其表现与 ease-in 函数类似;结束时,与 ease-out 函数类似。如下图8。
      image
      图8
    5. ease-out
      此动画突然开始,然后逐渐减速直至结束。此关键词表示缓冲函数 cubic-bezier(0.0, 0.0, 0.58, 1.0)。如下图9。
      image
      图9

    贝塞尔时间函数的内容很多,并且很晦涩,这里不再展开讨论。看看效果,如下图10

    图10

    3.3 请求接口

    请求接口前需要定义好奖品,以便从接口中取出中奖奖品信息,代码如下:

    data() {
      return {
        showBox: false,
        showPrize: false,
        prizeList: [
          {prizeId: "100860801", prizeName: "100元满减券"},
          {prizeId: "100860802", prizeName: "20元抵扣劵",},
          {prizeId: "100860803", prizeName: "10元抵扣券"},
          {prizeId: "100860804", prizeName: "1个月优惠员"},
          {prizeId: "100860805", prizeName: "1元红包"},
          {prizeId: "100860806", prizeName: "5红包"},
          {prizeId: "100860807", prizeName: "1元抵扣券"},
          {prizeId: "100860808", prizeName: "500元满减券"},
          {prizeId: "100860809", prizeName: "200元满减券"}
        ],
        title: ['发送给好友', '可增加一次开宝箱机会'],
        actionBtn: {id: 1, title: '呼朋唤友,再开一次'},
        prizeData: {prizeId: "100860801", prizeName: "100元移动话费"},      //抽奖信息奖信息
      }
    }
    

    这里依然使用getRandomIntInclusive()方法从奖品数据中随机取出一个奖品,模拟抽奖过程。代码如下:

    /* 开宝箱抽奖 */
    openBox() {
      this.showBox = true
      setTimeout(() =>  {
        this.showPrize = true
        let index = this.getRandomIntInclusive(0, this.prizeList.length - 1)
        this.prizeData = this.prizeList[index]
      }, 3000)
    },
    /* 关闭按钮 */
    followAction() {
      this.showBox = false
      this.showPrize = false
    },
    //返回随机数,大于等于min,小于等于max
    getRandomIntInclusive(min, max) {
      min = Math.ceil(min)
      max = Math.floor(max)
      return Math.floor(Math.random() * (max - min + 1)) + min //含最大值,含最小值 
    }
    

    3.4 显示奖品

    开宝箱的动画有了,剩下的就是请求接口,显示奖品了。注意开启的宝箱有两处留白,这里要使用相对定位来固定奖品图片,奖品名称文案,抽奖提示文案,如下图11
    image
    图11

    html代码如下:

    <!-- 弹出层 -->
    <div v-if="showBox" class="pop-up">
      <div class="prize-box">
        <template v-if="showPrize">
          <div class="prize">
            <img :src="require('./../assets/images/prize/' + prizeData.prizeId + '.png')" alt="" class="img-prize"/>
          </div>
          <div class="prizetip">
            <div>恭喜获您获得{{ prizeData.prizeName }}</div>
          </div>
          <div class="prizelead">
            <div class="content" @click="followAction">
              {{ actionBtn.title }}&gt;
            </div>
          </div>
        </template>
      </div>
      <img v-if="showPrize" class="close" src="./../assets/images/closebox@2x.png" @click="followAction" alt=""/>
    </div>
    

    css代码如下:

    // 奖品
    .prize {
      z-index: 5;
      position: absolute;
      left: 50%;
      margin-left: -118px;
      top: 190px;
      left: 50%;
       219px;
      height: 219px;
      background-size: 219px 219px;
      background-position: center;
      align-content: center;
      display: flex;
      align-items: center;
      justify-content: center;
      .img-prize {
           180px;
          height: 150px;
          z-index: 6;
      }
    }
    .prize:before {
      content: "";
      position: absolute;
      z-index: 4;
       110%;
      height: 110%;
      background: center / contain no-repeat url("../assets/images/prizebg@2x.png");
      animation: turn 6s linear infinite;
    }
    @keyframes turn{
      0% { -webkit-transform: rotate(0deg); }
      100%{ -webkit-transform: rotate(360deg); }
    }
    .prizetip {
      z-index: 6;
      position: relative;
      top: 380px;
      margin: 0 auto;
      font-size: 28px;
      font-family: HuipuMR;
      color: rgba(51, 51, 51, 1);
      height: 72px;
      @include flex(center, center, column, nowrap);
      div {
          height: 40px;
          line-height: 40px;
      }
    }
    .prizelead {
      position: relative;
      top: 525px;
      margin: 0 auto;
      max- 374px;
      height: 70px;
      display: flex;
      align-items: center;
      justify-content: center;
      background: linear-gradient(90deg, rgba(247, 231, 165, 1) 0%, rgba(255, 234, 114, 1) 100%);
      box-shadow: 0px 4px 8px 0px rgba(203, 68, 15, 1);
      border-radius: 40px;
      .content {
        text-align: center;
        font-size: 28px;
        color: rgba(191, 62, 11, 1);
        line-height: 38px;
        text-shadow: 0px 4px 8px rgba(203, 68, 15, 1);
      }
    }
    
    

    注意,显示了奖品之后我们还在奖品的背景,光芒四射图片上设置了一个旋转动画,这个相对简单,就是设置rotate从0deg到360deg。并且把这个背景使用了before伪类,这样就不用再弄一个dom层了。

    在最后加了一个关闭按钮,这个不再赘述。

    看下效果,如下图12
    image
    图12

    4. 总结

    本文介绍了如何使用css的animation动画实现一个开宝箱抽奖的功能,主要就是animation+keyframe,相对简单。

    作者:Tyler Ning
    出处:http://www.cnblogs.com/tylerdonet/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,请微信联系冬天里的一把火

  • 相关阅读:
    Job for apache2.service failed because the control process exited with error code. See "systemctl status apache2.service" and "journalctl -xe" for details.
    Jsonpath的基本使用
    [转]什么是CNN、RNN、LSTM
    [转]爬虫 selenium + phantomjs / chrome
    [转]js async await 终极异步解决方案
    [转]如何让多个不同类型的后端网站用一个nginx进行反向代理实际场景分析
    [转]java常用正则表达式
    [转]关于SSH与SSM的组成及其区别
    用live2d给自己的博客园加个小卡通,可以固定model也可以随机设置
    [转]关于/r与/n 以及 /r/n 的区别总结
  • 原文地址:https://www.cnblogs.com/tylerdonet/p/15164824.html
Copyright © 2020-2023  润新知