分享一个自用的数字翻牌器效果的vue组件

2024-12-18 18点热度 0人点赞 0条评论

效果动画图:

完整代码如下

<template>
  <div class="number-flip">
    <div class="box-item" v-for="(digit, index) in digits" :key="index">
      <span class="item-num" ref="spanRefs">0123456789</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { reactive, ref, watch, onMounted } from 'vue'

const props = defineProps<{
  number: number,
  enableInitialAnimation?: boolean // 是否启用初始动画
}>()

const spanRefs = ref<HTMLElement[]>([])
const digits = ref<number[]>([])

// 将数字转换为数字数组
const updateDigits = (num: number) => {
  digits.value = String(num).split('').map(Number)
}

// 更新数字位置
const updateDigitPositions = (withTransition = true) => {
  requestAnimationFrame(() => {
    spanRefs.value.forEach((span, index) => {
      if (span) {
        if (!withTransition) {
          // 临时移除过渡效果
          span.style.transition = 'none'
        }
        span.style.transform = `translate(-50%, -${digits.value[index] * 10}%)`
        if (!withTransition) {
          // 强制浏览器重绘
          span.offsetHeight
          // 恢复过渡效果
          span.style.transition = ''
        }
      }
    })
  })
}

// 初始化
onMounted(() => {
  updateDigits(props.number)
  updateDigitPositions(props.enableInitialAnimation)
})

// 监听数字变化
watch(() => props.number, (newVal) => {
  updateDigits(newVal)
  updateDigitPositions(true) // 数字变化时总是启用动画
})
</script>

<style lang="less" scoped>
.number-flip {
  display: inline-flex;
  align-items: center;
  
  .box-item {
    width: 0.8em;
    height: 1.4em;
    border-radius: 2px;
    position: relative;
    margin: 0 1px;
    overflow: hidden;

    .item-num {
      position: absolute;
      top: 1%;
      left: 40%;
      font-weight: bold;
      transform: translateX(-50%);
      writing-mode: vertical-lr;
      text-orientation: upright;
      transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
      line-height: 1.6;
      letter-spacing: 0.2em;
      font-size: 1.2em;
    }
  }
}
</style>

使用方式如下:

<NumberTransition :number="savedCnt" :enable-initial-animation="false" style="color:blue;font-weight:bold;vertical-align: middle;"/>

admin

这个人很懒,什么都没留下

文章评论

您需要 登录 之后才可以评论