2025/2/8第一次更新

This commit is contained in:
爱吃咸鱼小猫咪
2025-02-08 18:50:38 +08:00
commit d7af560866
26519 changed files with 5046029 additions and 0 deletions
@@ -0,0 +1,43 @@
import { computed, toRef } from 'vue'
import { useComponentColor, useNamespace } from '../../../../hooks'
import { formatDomSizeValue } from '../../../../utils'
import type { CSSProperties } from 'vue'
import type { CountToProps } from '../count-to'
export const useCountToCustomStyle = (props: CountToProps) => {
const ns = useNamespace('count-to')
// 解析文字颜色
const [textColorClass, textColorStyle] = useComponentColor(
toRef(props, 'textColor'),
'text'
)
// countTo对应的类
const countToClass = computed<string>(() => {
const cls: string[] = [ns.b()]
if (textColorClass.value) cls.push(textColorClass.value)
return cls.join(' ')
})
// countTo对应的样式
const countToStyle = computed<CSSProperties>(() => {
const style: CSSProperties = {}
if (!textColorClass.value) {
style.color = textColorStyle.value || 'var(--tn-text-color-primary)'
}
if (props.fontSize) style.fontSize = formatDomSizeValue(props.fontSize)
return style
})
return {
ns,
countToClass,
countToStyle,
}
}
@@ -0,0 +1,2 @@
export * from './count-to-custom'
export * from './use-count-to'
@@ -0,0 +1,114 @@
import { computed, ref, watch } from 'vue'
import { isEmptyVariableInDefault } from '../../../../utils'
import type { SetupContext } from 'vue'
import type { CountToEmits, CountToProps } from '../count-to'
export const useCountTo = (
props: CountToProps,
emits: SetupContext<CountToEmits>['emit']
) => {
// 开始值
const startValue = computed<number>(() =>
Number(isEmptyVariableInDefault(props.start, 0))
)
// 结束值
const endValue = computed<number>(() =>
Number(isEmptyVariableInDefault(props.end, 0))
)
// 判断是往下计数还是往上计数
const countDown = computed<boolean>(() => startValue.value > endValue.value)
// 动画执行时间
const duration = computed<number>(() =>
isEmptyVariableInDefault(props.duration, 1500)
)
// 待显示的内容
const content = ref<string>('')
// 格式化需要显示的内容
const _formatContent = (value: number) => {
const throusandNumberReg = /(\d+)(\d{3})/
const valueStr = value.toFixed(props.decimals)
const valueArr = valueStr.split('.')
let firestValue = valueArr[0]
let secondValue = ''
if (valueArr.length > 1) {
secondValue = `${isEmptyVariableInDefault(props.decimalSeparator, '.')}${
valueArr[1]
}`
}
if (props?.thousandsSeparator) {
while (throusandNumberReg.test(firestValue)) {
firestValue = firestValue.replace(
throusandNumberReg,
`$1${props.thousandsSeparator}$2`
)
}
}
return `${firestValue}${secondValue}`
}
// 计算缓动动画时间函数
function _easeOutCubic(t: number, b: number, c: number, d: number) {
return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b
}
/* 数值动画操作 start */
// 动画执行开始时间
let startTime: number | null = null
// 开始执行动画
const countToAnimation = () => {
if (!startTime) startTime = Date.now()
const elapsed = Date.now() - startTime
let currentValue = 0
if (countDown.value) {
currentValue =
startValue.value -
_easeOutCubic(
elapsed,
0,
startValue.value - endValue.value,
duration.value
)
currentValue =
currentValue < endValue.value ? endValue.value : currentValue
} else {
currentValue = _easeOutCubic(
elapsed,
startValue.value,
endValue.value - startValue.value,
duration.value
)
currentValue =
currentValue > endValue.value ? endValue.value : currentValue
}
content.value = _formatContent(currentValue)
if (elapsed < duration.value) {
// 使用settimeout来模拟requestAnimationFrame
setTimeout(countToAnimation, 16)
} else {
// 动画执行结束
emits('end')
}
}
/* 数值动画操作 end */
// 监听endValue和startValue的变化
watch(
[endValue, startValue],
() => {
startTime = null
countToAnimation()
},
{
immediate: true,
}
)
return {
content,
}
}
@@ -0,0 +1,63 @@
import { buildProps } from '../../../utils'
import type { ExtractPropTypes } from 'vue'
export const countToProps = buildProps({
/**
* @description 开始的值
*/
start: {
type: [String, Number],
default: 0,
},
/**
* @description 结束的值
*/
end: {
type: [String, Number],
required: true,
},
/**
* @description 文字颜色,以tn开头则使用图鸟内置的颜色
*/
textColor: String,
/**
* @description 字体大小,默认单位 rpx
*/
fontSize: String,
/**
* @description 显示小数的位数
*/
decimals: {
type: Number,
default: 0,
},
/**
* @description 小数点的分隔符
*/
decimalSeparator: {
type: String,
default: '.',
},
/**
* @description 千分位的分隔符,如果不填写则为没有千分位
*/
thousandsSeparator: String,
/**
* @description 动画执行时间,单位毫秒
*/
duration: {
type: Number,
default: 1500,
},
})
export const countToEmits = {
/**
* @description 数字变化结束时触发
*/
end: () => true,
}
export type CountToProps = ExtractPropTypes<typeof countToProps>
export type CountToEmits = typeof countToEmits
@@ -0,0 +1,20 @@
<script lang="ts" setup>
import { countToEmits, countToProps } from './count-to'
import { useCountTo, useCountToCustomStyle } from './composables'
const props = defineProps(countToProps)
const emits = defineEmits(countToEmits)
const { countToClass, countToStyle } = useCountToCustomStyle(props)
const { content } = useCountTo(props, emits)
</script>
<template>
<view :class="[countToClass]" :style="countToStyle">
{{ content }}
</view>
</template>
<style lang="scss" scoped>
@import '../../../theme-chalk//src/count-to.scss';
</style>
@@ -0,0 +1,3 @@
import type CountTo from './count-to.vue'
export type TnCountToInstance = InstanceType<typeof CountTo>