1. 程式人生 > 程式設計 >Vue實現圓環進度條的示例

Vue實現圓環進度條的示例

資料展示,一直是各行各業樂此不疲的需求,具體到前端開發行業,則是各種各種圖表資料展示,各種表格資料展示,煩不勝煩(繁不勝繁)!
前幾天剛做了折線圖、柱狀圖、餅狀圖之類的圖表資料展示效果,今天又碰到了類似圓環進度條的展示效果。天天跟資料打交道,天天跟介面打交道,專案做了不少,菜逼還是菜逼,都是淚啊!
其實說白了,是自己對canvas不熟,對CSS3不熟,所以就找了一個現成的輪子:

<template>
 <div class="content" ref="box">
 <svg style="transform: rotate(-90deg)" :width="width" :height="width" xmlns="http://www.w3.org/2000/svg">
  <circle :r="(width-radius)/2"
  :cy="width/2"
  :cx="width/2"
  :stroke-width="radius"
  :stroke="backgroundColor"
  fill="none"
  />
  <circle ref="$bar"
  :r="(width-radius)/2"
  :cy="width/2"
  :cx="width/2"
  :stroke="barColor"
  :stroke-width="radius"
  :stroke-linecap="isRound ? 'round' : 'square'"
  :stroke-dasharray="(width-radius)*3.14"
  :stroke-dashoffset="isAnimation ? (width-radius) * 3.14 : (width - radius) * 3.14 * (100 - progress) / 100"
  fill="none"
  />
 </svg>
 <div class="center_text" :style="{color,fontSize}">
  <p v-if="!$slots.default" class="title">{{progress}}%</p>
  <slot></slot>
 </div>
 </div>
</template>

<script>
export default {
 props: {
 radius: {
  type: [Number,String],default: 20
 },// 進度條厚度
 progress: {
  type: [Number,// 進度條百分比
 barColor: {
  type: String,default: "#1890ff"
 },// 進度條顏色
 backgroundColor: {
  type: String,default: "rgba(0,0.3)"
 },// 背景顏色
 isAnimation: {
  // 是否是動畫效果
  type: Boolean,default: true
 },isRound: {
  // 是否是圓形畫筆
  type: Boolean,id: {
  // 元件的id,多元件共存時使用
  type: [String,Number],default: 1
 },duration: {
  // 整個動畫時長
  type: [String,default: 1000
 },delay: {
  // 延遲多久執行
  type: [String,default: 200
 },timeFunction: {
  // 動畫緩動函式
  type: String,default: "cubic-bezier(0.99,0.01,0.22,0.94)"
 },circleWidth: {
  //圓環寬度
  type: Number,default: 100,},color: {
  //文字顏色
  type: String,default: '#000'
 },fontSize: {
  //文字大小
  type: String,default: '18px'
 }
 },data() {
 return {
  width: this.circleWidth,idStr: `circle_progress_keyframes_${this.id}`
 };
 },beforeDestroy() {
 // 清除舊元件的樣式標籤
 document.getElementById(this.idStr) &&
 document.getElementById(this.idStr).remove();
 window.addEventListener(() => {});
 },mounted() {
 let self = this;
 this.setCircleWidth();
 this.setAnimation();
 // 此處不能使用window.onresize
 window.addEventListener(
  "resize",debounce(function() {
  self.setCircleWidth();
  self.setAnimation(self);
  },300)
 );
 },methods: {
 setCircleWidth() {
  let box = this.$refs.box;
  let width = box.clientWidth;
  let height = box.clientHeight;
  let cW = width > height ? height : width;
  this.width = cW;
 },setAnimation() {
  let self = this;
  if (self.isAnimation) {
  // 重複定義判斷
  if (document.getElementById(self.idStr)) {
   console.warn("vue-circle-progress should not have same id style");
   document.getElementById(self.idStr).remove();
  }
  // 生成動畫樣式檔案
  let style = document.createElement("style");
  style.id = self.idStr;
  style.type = "text/css";
  style.innerHTML = `
  @keyframes circle_progress_keyframes_name_${self.id} {
  from {stroke-dashoffset: ${(self.width - self.radius) * 3.14}px;}
  to {stroke-dashoffset: ${((self.width - self.radius) *
  3.14 *
  (100 - self.progress)) /
  100}px;}}
  .circle_progress_bar${
  self.id
  } {animation: circle_progress_keyframes_name_${self.id} ${
   self.duration
  }ms ${self.delay}ms ${self.timeFunction} forwards;}`;
  // 新增新樣式檔案
  document.getElementsByTagName("head")[0].appendChild(style);
  // 往svg元素中新增動畫class
  self.$refs.$bar.classList.add(`circle_progress_bar${self.id}`);
  }
 }
 }
};
</script>
<style scoped>
.content {height:100%;display:flex;justify-content:center;align-items: center;}
.center_text {position:absolute;}
</style>

使用方法:

<CircleProgress :id="'circle1'" :circleWidth="40" :radius="7" :progress="30" :isAnimation="true" :backgroundColor="'#E9E9E9'" :barColor="'#FF4F4F'" />
<CircleProgress :id="'circle2'" :circleWidth="40" :radius="7" :progress="50" :isAnimation="true" :backgroundColor="'#E9E9E9'" :barColor="'#FF902A'" />
<CircleProgress :id="'circle3'" :circleWidth="40" :radius="7" :progress="89" :isAnimation="true" :backgroundColor="'#E9E9E9'" :barColor="'#FFDB4F'" />
<CircleProgress :id="'circle4'" :circleWidth="40" :radius="7" :progress="25" :isAnimation="true" :backgroundColor="'#E9E9E9'" :barColor="'#B8D87E'" />

使用時需要注意一下,如果你的頁面中同時使用了超過兩個以上的這種圓環進度條,就需要給每個圓環進度條設定不同的id,否則,所有圓環最終展示的資料都會是最後一個圓環的資料。

程式碼中有一個防抖動的函式,這裡就貼一下這個函式:

function debounce(func,wait,immediate) {
 let timeout,args,context,timestamp,result

 const later = function () {
 // 據上一次觸發時間間隔
 const last = +new Date() - timestamp

 // 上次被包裝函式被呼叫時間間隔last小於設定時間間隔wait
 if (last < wait && last > 0) {
  timeout = setTimeout(later,wait - last)
 } else {
  timeout = null
  // 如果設定為immediate===true,因為開始邊界已經呼叫過了此處無需呼叫
  if (!immediate) {
  result = func.apply(context,args)
  if (!timeout) context = args = null
  }
 }
 }

本文參考的是npm上的一個圓環進度條的外掛vue-circleprogressbar,之所以沒有在專案中直接安裝並使用這個外掛,是因為這個外掛有點不太符合我們開發的需求,比如這個外掛不能設定圓環的寬度,不能設定文字的顏色,不能設定文字的大小,再比如這個外掛僅僅為了防抖而依賴了lodash(這個lodash的體積還是很大的)。

至於這個元件在react中的使用,按照react的生命週期,或者react hooks的語法,或者dva模式的語法,稍微改巴改巴就可以使用了,很簡單,就不再展開了。

作者:小壞

出處:http://tnnyang.cnblogs.com

以上就是Vue實現圓環進度條的示例的詳細內容,更多關於Vue 實現圓環進度條的資料請關注我們其它相關文章!