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,24 @@
import { buildProps } from '../../../utils'
import { propgressBaseProps } from '../../base/common-props/progress'
import type { ExtractPropTypes } from 'vue'
export const circleProgressProps = buildProps({
...propgressBaseProps,
/**
* @description 圆环的半径,单位 px,只支持传递固定的值
*/
radius: {
type: Number,
default: 50,
},
/**
* @description 圆环的宽度,单位 px,只支持传递固定的值
*/
ringWidth: {
type: Number,
default: 7,
},
})
export type CircleProgressProps = ExtractPropTypes<typeof circleProgressProps>
@@ -0,0 +1,29 @@
<script lang="ts" setup>
import { circleProgressProps } from './circle-progress'
import { useCircleProgress } from './composables'
const props = defineProps(circleProgressProps)
const { ns, canvasId, radius, activeCircleColor } = useCircleProgress(props)
</script>
<template>
<view
:class="[ns.b()]"
:style="{
width: `${radius * 2}px`,
height: `${radius * 2}px`,
color: activeCircleColor,
}"
>
<!-- 默认圆环 -->
<canvas :id="canvasId" :class="[ns.e('canvas')]" :canvas-id="canvasId" />
<!-- 数值 -->
<view v-if="showPercent || $slots.default" :class="[ns.e('precent-value')]">
<slot> {{ percent }}% </slot>
</view>
</view>
</template>
<style lang="scss" scoped>
@import '../../../theme-chalk/src/circle-progress.scss';
</style>
@@ -0,0 +1 @@
export * from './use-circle-progress'
@@ -0,0 +1,146 @@
import { computed, getCurrentInstance, nextTick, watch } from 'vue'
import { useNamespace } from '../../../../hooks'
import { generateId, isEmptyVariableInDefault } from '../../../../utils'
import type { ComponentInternalInstance } from 'vue'
import type { CircleProgressProps } from '../circle-progress'
export const useCircleProgress = (props: CircleProgressProps) => {
const instance = getCurrentInstance() as ComponentInternalInstance
const ns = useNamespace('circle-progress')
// 圆环的直径
const radius = computed<number>(() => {
return isEmptyVariableInDefault(props?.radius, 50)
})
// 圆环的宽度
const ringWidth = computed<number>(() => {
return isEmptyVariableInDefault(props?.ringWidth, 14)
})
// 圆环的颜色
const circleColor = computed<string>(() => {
return isEmptyVariableInDefault(props?.inactiveColor, '#e6e6e6')
})
// 圆环激活时的颜色
const activeCircleColor = computed<string>(() => {
return isEmptyVariableInDefault(props?.activeColor, '#01beff')
})
// 动画执行时间
const duration = computed<number>(() => {
return isEmptyVariableInDefault(props?.duration, 1500)
})
// 进度信息,为了产生动画效果,需要在进度条变化时,将进度信息保存下来
let currentPercent = 0
let prevPercent = 0
// 生成canvas圆环id
const canvasId = String(generateId())
// canvas容器对象
let progressCanvas: UniApp.CanvasContext | null = null
// 圆环开始角度
const startAngle = -90 * (Math.PI / 180)
// 绘制progress圆环
const drawProgressCircle = (percent: number) => {
if (!progressCanvas) {
progressCanvas = uni.createCanvasContext(canvasId, instance)
}
// 清空画布
progressCanvas.clearRect(0, 0, radius.value * 2, radius.value * 2)
// 绘制底部圆环
progressCanvas.beginPath()
// 设置颜色\线框
progressCanvas.setLineWidth(ringWidth.value)
progressCanvas.setStrokeStyle(circleColor.value)
// 绘制圆环
progressCanvas.arc(
radius.value,
radius.value,
radius.value - ringWidth.value / 2,
startAngle,
Math.PI * 1.5,
false
)
progressCanvas.stroke()
// 如果进度为0,不绘制进度圆环
if (percent === 0) {
progressCanvas.draw()
return
}
// 绘制进度圆环
progressCanvas.beginPath()
// 设置颜色\线框
progressCanvas.setLineCap('round')
progressCanvas.setLineWidth(ringWidth.value)
progressCanvas.setStrokeStyle(activeCircleColor.value)
// 结束角度
const endAngle = (Math.PI * 2 * percent) / 100 - Math.PI / 2
progressCanvas.arc(
radius.value,
radius.value,
radius.value - ringWidth.value / 2,
startAngle,
endAngle,
false
)
progressCanvas.stroke()
progressCanvas.draw()
}
// 计算缓动动画时间函数
function easeOutCubic(t: number, b: number, c: number, d: number) {
return c * ((t = t / d - 1) * t * t + 1) + b
}
// 开始执行动画
let startTime: number | null = null
const progressAnimation = () => {
if (!startTime) startTime = Date.now()
const elapsed = Date.now() - startTime
let percent = easeOutCubic(
elapsed,
prevPercent,
currentPercent - prevPercent,
duration.value
)
if (percent < 0) percent = 0
drawProgressCircle(percent)
if (elapsed < duration.value) {
setTimeout(progressAnimation, 16)
}
}
watch(
() => props.percent,
(nVal: number, oVal: number | undefined) => {
currentPercent = nVal > 100 ? 100 : nVal
prevPercent = !oVal || oVal < 0 ? 0 : oVal
nextTick(() => {
startTime = null
progressAnimation()
})
},
{
immediate: true,
}
)
return {
ns,
canvasId,
radius,
activeCircleColor,
}
}
@@ -0,0 +1,3 @@
import type CircleProgress from './circle-progress.vue'
export type TnCircleProgressInstance = InstanceType<typeof CircleProgress>