Vue實現(xiàn)圓環(huán)進度條的示例
數(shù)據(jù)展示,一直是各行各業(yè)樂此不疲的需求,具體到前端開發(fā)行業(yè),則是各種各種圖表數(shù)據(jù)展示,各種表格數(shù)據(jù)展示,煩不勝煩(繁不勝繁)!
前幾天剛做了折線圖、柱狀圖、餅狀圖之類的圖表數(shù)據(jù)展示效果,今天又碰到了類似圓環(huán)進度條的展示效果。天天跟數(shù)據(jù)打交道,天天跟接口打交道,項目做了不少,菜還是菜,都是淚?。?br />其實說白了,是自己對canvas不熟,對CSS3不熟,所以就找了一個現(xiàn)成的輪子:
<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, String],
default: 20
}, // 進度條百分比
barColor: {
type: String,
default: "#1890ff"
}, // 進度條顏色
backgroundColor: {
type: String,
default: "rgba(0,0,0,0.3)"
}, // 背景顏色
isAnimation: {
// 是否是動畫效果
type: Boolean,
default: true
},
isRound: {
// 是否是圓形畫筆
type: Boolean,
default: true
},
id: {
// 組件的id,多組件共存時使用
type: [String, Number],
default: 1
},
duration: {
// 整個動畫時長
type: [String, Number],
default: 1000
},
delay: {
// 延遲多久執(zhí)行
type: [String, Number],
default: 200
},
timeFunction: {
// 動畫緩動函數(shù)
type: String,
default: "cubic-bezier(0.99, 0.01, 0.22, 0.94)"
},
circleWidth: {
//圓環(huán)寬度
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'" />
使用時需要注意一下,如果你的頁面中同時使用了超過兩個以上的這種圓環(huán)進度條,就需要給每個圓環(huán)進度條設(shè)置不同的id,否則,所有圓環(huán)最終展示的數(shù)據(jù)都會是最后一個圓環(huán)的數(shù)據(jù)。
代碼中有一個防抖動的函數(shù),這里就貼一下這個函數(shù):
function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function () {
// 據(jù)上一次觸發(fā)時間間隔
const last = +new Date() - timestamp
// 上次被包裝函數(shù)被調(diào)用時間間隔last小于設(shè)定時間間隔wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果設(shè)定為immediate===true,因為開始邊界已經(jīng)調(diào)用過了此處無需調(diào)用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}本文參考的是npm上的一個圓環(huán)進度條的插件vue-circleprogressbar,之所以沒有在項目中直接安裝并使用這個插件,是因為這個插件有點不太符合我們開發(fā)的需求,比如這個插件不能設(shè)置圓環(huán)的寬度,不能設(shè)置文字的顏色,不能設(shè)置文字的大小,再比如這個插件僅僅為了防抖而依賴了lodash(這個lodash的體積還是很大的)。
至于這個組件在react中的使用,按照react的生命周期,或者react hooks的語法,或者dva模式的語法,稍微改巴改巴就可以使用了,很簡單,就不再展開了。
作者:小壞
以上就是Vue實現(xiàn)圓環(huán)進度條的示例的詳細內(nèi)容,更多關(guān)于Vue 實現(xiàn)圓環(huán)進度條的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決vue中無法動態(tài)修改jqgrid組件 url地址的問題
下面小編就為大家分享一篇解決vue中無法動態(tài)修改jqgrid組件 url地址的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03

