APIs
参数 |
说明 |
类型 |
默认值 |
必传 |
from |
数值动画起始数值 |
number |
0 |
false |
to |
数值目标值 |
number |
1000 |
false |
duration |
数值动画持续时间,单位ms |
number |
3000 |
false |
autoplay |
是否自动开始动画 |
boolean |
true |
false |
precision |
精度,保留小数点后几位 |
number |
0 |
false |
prefix |
前缀 |
string |
‘’ |
false |
suffix |
后缀 |
string |
‘’ |
false |
separator |
千分位分隔符 |
string |
‘,’ |
false |
decimal |
小数点字符 |
string |
‘.’ |
false |
valueStyle |
数值文本样式 |
CSSProperties |
{} |
false |
transition |
动画过渡效果 |
TransitionFunc |
TransitionFunc[‘easeInOutCubic’] |
false |
Methods
事件名称 |
说明 |
参数 |
play |
播放动画 |
() => void |
Events
事件名称 |
说明 |
参数 |
started |
动画开始播放 |
() => void |
finished |
动画播放完成 |
() => void |
创建数值动画组件NumberAnimation.vue
<script setup lang="ts">
import {
ref, computed, watchEffect, onMounted, watch } from 'vue'
import type {
CSSProperties } from 'vue'
import {
useTransition, TransitionPresets } from '@vueuse/core'
enum TransitionFunc {
linear = 'linear',
easeOutSine = 'easeOutSine',
easeInOutSine = 'easeInOutSine',
easeInQuad = 'easeInQuad',
easeOutQuad = 'easeOutQuad',
easeInOutQuad = 'easeInOutQuad',
easeInCubic = 'easeInCubic',
easeOutCubic = 'easeOutCubic',
easeInOutCubic = 'easeInOutCubic',
easeInQuart = 'easeInQuart',
easeOutQuart = 'easeOutQuart',
easeInOutQuart = 'easeInOutQuart',
easeInQuint = 'easeInQuint',
easeOutQuint = 'easeOutQuint',
easeInOutQuint = 'easeInOutQuint',
easeInExpo = 'easeInExpo',
easeOutExpo = 'easeOutExpo',
easeInOutExpo = 'easeInOutExpo',
easeInCirc = 'easeInCirc',
easeOutCirc = 'easeOutCirc',
easeInOutCirc = 'easeInOutCirc',
easeInBack = 'easeInBack',
easeOutBack = 'easeOutBack',
easeInOutBack = 'easeInOutBack'
}
interface Props {
from?: number
to?: number
duration?: number
autoplay?: boolean
precision?: number
prefix?: string
suffix?: string
separator?: string
decimal?: string
valueStyle?: CSSProperties
transition?: TransitionFunc
}
const props = withDefaults(defineProps<Props>(), {
from: 0,
to: 1000,
duration: 3000,
autoplay: true,
precision: 0,
prefix: '',
suffix: '',
separator: ',',
decimal: '.',
valueStyle: () => ({
}),
transition: TransitionFunc['easeInOutCubic']
})
const source = ref(props.from)
watchEffect(() => {
source.value = props.from
})
watch(
[() => props.from, () => props.to],
() => {
if (props.autoplay) {
play()
}
}
)
onMounted(() => {
props.autoplay && play()
})
const outputValue = useTransition(source, {
duration: props.duration,
transition: TransitionPresets[props.transition],
onFinished: () => emits('finished'),
onStarted: () => emits('started')
})
function play () {
source.value = props.to
}
const showValue = computed(() => formatNumber(outputValue.value))
function isNumber (val: any) {
return Object.prototype.toString.call(val) === '[object Number]'
}
const emits = defineEmits(['started', 'finished'])
function formatNumber (num: number | string) {
const {
precision, decimal, separator, suffix, prefix } = props
if (num === 0) {
return num.toFixed(precision)
}
if (!num) {
return ''
}
num = Number(num).toFixed(precision)
num += ''
const x = num.split('.')
let x1 = x[0]
const x2 = x.length > 1 ? decimal + x[1] : ''
const rgx = /(\d+)(\d{3})/
if (separator && !isNumber(separator)) {
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + separator + '$2')
}
}
return prefix + x1 + x2 + suffix
}
defineExpose({
play
})
</script>
<template>
<span :style="valueStyle">
{
{
showValue }}
</span>
</template>
在要使用的页面引入
<script setup lang="ts">
import NumberAnimation from 'NumberAnimation.vue'
import {
ref } from 'vue'
function onStarted () {
console.log('started')
}
function onFinished () {
console.log('finished')
}
const animationRef = ref()
function onClick () {
animationRef.value.play()
}
</script>
<template>
<div>
<h1>NumberAnimation 数值动画</h1>
<h2 class="mt30 mb10">基本使用</h2>
<Row>
<Col :span="12">
<Statistic title="一个小目标">
<NumberAnimation :to="100000000.12345" />
</Statistic>
</Col>
<Col :span="12">
<Statistic title="一个小目标">
<NumberAnimation :to="100000000.12345" separator="" />
</Statistic>
</Col>
</Row>
<h2 class="mt30 mb10">精度</h2>
<Row>
<Col :span="12">
<Statistic title="一个小目标">
<NumberAnimation :from="0.00" :to="100000000.12345" :precision="2" />
</Statistic>
</Col>
<Col :span="12">
<Statistic title="一个小目标">
<NumberAnimation :to="100000000.12345" :precision="3"/>
</Statistic>
</Col>
</Row>
<h2 class="mt30 mb10">自定义前缀 & 后缀</h2>
<Row>
<Col :span="12">
<Statistic title="一个小目标">
<NumberAnimation
prefix="$"
:from="0"
:to="100000000" />
</Statistic>
</Col>
<Col :span="12">
<Statistic title="一个小目标">
<NumberAnimation
:from="0"
:to="100000000"
suffix="元" />
</Statistic>
</Col>
</Row>
<h2 class="mt30 mb10">自定义样式</h2>
<Row>
<Col :span="12">
<Statistic title="一个小目标">
<NumberAnimation :value-style="{fontSize: '30px', fontWeight: 600, color: '#d4380d'}" :from="0" :to="100000000"/>
</Statistic>
</Col>
</Row>
<h2 class="mt30 mb10">自定义播放和动画时间</h2>
<Row>
<Col :span="12">
<Statistic title="一个小目标">
<NumberAnimation
ref="animationRef"
:from="0"
:to="100000000"
:duration="5000"
:precision="2"
:autoplay="false"
@started="onStarted"
@finished="onFinished" />
</Statistic>
<Button @click="onClick">播放</Button>
</Col>
</Row>
</div>
</template>