Skip to content

CircleProgress 环形进度条 ​

17:06

说明 ​

环形进度条,用圆环弧长表达 0–100 的进度值。全平台统一使用 canvas 2d 绘制(背景弧与进度弧画在同一画布),percent 变化时按 duration 平滑过渡;默认插槽用于在圆心放置自定义内容(如百分比文字)。

兼容性 ​

平台支持情况
App✅ 支持
H5✅ 支持
微信小程序✅ 支持

示例 ​

basic ​

传入 percent 设置进度值,并用默认插槽在圆心放置百分比文字。

查看源码
vue
<template>
    <view class="wrap">
        <ux-circle-progress :percent="65" type="primary">
            <text class="percent">65%</text>
        </ux-circle-progress>
    </view>
</template>

<style scoped>
.wrap {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    padding: 20px 0;
}
.percent {
    font-size: 20px;
    font-weight: bold;
    color: #303133;
}
</style>

type ​

通过 type 配置 primary / success / warning / error / info 五种主题色,设置后 active-color 失效。

查看源码
vue
<template>
    <view class="row">
        <view class="item" v-for="(item, index) in typeList" :key="index">
            <ux-circle-progress :percent="70" :type="item.type" :width="80">
                <text class="percent-small">70%</text>
            </ux-circle-progress>
        </view>
    </view>
</template>

<script setup lang="uts">
const typeList = [
    { type: 'primary', label: 'primary' },
    { type: 'success', label: 'success' },
    { type: 'warning', label: 'warning' },
    { type: 'error', label: 'error' },
    { type: 'info', label: 'info' }
];
</script>

<style scoped>
.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    padding: 10px 0 5px;
}
.item {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 15px;
    padding: 0 12px;
}
.percent-small {
    font-size: 13px;
    font-weight: bold;
    color: #303133;
}
</style>

size ​

通过 width 设置圆环整体宽度(高度等于宽度),border-width 设置环的线宽,单位均为 px。

查看源码
vue
<template>
    <view class="row">
        <view class="item">
            <ux-circle-progress :percent="60" type="primary" :width="70" :border-width="4">
                <text class="percent-small">60%</text>
            </ux-circle-progress>
            <text class="label">140</text>
        </view>
        <view class="item">
            <ux-circle-progress :percent="60" type="primary" :width="100" :border-width="7">
                <text class="percent">60%</text>
            </ux-circle-progress>
            <text class="label">200</text>
        </view>
        <view class="item">
            <ux-circle-progress :percent="60" type="primary" :width="120" :border-width="12">
                <text class="percent-small">60%</text>
            </ux-circle-progress>
            <text class="label">240</text>
        </view>
    </view>
</template>

<style scoped>
.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    padding: 10px 0 5px;
}
.item {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 15px;
    padding: 0 12px;
}
.percent {
    font-size: 20px;
    font-weight: bold;
    color: #303133;
}
.percent-small {
    font-size: 13px;
    font-weight: bold;
    color: #303133;
}
.label {
    margin-top: 6px;
    font-size: 12px;
    color: #c0c4cc;
}
</style>

dynamic ​

percent 为响应式值时,变化会带动画重绘圆环;示例通过按钮增减进度。

查看源码
vue
<template>
    <view class="wrap">
        <ux-circle-progress :percent="percent" type="success">
            <text class="percent">{{ percent + '%' }}</text>
        </ux-circle-progress>
    </view>
    <view class="btn-row">
        <view class="btn" @click="reduce">
            <text class="btn-text">-</text>
        </view>
        <text class="btn-value">{{ percent + '%' }}</text>
        <view class="btn" @click="add">
            <text class="btn-text">+</text>
        </view>
    </view>
</template>

<script setup lang="uts">
const percent = ref<number>(65);

function add(): void {
    percent.value = Math.min(percent.value + 10, 100);
}

function reduce(): void {
    percent.value = Math.max(percent.value - 10, 0);
}
</script>

