uniapp 用css实现圆形进度条组件

一个基于 UniApp + Vue2 的圆形进度条组件,支持自定义进度、颜色、文本和内圈样式。

效果预览

功能特性

  • 圆形进度条显示
  • 完全可自定义的颜色和样式
  • 支持数值和描述文本
  • 灵活的内圈配置
  • 响应式设计,支持 rpx 单位
  • 性能比canvas好太多

实现代码

MDPieProgress.vue 组件实现代码:

uniapp 复制代码
<template>
  <view class="pie-progress">
    <view class="progress-container" :style="{ width: config.width + 'rpx', height: config.height + 'rpx' }">
      <!-- 使用相同的计算方式 -->
      <view class="progress-bg" :style="{
        background: `conic-gradient(${config.progress.color} 0, ${config.progress.color} ${config.value}%, ${config.progress.backgroundColor } ${config.value}%, ${config.progress.backgroundColor} 100%)`,
        '-webkit-mask': `radial-gradient(transparent 0%, transparent ${config.inner.width * 70}%, #000 ${config.inner.width * 70}%, #000 0)`,
        width: config.width + 'rpx',
        height: config.height + 'rpx'
      }"></view>

      <!-- 内圈背景 -->
      <view
        class="inner-background"
        :style="{
          width: (config.inner.width * 100) + '%',
          height: (config.inner.width * 100) + '%',
          backgroundColor: config.inner.backgroundColor
        }"
      ></view>

      <!-- 文字内容 -->
      <view class="progress-inner flex-c-c">
        <view class="progress-text flex-c">
          <text
            class="value"
            v-if="config.valueText && config.valueText.value"
            :style="{
              color: config.valueText.color,
              fontSize: config.valueText.fontSize,
              fontWeight: config.valueText.fontWeight
            }"
          >{{ config.valueText.value }}</text>
          <text
            class="desc"
            v-if="config.descText && config.descText.value"
            :style="{
              color: config.descText.color,
              fontSize: config.descText.fontSize,
              fontWeight: config.descText.fontWeight
            }"
          >{{ config.descText.value }}</text>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  props: {
    // 配置对象
    opts: {
      type: Object,
      default: () => ({})
    }
  },
  computed: {
    config() {
      return this.mergeWithDefault(this.opts)
    }
  },
  data() {
    return {
      defaultConfig: {
        // 进度值 (0-100)
        value: 0,
        width: 200, // 整体宽度 (单位: rpx)
        height: 200, // 整体高度 (单位: rpx)
        // 进度条配置
        progress: {
          color: '#0E9BF3', // 进度条颜色
          backgroundColor: '#E0E4EB' // 进度条背景色
        },
        // 值文本
        valueText: {
          value: "",
          color: "#3B3B4D",
          fontSize: "28rpx",
          fontWeight: "bold",
        },
        // 描述文本
        descText: {
          value: "",
          color: "#999",
          fontSize: "20rpx",
          fontWeight: "normal"
        },
        // 内圈配置
        inner: {
          width: 0.8, // 内圈宽度占比 (0-1) 占比越大内圈越大,进度条越细
          backgroundColor: "transparent" // 内圈背景色
        }
      }
    }
  },
  methods: {
    // 合并函数
    mergeWithDefault(opts) {
      if (!opts || typeof opts !== 'object') {
        return { ...this.defaultConfig };
      }
      const result = {
        // 第一层合并
        ...this.defaultConfig,
        ...opts,
        // 第二层深度合并
        progress: {
          ...this.defaultConfig.progress,
          ...(opts.progress || {})
        },
        valueText: {
          ...this.defaultConfig.valueText,
          ...(opts.valueText || {})
        },
        descText: {
          ...this.defaultConfig.descText,
          ...(opts.descText || {})
        },
        inner: {
          ...this.defaultConfig.inner,
          ...(opts.inner || {})
        }
      }
      return result
    }
  }
}
</script>

