component-svg圆环进度百分比图(顶部文本,中间图形,底部文本)

svg图形展示

vue3 + ts

图表顶部自定义编辑文本,圆环可自定义背景与颜色,底部为图表文本。

在ant 或echarts中也有类似的圆环进度

父组件调用

顶部自定义为文本描述信息

对应进度可计算为百分比,圆环宽度,进度以及背景颜色,百分比字体颜色,百分比底部文本,以及进度圆环开始渲染位置。

javascript 复制代码
<template>
  <div class="content-all">
    <div class="content-top-text">echarts文本描述</div>
    <!-- echarts整体-(图表+底部文本)  -->
    <div class="echarts-all">
       <!-- echarts整体-图表 -->
      <div class="echarts-chart">
        <HDemoSon
          :progress="75"
          :strokeWidth="12"
          :progressColor="'#4CAF50'"
          :backgroundColor="'#FFF'"
          :percentageTextColor="'#4CAF50'"
          :title="'完成率'"
          direction="top"
        />
      </div>
      <!-- echarts整体-底部文本 -->
      <div class="echarts-bottom-text">累计</div>  
    </div>
  </div>
</template>

<script setup>
import HDemoSon from './HDemoSon.vue'
</script>

<style scoped lang="scss">

@function vh($px) {
  @return calc($px / 1080) * 100vh;
}
// 整体样式
.content-all {
  padding: 2px;
  height: 100%;
  width: 100%;
  background-color: #0C6299;
}

// 顶部数据统计
.content-top-text{
  width: 100%;
  height: 20px;
  background-color: blueviolet;
}

// echarts整体-(图表+底部文本)
.echarts-all {
  width: 70px; 
  height: 90px;
  background-color: red;
}

// echarts整体-图表
.echarts-chart {
  width: 70px;
  height: 70px;
}


// echarts整体-底部文本
.echarts-bottom-text {
  background-color: aqua;
  height: 20px;
  width: 100%;
  line-height: 20px;
  text-align: center;
  font-weight: 500;
  font-size: 10px;
}
</style>

子组件-进度svg图形

图表正常接收数据进行渲染,底部自定义文本信息或样式

javascript 复制代码
<!-- 进度圆环组件 -->
<template>
  <div class="progress-ring">
    <!-- SVG -->
    <svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
      <!-- 背景圆环 -->
      <circle
        :stroke="backgroundColor"
        :stroke-width="strokeWidth"
        fill="transparent"
        :r="radius"
        cx="50"
        cy="50"
      />
      <!-- 进度圆环 -->
      <circle
        :stroke="progressColor"
        :stroke-width="strokeWidth"
        fill="transparent"
        :r="radius"
        cx="50"
        cy="50"
        :stroke-dasharray="circumference"
        :stroke-dashoffset="strokeDashoffset"
        :transform="rotationTransform"
      />
    </svg>
    <!-- 文本内容 -->
    <div class="progress-ring-text-container">
      <div class="progress-ring-percentage" :style="percentageStyle">
        {{ percentageText }}
      </div>
       <div v-if="title" class="progress-ring-title">
        {{ title }}
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  progress: {
    type: Number,
    default: 0,
    validator: (v) => v >= 0 && v <= 100
  },
  // 圆环宽度   
  strokeWidth: {
    type: Number,
  },
  // 进度圆环背景颜色  
  progressColor: {
    type: String,
  },
  // 进度圆环背景颜色   
  backgroundColor: {
    type: String,
  },
  // 字体   
  title: {
    type: String,
    default: ''
  },
  // 百分比字体颜色
  percentageTextColor: {
    type: String,
  },
  // 进度圆环开始绘制方向  
  direction: {
    type: String,
    default: 'top',
    validator: (v) => ['top', 'right', 'bottom', 'left'].includes(v)
  }
})

// 半径基于 viewBox 100x100
const radius = computed(() => 50 - props.strokeWidth / 2)
const circumference = computed(() => 2 * Math.PI * radius.value)

const strokeDashoffset = computed(() => {
  const p = Math.max(0, Math.min(100, props.progress))
  return circumference.value - (p / 100) * circumference.value
})

const rotationTransform = computed(() => {
  const map = { top: -90, right: 0, bottom: 90, left: 180 }
  return `rotate(${map[props.direction]} 50 50)`
})

// 百分比颜色
const percentageStyle = computed(() => ({
  color: props.percentageTextColor,
}))

// 百分比计算
const percentageText = computed(() => `${Math.round(props.progress)}%`)
</script>

<style scoped lang="scss">

@function vh($px) {
  @return calc($px / 1080) * 100vh;
}
/* 整体样式 */
.progress-ring {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.progress-ring svg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

/* 中心文本内容 */
.progress-ring-text-container {
  position: relative;
  text-align: center;
  font-family: Arial, sans-serif;
  line-height: 1.2;
  z-index: 1;
}

/* 百分比 */
.progress-ring-percentage{
    font-size: 16px;
}

/* 文本 */
.progress-ring-title{
    font-size: 12px;
    color: #666;
}
</style>
相关推荐
JustHappy4 小时前
古法编程秘籍(七):互联网到底是什么?把两台电脑怎么说话搞懂就够了
前端·后端·网络协议
snow@li4 小时前
SEO-文章标题:写文章时候,分类+主标题+大纲+解释 作为标题 / 不点进去也知道全文覆盖什么 / 标题即架构
前端
kyriewen5 小时前
Git Commit 前自动修复代码风格?配置 Husky + lint-staged,从此 CR 只聊逻辑
前端·git·面试
小和尚同志5 小时前
AI 自动化测试探索(一):Playwright MCP
前端·人工智能·aigc
老马识途2.06 小时前
在AI的帮助下理解spring的启动过程
java·前端·spring
徐小夕6 小时前
Loop Engineering 深度解析与实战指南(全网最全)
前端·算法·github
运筹vivo@6 小时前
Python ContextVar 底层机制与内存模型拆解
前端·数据库·python
#麻辣小龙虾#8 小时前
基于vue3.0开发一款【固废与废气运维管理系统】(支持源码)
前端·vue.js·vue3
Cosolar8 小时前
Docsify零构建文档站完全指南:从快速搭建到企业级部署
前端·开源·github
weixin_471383038 小时前
Taro-02-页面路由
前端·taro