当前位置: 首页 > news >正文

Vue3进度条(Progress)

Vue2进度条(Progress)

可自定义设置以下属性:

  • 进度条宽度(width),单位 px,类型:string | number,默认 undefined;type: 'line' 时,为进度条宽度,默认值 '100%';type: 'circle' 时,为进度圈宽高,默认值 120

  • 当前进度百分比(percent),类型:number,默认 0

  • 进度条的尺寸(lineSize),单位 px,类型:number,默认 undefined;type: 'line' 时,为进度条线高,默认值 8;type: 'circle' 时,单位是进度圈画布宽度的百分比,默认值 6

  • 进度条的色彩(lineColor),类型:string | {'0%'?: string, '100%'?: string, from?: string, to?: string, direction?: 'left'|'right'},默认 undefined;传入 string 时为纯色,传入 object 时为渐变,进度圈时 direction: 'left' 为逆时针,direction: 'right' 为顺时针

  • 进度条边缘的形状(lineCap),类型:'round' | 'square',默认 'round'

  • 是否显示进度数值或状态图标(showInfo),类型:boolean,默认 true

  • 进度数值或状态图标的尺寸(infoSize),单位 px,类型:number,默认 undefined;type: 'line' 时,默认值 14;type: 'circle' 时,默认值 undefined

  • 进度完成时的信息(success),类型:string | slot,默认 undefined

  • 内容的模板函数(format),类型:(percent: number) => (string | number) | slot,默认:(percent: number) => percent + '%'

  • 进度条类型(type),类型:'line' | 'circle',默认 'line'

效果如下图:

在线预览

①创建进度条组件Progress.vue:

其中引入使用了以下工具函数:

  • 监听插槽存在 useSlotsExist
  • 获取依赖注入 useInject

