自定义封装进度条、环形进度条

<template>
  <div class="progress" :class="'progress--' + ptype">
    <!-- 条形进度条 -->
    <div class="progress-bar" v-if="ptype === 'line'">
      <div class="progress-bar__outer" :style="{ height: strokeHeight + 'px' }">
        <div class="progress-bar__inner" :style="barStyle">
          <!-- 进度条内显示百分比 -->
          <!-- <div v-if="textInside" class="progress__text" style="color: white">
            {{ percentage }}%
          </div> -->
        </div>
      </div>
    </div>
    <!-- 环形进度条 采用SVG实现 -->
    <div
      class="progress_circle"
      :style="{ width: cwidth + 'px', height: cwidth + 'px' }"
      v-else
    >
      <svg
        viewBox="0 0 100 100"
        :style="{ width: cwidth + 'px', height: cwidth + 'px' }"
      >
        <!-- 背景圆形 -->
        <path
          :d="trackPath"
          fill="none"
          :stroke-width="relativeStrokeHeight"
          stroke="#e5e9f2"
        />
        <!-- 进度圆形 -->
        <path
          :d="trackPath"
          fill="none"
          :stroke-width="relativeStrokeHeight"
          :stroke="stroke"
          :style="circlePathStyle"
          stroke-linecap="round"
          
        />
      </svg>
    </div>
    <div
      v-if="!textInside"
      class="progress__text"
      :style="{ fontSize: progressTextSize + 'px' }"
    >
      <!-- <template v-if="!status"> {{ percentage }}% </template> -->
      <!-- <i v-else class="icon" :class="iconCls"></i> -->
    </div>
  </div>
</template>
<script>
export default {
  props: {
    strokeHeight: {
      // 进度条高度
      // required:true,
      type: Number,
      default: 10,
    },
    percentage: {
      // 进度条百分比
      type: Number,
      default: 0,
      required: true,
      valiator(value) {
        return value >= 0 && value <= 100;
      },
    },
    status: {
      // 进度条状态:正常状态,成功状态,异常状态
      type: String,
    },
    ptype: {
      // 进度条样式:条形,还是圆形
      type: String,
      default: "line",
      validator: (val) => ["circle", "line"].includes(val),
    },
    textInside: {
      // 文字是否內显
      type: Boolean,
      default: false,
    },
    pcolor: {
      // 进度条颜色
      type: String,
    },
    cwidth: {
      type: Number,
      default: 126,
    },
  },
  computed: {
    progressTextSize() {
      return 9 + this.strokeHeight * 0.4;
    },
    stroke() {
      let color;
      if (this.pcolor) {
        return this.pcolor;
      }
      switch (this.status) {
        case "success":
          color = "#13ce66";
          break;
        case "failure":
          color = "#ff4949";
          break;
        default:
          color = "#20a0ff";
          break;
      }
      return color;
    },
    barStyle() {
      // 计算属性调用其他计算属性,必须加this关键字,否则找不到
      return { width: this.percentage + "%", backgroundColor: this.stroke };
    },
    iconCls() {
      if (this.ptype === "line") {
        // 如果是线性进度条
        return this.status === "success"
          ? "icon-circle-check"
          : "icon-circle-close";
      } else {
        return this.status === "success" ? "icon-check" : "icon-close";
      }
    },
    trackPath() {
      const radius = 50 - this.relativeStrokeHeight / 2;
      return (
        "M 50 50 m 0 -" +
        radius +
        " a " +
        radius +
        " " +
        radius +
        " 0 1 1 0 " +
        radius * 2 +
        " a " +
        radius +
        " " +
        radius +
        " 0 1 1 0 -" +
        radius * 2 +
        " "
      );
    },
    relativeStrokeHeight() {
      return (this.strokeHeight * 100) / this.cwidth;
    },
    perimeter() {
      const radius = 50 - this.relativeStrokeHeight / 2;
      return 2 * Math.PI * radius;
    },
    circlePathStyle() {
      const perimeter = this.perimeter;
      return {
        strokeDasharray: "" + perimeter + "px," + perimeter + "px",
        strokeDashoffset: (1 - this.percentage / 100) * perimeter + "px",
      };
    },
  },
};
</script>
<style>
.progress {
  margin: 10px;
  /* border: 1px solid #ffbbff; */
}
/* .progress-bar {
  /* display: inline-block;
  width: 98%;
  box-sizing: border-box;
  margin-right: -50px;
  padding-right: 50px; 
} */
.progress-bar__outer {
  width: 100%;
  border-radius: 10px;
  background-color: #ebeef5;
}
.progress-bar__inner {
  /* width: 60%; */
  background-color: rebeccapurple;
  border-radius: 10px;
  height: 100%;
  transition: width 0.6s ease;
  text-align: right;
  line-height: 80%;
}
.progress__text {
  font-size: 12px;
  margin-left: 6px;
  display: inline-block;
  vertical-align: middle;
  margin-right: 5px;
}
.icon-circle-close,
.icon-close {
  font-family: "Wingdings" !important;
  color: red;
}
.icon-circle-check,
.icon-check {
  font-family: "Wingdings" !important;
  color: seagreen;
}

.icon-circle-close::before {
  content: "\FD";
}
.icon-close::before {
  content: "\FB";
}
.icon-circle-check::before {
  content: "\FE";
}
.icon-check::before {
  content: "\FC";
}

.progress_circle {
  /* 环形进度条 */
}
.progress--circle {
  display: inline-block;
  position: relative;
}

.progress--circle .progress__text {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  margin-left: 0px;
  text-align: center;
  width: 100%;
}
</style>

进度条调用:

<dProgress :percentage="40" pcolor="orange" />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值