<style scoped>
.wrap {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    padding: 20px 0;
}
.percent {
    font-size: 20px;
    font-weight: bold;
    color: #303133;
}
.btn-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    margin-top: 10px;
}
.btn {
    width: 40px;
    height: 40px;
    border-radius: 40px;
    background-color: #2979ff;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
}
.btn-text {
    font-size: 22px;
    color: #ffffff;
    line-height: 22px;
}
.btn-value {
    font-size: 18px;
    font-weight: bold;
    color: #303133;
    margin: 0 20px;
    min-width: 60px;
    text-align: center;
}
</style>

custom ​

通过 active-color / inactive-color 自定义激活色与底色,bg-color 设置组件背景色,duration 控制画一圈的动画时长。

查看源码
vue
<template>
    <view class="wrap">
        <ux-circle-progress
            :percent="percent"
            :active-color="activeColor"
            :inactive-color="inactiveColor"
            :bg-color="bgColor"
            :duration="duration"
        >
            <text class="percent">{{ percent + '%' }}</text>
        </ux-circle-progress>
    </view>
    <view class="btn-row">
        <view class="btn" @click="reduce">
            <text class="btn-text">-</text>
        </view>
        <text class="btn-value">{{ percent + '%' }}</text>
        <view class="btn" @click="add">
            <text class="btn-text">+</text>
        </view>
    </view>
</template>

<script setup lang="uts">
const percent = ref<number>(80);
const activeColor = '#19be6b';
const inactiveColor = '#ebeef5';
const bgColor = '#f4f6f8';
const duration = 2000;

function add(): void {
    percent.value = Math.min(percent.value + 10, 100);
}

function reduce(): void {
    percent.value = Math.max(percent.value - 10, 0);
}
</script>

<style scoped>
.wrap {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    padding: 20px 0;
}
.percent {
    font-size: 20px;
    font-weight: bold;
    color: #303133;
}
.btn-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    margin-top: 10px;
}
.btn {
    width: 40px;
    height: 40px;
    border-radius: 40px;
    background-color: #19be6b;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
}
.btn-text {
    font-size: 22px;
    color: #ffffff;
    line-height: 22px;
}
.btn-value {
    font-size: 18px;
    font-weight: bold;
    color: #303133;
    margin: 0 20px;
    min-width: 60px;
    text-align: center;
}
</style>

API ​

Props ​

属性说明类型默认值版本
customStyle自定义根节点样式UTSJSONObject--
customClass自定义根节点样式类string''-
percent圆环进度百分比,0-100number0-
inactiveColor圆环的底色string''-
activeColor圆环激活部分颜色string''-
width整个圆环组件的宽度,单位 pxnumber | string100-
borderWidth圆环的边框宽度,单位 pxnumber | string7-
duration整个圆环画一圈的时间,单位 msnumber | string1500-
type主题类型string''-
bgColor整个组件背景颜色string''-

Events ​

ux-circle-progress 无事件。

Slots ​

插槽名说明版本
default圆心内容(通常放百分比文字),通过绝对定位居中显示-

注意事项 ​

  1. percent 会先被钳制到 0–100 再绘制,传入超范围值不会越界。
  2. type 优先于 activeColor:设置 type 后 activeColor 失效;两者都不传时回退主题 success 色。
  3. 组件宽高相等(height 等于 width),圆环半径 = width / 2 - borderWidth;请保证 borderWidth 小于 width / 2,否则圆环会退化。
  4. 圆环由 canvas 2d 绘制,圆心内容需通过默认插槽放入,组件不会自动生成百分比文字(与线型进度条不同)。
  5. duration 是画满一圈的耗时,单次动画时长与本次进度增量成正比(例如追加 5% 约耗时 duration / 100 × 5 ms),并非每次都走满 duration。
  6. bgColor 默认为透明,只有显式传入时才给整个组件上背景色(避免圆环外围出现实心色块)。
  7. 画布上下文通过 uni.createCanvasContextAsync 异步获取,首次渲染进度从 0 动画到目标值。