<script setup lang="ts"> import { computed } from 'vue' import { useSlotsExist, useInject } from 'components/utils' export interface Gradient { '0%'?: string '100%'?: string from?: string to?: string direction?: 'left' | 'right' // 默认 'right' } export interface Props { width?: number | string // 进度条宽度,单位 px;type: 'line' 时,为进度条宽度,默认值 '100%';type: 'circle' 时,为进度圈宽高,默认值 120 percent?: number // 当前进度百分比 lineSize?: number // 进度条的尺寸,单位 px;type: 'line' 时,为进度条线高,默认值 8;type: 'circle' 时,单位是进度圈画布宽度的百分比,默认值 6 lineColor?: string | Gradient // 进度条的色彩,传入 string 时为纯色,传入 Gradient 时为渐变,进度圈时 direction: 'left' 为逆时针,direction: 'right' 为顺时针 lineCap?: 'round' | 'butt' // 进度条边缘的形状 showInfo?: boolean // 是否显示进度数值或状态图标 infoSize?: number // 进度数值或状态图标的尺寸,单位 px;type: 'line' 时,默认值 14;type: 'circle' 时,默认值 24 success?: string // 进度完成时的信息 string | slot format?: (percent: number) => string | number // 内容的模板函数 function | slot type?: 'line' | 'circle' // 进度条类型 } const props = withDefaults(defineProps<Props>(), { width: undefined, percent: 0, lineSize: undefined, lineColor: undefined, lineCap: 'round', showInfo: true, infoSize: undefined, success: undefined, format: (percent: number) => percent + '%', type: 'line' }) const { colorPalettes } = useInject('Progress') // 主题色注入 const slotsExist = useSlotsExist(['success']) // 进度条宽度/进度圈宽高 const progressSize = computed(() => { if (props.width === undefined) { if (props.type === 'line') { return '100%' } if (props.type === 'circle') { return '120px' } } return typeof props.width === 'number' ? `${props.width}px` : props.width }) // 进度条高度;进度圈线宽 const progressLineSize = computed(() => { if (props.lineSize === undefined) { if (props.type === 'line') { return 8 } if (props.type === 'circle') { return 6 } } return props.lineSize as number }) // 进度条/圈进度数值或状态图标尺寸 const progressInfoSize = computed(() => { if (props.infoSize === undefined) { if (props.type === 'line') { return '14px' } if (props.type === 'circle') { return '24px' } } return `${props.infoSize}px` }) // 圆条周长 const perimeter = computed(() => { return (100 - progressLineSize.value) * Math.PI }) // 圆条轨道路径指令 const path = computed(() => { const long = 100 - progressLineSize.value return `M 50,50 m 0,-${long / 2} a ${long / 2},${long / 2} 0 1 1 0,${long} a ${long / 2},${long / 2} 0 1 1 0,-${long}` }) // 是否为渐变色 const isGradientColor = computed(() => { if (props.lineColor !== undefined && typeof props.lineColor !== 'string') { return true } return false }) // 进度条/圈颜色 const lineColorComputed = computed(() => { if (props.lineColor === undefined) { return colorPalettes.value[5] } else if (typeof props.lineColor === 'string') { return props.lineColor } else { return `linear-gradient(to ${props.lineColor.direction || 'right'}, ${props.lineColor['0%'] || props.lineColor.from}, ${props.lineColor['100%'] || props.lineColor.to})` } }) // 进度圈渐变色 id const circleGradient = computed(() => { if (isGradientColor.value) { const gradientColor = props.lineColor as Gradient if (gradientColor.direction === undefined || gradientColor.direction === 'right') { return `right-${gradientColor['0%'] || gradientColor.from}-${gradientColor['100%'] || gradientColor.to}` } return `left-${gradientColor['100%'] || gradientColor.to}-${gradientColor['0%'] || gradientColor.from}` } return null }) const circleColorFrom = computed(() => { if (isGradientColor.value) { const gradientColor = props.lineColor as Gradient if (gradientColor.direction === undefined || gradientColor.direction === 'right') { return gradientColor['0%'] || gradientColor.from } else { return gradientColor['100%'] || gradientColor.to } } return }) const circleColorTo = computed(() => { if (isGradientColor.value) { const gradientColor = props.lineColor as Gradient if (!gradientColor.direction || gradientColor.direction === 'right') { return gradientColor['100%'] || gradientColor.to } else { return gradientColor['0%'] || gradientColor.from } } return }) const showPercent = computed(() => { return props.format(props.percent > 100 ? 100 : props.percent) }) const showSuccess = computed(() => { return slotsExist.success || props.success }) </script> <template> <div v-if="type === 'line'" class="progress-line-wrap" :style="` --progress-size: ${progressSize}; --progress-primary-color: ${lineColorComputed}; --progress-success-color: #52c41a; --progress-font-size: ${progressInfoSize}; --progress-border-radius: ${lineCap === 'round' ? '100px' : 0}; `" > <div class="progress-inner"> <div :class="['progress-bg', { 'line-success': percent >= 100 && !isGradientColor }]" :style="`width: ${percent >= 100 ? 100 : percent}%; height: ${progressLineSize}px;`" ></div> </div> <template v-if="showInfo"> <Transition name="fade" mode="out-in"> <span v-if="percent >= 100" class="progress-success"> <svg v-if="showSuccess === undefined" class="icon-svg" focusable="false" ><script setup lang="ts"> import Progress from './Progress.vue' import { ref } from 'vue' import { MinusOutlined, PlusOutlined } from '@ant-design/icons-vue' import type { ProgressProps } from 'vue-amazing-ui' const percent = ref(80) const lineCapOptions = [ { label: 'round', value: 'round' }, { label: 'butt', value: 'butt' } ] const lineCap = ref<ProgressProps['lineCap']>('butt') function onIncrease(scale: number) { const res = percent.value + scale if (res > 100) { percent.value = 100 } else { percent.value = res } } function onDecline(scale: number) { const res = percent.value - scale if (res < 0) { percent.value = 0 } else { percent.value = res } } </script> <template> <div style="width: 900px"> <h1>{{ $route.name }} {{ $route.meta.title }}</h1> <h2 class="mt30 mb10">基本使用</h2> <Progress :percent="percent" /> <h2 class="mt30 mb10">进度圈</h2> <Space align="center"> <Progress type="circle" :percent="percent" /> <Button @click="onDecline(5)" size="large" :icon="MinusOutlined">Decline</Button> <Button @click="onIncrease(5)" size="large" :icon="PlusOutlined">Increase</Button> </Space> <h2 class="mt30 mb10">完成进度条</h2> <Flex vertical> <Progress :percent="100" /> <Progress type="circle" :percent="100" /> </Flex> <h2 class="mt30">渐变进度条</h2> <h3 class="mb10"> strokeColor: { '0%': '#108ee9', '100%': '#87d068', direction: 'right' } 或 { from: '#108ee9', to: '#87d068', direction: 'right' } </h3> <Flex vertical> <Progress :line-color="{ '0%': '#108ee9', '100%': '#87d068' }" :percent="percent" /> <Space align="center"> <Progress type="circle" :line-color="{ '0%': '#108ee9', '100%': '#87d068' }" :percent="percent" /> <Button @click="onDecline(5)" size="large" :icon="MinusOutlined">Decline</Button> <Button @click="onIncrease(5)" size="large" :icon="PlusOutlined">Increase</Button> </Space> </Flex> <h2 class="mt30 mb10">自定义样式</h2> <Flex vertical> <Progress style="--progress-success-color: #ff6900" :line-size="24" :line-color="{ '0%': '#108ee9', '100%': '#87d068', direction: 'left' }" :info-size="24" :percent="percent" /> <Space align="center"> <Progress style="--progress-success-color: #ff6900" type="circle" :width="180" :line-size="14" :line-color="{ '0%': '#108ee9', '100%': '#87d068', direction: 'left' }" :info-size="28" :percent="percent" /> <Button @click="onDecline(5)" size="large" :icon="MinusOutlined">Decline</Button> <Button @click="onIncrease(5)" size="large" :icon="PlusOutlined">Increase</Button> </Space> </Flex> <h2 class="mt30 mb10">自定义边缘形状</h2> <Flex vertical> <Radio :options="lineCapOptions" v-model:value="lineCap" button button-style="solid" /> <Progress :line-size="20" :line-color="{ '0%': 'white', '100%': 'pink' }" :line-cap="lineCap" :info-size="20" :percent="percent" /> <Space align="center"> <Progress type="circle" :width="160" :line-size="12" :line-color="{ '0%': '#e3f2fd', '100%': '#2080f0' }" :line-cap="lineCap" :info-size="24" :percent="percent" /> <Button @click="onDecline(5)" size="large" :icon="MinusOutlined">Decline</Button> <Button @click="onIncrease(5)" size="large" :icon="PlusOutlined">Increase</Button> </Space> </Flex> <h2 class="mt30 mb10">自定义文字</h2> <Flex vertical> <Progress :line-size="20" :info-size="20" :percent="percent" :format="(percent: number) => `$${percent}`" success="Done" /> <Progress style="--success-color: #d48806" :line-size="20" :info-size="20" :percent="percent"> <template #format="{ percent }"> <span style="color: #d4380d">{{ percent }}%</span> </template> <template #success> <span style="color: #d48806">Bingo</span> </template> </Progress> <Space align="center"> <Progress type="circle" :width="160" :line-size="12" :info-size="24" :percent="percent" :format="(percent: number) => `${percent} Days`" success="Done" /> <Progress style="--success-color: #d48806" type="circle" :width="160" :line-size="12" :info-size="24" :percent="percent" > <template #format="{ percent }"> <span style="color: #d4380d">{{ percent }}%</span> </template> <template #success> <span style="color: #d48806">Bingo</span> </template> </Progress> <Button @click="onDecline(5)" size="large" :icon="MinusOutlined">Decline</Button> <Button @click="onIncrease(5)" size="large" :icon="PlusOutlined">Increase</Button> </Space> </Flex> </div> </template>
http://www.cnnetsun.cn/news/4287901.html

相关文章:

  • 2026年AI论文平台推荐:9款高效AI工具一站式清单
  • DSP算法FPGA实现:从理论到硬件的完整工程链路与实践指南
  • mermaid流程图
  • 千问本地部署实战:从Ollama到Spring AI的完整接入指南
  • 前端工程协作的构建与发布
  • IBASE MI1001 Mini-ITX工业主板:边缘计算与工控替换的可靠之选
  • REDRIVER2:PS1经典游戏《Driver 2》的现代C++重实现与逆向工程解析
  • C++ I/O流与模板编程:从基础原理到实战应用
  • AI+3D人体解剖可视化工具的技术实现与搭建指南
  • 创业产品如何识别价值主张和替代方案
  • 转向系统编程的选型方法
  • ai文章怎么去掉ai痕迹?朱雀AIGC检测后怎样降AI率又保留品牌事实
  • 从自我造题到自我迭代:35B模型如何用数据飞轮逼近万亿参数
  • 皮尔逊相关系数:从原理到实战,避开数据分析中的常见陷阱
  • 第二代Open Virtual Platforms API:从组件化建模到多核虚拟平台实战
  • 【算法】数字滤波
  • 基于TensorFlow与CNN的猫狗识别实战:从环境搭建到模型部署
  • 跨端界面选型看真实页面
  • WinForm应用实战开发指南 - 应用程序如何实现手写签名?
  • 效率工具评审从用户任务出发
  • STM8 I2C BUSY位卡死排查与恢复:从寄存器状态到总线释放方案
  • DV-1100边缘计算工控机选型与部署实战:从车载到产线
  • 蓝桥杯国赛真题深度解析:Java算法实战与避坑指南
  • Vue3折叠面板(Collapse)
  • 唯品会校招数据结构笔试题复盘:链表、二叉树与排序考点全解析
  • curl接口健康检查
  • Linux(CentOS)系统安装mysql8流程
  • Floyd算法全解析:动态规划求所有点对最短路径的原理与实现
  • ADS8866三线SPI模式驱动开发与高速通信调试实战
  • 机器视觉1