<style lang="scss">
.pie-progress {
  .progress-container {
    position: relative;

    .progress-bg {
      position: absolute;
      top: 0;
      left: 0;
      border-radius: 50%;
    }

    .inner-background {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      border-radius: 50%;
      z-index: 1;
    }

    .progress-inner {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      z-index: 2;
      .progress-text {
        flex-direction: column;
        flex-shrink: 0;
        .value {
          font-weight: bold;
        }
      }
    }
  }
}
</style>

父组件使用案例代码:

uniapp 复制代码
<template>
  <view>
    ......
    <MDPieProgress :opts="getPieProgressConfig(item)"></MDPieProgress>
  </view>
</template>

<script>
export default {
  methods: {
    getPieProgressConfig(item) {
      return {
        value:item.rate,
        width: 108,
        height: 108,
        progress: {
          color: isSub ? '#FF451C' : '#0E9BF3',
          backgroundColor: '#E0E4EB'
        },
        valueText: {
          value: `${item.rate}%`,
          color: '#3B3B4D',
          fontSize: '28rpx',
          fontWeight: 'bold'
        },
        descText: {
          value: '达成率',
          color: '#999999',
          fontSize: '20rpx',
          fontWeight: 'normal'
        },
        inner: {
          width: 0.8,
          backgroundColor: '#FFFFFF'
        }
      }
    }, 
  }
}
</script>

操作手册(配置参数)

基础配置

参数 类型 默认值 必填 说明 示例
value Number 0 进度值,范围 0-100 75
width Number 200 组件整体宽度,单位 rpx 250
height Number 200 组件整体高度,单位 rpx 250

进度条配置 progress

参数 类型 默认值 必填 说明 示例
progress.color String '#0E9BF3' 已完成进度部分颜色 '#42b983'
progress.backgroundColor String '#E0E4EB' 未完成进度部分颜色 '#f0f9eb'

数值文本配置 valueText

参数 类型 默认值 必填 说明 示例
valueText.value String "" 显示的数值文本内容 "75%"
valueText.color String "#3B3B4D" 数值文字颜色 "#ff5722"
valueText.fontSize String "28rpx" 数值文字大小 "32rpx"
valueText.fontWeight String "bold" 数值文字粗细 "600"

描述文本配置 descText

参数 类型 默认值 必填 说明 示例
descText.value String "" 描述文本内容 "完成率"
descText.color String "#999" 描述文字颜色 "#666"
descText.fontSize String "20rpx" 描述文字大小 "24rpx"
descText.fontWeight String "normal" 描述文字粗细 "normal"

内圈配置 inner

参数 类型 默认值 必填 说明 示例
inner.width Number 0.8 内圈宽度占比 (0-1),值越大内圈越大,进度条越细 0.7
inner.backgroundColor String "transparent" 内圈背景颜色 "#FFFFFF"

注意事项

  1. 单位系统 :所有尺寸单位使用 rpx,确保在不同设备上的适配
  2. 渐进式配置:只需提供需要覆盖的配置项,未提供的项将使用默认值
  3. 内圈宽度inner.width 的值范围是 0-1,值越大内圈越大,进度条越细
  4. 背景色透明 :设置 inner.backgroundColor: "transparent" 可使内圈透明
相关推荐
杏花春雨江南8 小时前
npm error Could not resolve dependency:
前端·npm·node.js
嫂子的姐夫8 小时前
10-七麦js扣代码
前端·javascript·爬虫·python·node.js·网络爬虫
Komorebi_99998 小时前
Vue3 + TypeScript provide/inject 小白学习笔记
前端·javascript·vue.js
少吃一口都不行8 小时前
脚手架学习
前端·javascript·学习
地方地方8 小时前
手写JavaScript 深拷贝
前端·javascript
yeyuningzi8 小时前
npm升级提示error engine not compatible with your version of node/npm: npm@11.6.2
前端·npm·node.js
1024小神8 小时前
next 项目中的 'use client' 是什么意思
前端
我是华为OD~HR~栗栗呀8 小时前
24届-Python面经(华为OD)
java·前端·c++·python·华为od·华为·面试
whysqwhw8 小时前
mac上AndroidStudio升级无写入权限问题
前端