翻牌器

翻牌器

ScrollCom.vue
<template>
  <ul class="flex">
    <ScrollNum
      v-for="(num, idx) of numArr"
      :key="idx"
      as="li"
      :i="num"
      :delay="idx + 1"
    />
  </ul>
</template>

<script>
import ScrollNum from '/ScrollNum.vue'

export default {
  name: 'ScrollCom',
  components: { ScrollNum },
  data: () => ({ num: 886 }),
  computed: {
    numArr () {
      const str = String(this.num)
      let arr = []

      for (let i = 0; i < str.length; i++) {
        arr.push(parseInt(str[i]))
      }

      return arr
    }
  },
  mounted () {
    setInterval(() => this.num++, 10000)
  }
}
</script>

<style scoped>
.flex {
  display: flex;
}
ul {
  padding: 0;
  margin: 0;
  list-style: none;
}
</style>
ScrollNum.vue
<template>
  <component
    :is="as"
    class="scroll-num"
    :class="{ 'border-animate': showAnimate }"
    :style="{ '--i': i, '--delay': delay }"
    @animationend="showAnimate = false"
  >
    <ul ref="ul" :class="{ animate: showAnimate }">
      <li>0</li>
      <li v-for="item in 9" :key="item">{{ item }}</li>
      <li>0</li>
    </ul>

    <svg width="0" height="0">
      <filter id="blur">
        <feGaussianBlur in="SourceGraphic" :stdDeviation="`0 ${blur}`" />
      </filter>
    </svg>
  </component>
</template>

<script>
export default {
  name: 'ScrollNum',
  props: {
    as: {
      type: String,
      default: 'div'
    },
    i: {
      type: Number,
      default: 0,
      validator: v => v < 10 && v >= 0 && Number.isInteger(v)
    },
    delay: {
      type: Number,
      default: 1
    },
    blur: {
      type: Number,
      default: 2
    }
  },
  data: () => ({
    timer: null,
    showAnimate: true
  }),
  watch: { i () { this.showAnimate = true } },
  mounted () {
    const ua = navigator.userAgent.toLowerCase()
    const testUA = regexp => regexp.test(ua)
    const isSafari = testUA(/safari/g) && !testUA(/chrome/g)

    // Safari浏览器的兼容代码
    isSafari && (this.timer = setTimeout(() => {
      this.$refs.ul.setAttribute('style', `
        animation: none;
        transform: translateY(calc(var(--i) * -9.09%))
      `)
    }, this.delay * 1000))
  },
  beforeUnmount () { clearTimeout(this.timer) }
}
</script>

<style scoped>
.scroll-num {
   var(--width, 20px);
  /* var(自定义值, 默认值) */
  height: var(--height, calc(var(--width, 20px) * 1.8));
  color: var(--color, #333);
  font-size: var(--height, calc(var(--width, 20px) * 1.1));
  line-height: var(--height, calc(var(--width, 20px) * 1.8));
  text-align: center;
  overflow: hidden;
}

.animate {
  animation: move 0.3s linear infinite,
    bounce-in-down 1s calc(var(--delay) * 1s) forwards;
}
.border-animate {
  animation: enhance-bounce-in-down 1s calc(var(--delay) * 1s) forwards;
}

ul {
  padding: 0;
  margin: 0;
  list-style: none;
  transform: translateY(calc(var(--i) * -9.09%));
}

@keyframes move {
  from {
    transform: translateY(-90%);
    filter: url(#blur);
  }
  to {
    transform: translateY(1%);
    filter: url(#blur);
  }
}

@keyframes bounce-in-down {
  from {
    transform: translateY(calc(var(--i) * -9.09% - 7%));
    filter: none;
  }
  25% {
    transform: translateY(calc(var(--i) * -9.09% + 3%));
  }
  50% {
    transform: translateY(calc(var(--i) * -9.09% - 1%));
  }
  70% {
    transform: translateY(calc(var(--i) * -9.09% + 0.6%));
  }
  85% {
    transform: translateY(calc(var(--i) * -9.09% - 0.3%));
  }
  to {
    transform: translateY(calc(var(--i) * -9.09%));
  }
}

@keyframes enhance-bounce-in-down {
  25% {
    transform: translateY(8%);
  }
  50% {
    transform: translateY(-4%);
  }
  70% {
    transform: translateY(2%);
  }
  85% {
    transform: translateY(-1%);
  }
  to {
    transform: translateY(0);
  }
}
</style>
请用今天的努力,让明天没有遗憾。
原文地址:https://www.cnblogs.com/cupid10/p/15325523.html