本篇介紹底部快捷控件的環形進度條的實現方法:通過svg
繪製兩個環,線條模糊的環作爲背景、線條明亮的環根據傳入的百分比繪製相應長度(即進度)。該組件同樣屬於基礎組件,在src/base/progress-circle/目錄下新建progress-circle.vue
:
樣式部分
<style lang="stylus" rel="stylesheet/stylus">
// variable.styl傳送門:https://wy310.cn/2020/01/11/vue-build-basic-style-structure/
@import "~common/stylus/variable"
.progress-circle
position: relative
circle
stroke-width: 8px
transform-origin: center
&.progress-bg
transform: scale(0.9)
stroke: $color-theme-d
&.progress-bar
transform: scale(0.9) rotate(-90deg)
stroke: $color-theme
</style>
- 這裏先貼出樣式代碼,circle統一設置了描邊寬度爲8px(這裏的8px會根據後面介紹的svg的寬高動態變化,不是絕對的8像素長度,而是8%),背景圓的描邊顏色爲
$color-theme-d
(rgba(255, 205, 49, 0.5)),進度圓的描邊顏色爲$color-theme
(#ffcd32),另外,還讓進度圓環逆時針旋轉90度,以讓它的起始點在最高處(旋轉之前起始點在最右側),以實現歌曲環形進度條以頂部爲起點順時針旋轉的業務需求。
DOM部分
<template>
<div class="progress-circle">
<svg :width="length" :height="length" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<!--背景圓環:線條模糊-->
<circle class="progress-bg" r="50" cx="50" cy="50" fill="transparent"></circle>
<!--進度圓環:線條明亮-->
<circle class="progress-bar" r="50" cx="50" cy="50" fill="transparent" :stroke-dasharray="dasharray" :stroke-dashoffset="dashoffset"></circle>
</svg>
</div>
</template>
- svg標籤的
viewBox
的四個參數分別表示:最小橫座標值、最小縱座標值、寬度、高度。前面兩個參數,個人覺得除非對svg的內部做整體偏移,否則一般都是“0, 0”,即svg的左上角(爲起點);後面兩個參數,我們暫時把它們理解成比例或者等份,“100, 100”代表寬和高都設置成100等份,注意它們的單位不是px,爲什麼這麼說呢?因爲我們發現,svg標籤上還又兩個屬性:width和height,它們的單位纔是px(length變量將在後面的代碼中被賦予80),也是真正決定svg寬高的屬性(即svg真實寬高其實是length個像素的長度,也就是80px),那麼viewBox
後兩個參數中的一份就表示length / 100個像素的長度(length爲50,一份就等於0.5px;爲80,就是0.8px;爲100,就是1px……)。所以一般爲了方便計算,我們都會設置一個整數值,如100(等份),而不會是一個不能被任何數整除的質數,如123(等份); - circle標籤的
r
、cx
、cy
分別表示半徑、圓心橫座標、圓心縱座標。它們的單位也都不是px,而是和viewBox
一樣(以及之後的stroke-dasharray
、stroke-dashoffset
單位也是如此)。100等份中的50份,表示該圓的圓心就在svg的中心,它的半徑就是svg邊長的一半,也就是說該圓是svg正方形的內切圓; -
stroke-dasharray
的數值我們設置成該圓的周長,也就是2πr,即Math.PI * 100
,現在這個淺黃色的背景圓環就能顯示出來了; -
stroke-dashoffset
稍微有點不一樣,舉幾個測試例子幫助大家理解:上面提到該圓的周長約等於314,那麼我們把stroke-dashoffset
先後設置成0
、100
、200
、314
之後看看效果(如下圖),似乎與我們的預期相反:0
是滿的,314
卻是空的……所以,我們發現使用314 - x
倒是符合需求,於是引出下面的js部分。
JS部分
<script>
export default {
name: 'progress-circle',
data () {
return {
dasharray: Math.PI * 100
}
},
props: {
// svg邊長
length: {
type: Number,
default: 80
},
percent: {
type: Number,
default: 0
}
},
computed: {
dashoffset () {
return (1 - this.percent) * this.dasharray
}
}
}
</script>
- 對外暴露一個百分比props:
percent
(0到1的小數),調用組件時需要傳入一個小數,就像這樣:<progress-circle :percent="percent"></progress-circle>
; - 傳入百分比,計算屬性
dashoffset
函數會計算出該persent
對應的進度偏移量,然後賦值到DOM上的stroke-dashoffset
,完成進度條渲染。