思路
- 使用2個(gè)canvas 一個(gè)是背景圓環(huán),一個(gè)是彩色圓環(huán)。
- 使用setInterval 讓彩色圓環(huán)逐步繪制。
在看我的文章前,必須先看 ,下面轉(zhuǎn)的文章,因?yàn)楸疚氖窃谒鼈兓A(chǔ)上修改的.
它們的缺點(diǎn)為:
1.組件必須用js實(shí)例化 (如果我有一個(gè)任務(wù)列表,后面會(huì)顯示每個(gè)任務(wù)的進(jìn)度,每個(gè)任務(wù)都必須實(shí)例化)
2.它們js實(shí)例化時(shí),繪圖是用 px繪制,導(dǎo)致頁(yè)面用rpx布局,組件卻用px繪制.
修改后的組件

image.png
circle.js :
/* components/circle/circle.js */
Component({
options: {
multipleSlots: true // 在組件定義時(shí)的選項(xiàng)中啟用多slot支持
},
properties: {
draw: {//畫板元素名稱id
type: String,
value: 'draw'
},
per:{ //百分比 通過(guò)此值轉(zhuǎn)換成step
type: String,
value: '0'
},
r:{//半徑
type: String,
value: '50'
}
},
data: { /* 私有數(shù)據(jù),可用于模版渲染 */
step: 1, //用來(lái)算圓的弧度0-2
size:0, //畫板大小
screenWidth:750, //實(shí)際設(shè)備的寬度
txt:0
},
methods: {
/**
* el:畫圓的元素
* r:圓的半徑
* w:圓的寬度
* 功能:畫背景
*/
drawCircleBg: function (el, r, w) {
const ctx = wx.createCanvasContext(el,this);
ctx.setLineWidth(w);// 設(shè)置圓環(huán)的寬度
ctx.setStrokeStyle('#E5E5E5'); // 設(shè)置圓環(huán)的顏色
ctx.setLineCap('round') // 設(shè)置圓環(huán)端點(diǎn)的形狀
ctx.beginPath();//開始一個(gè)新的路徑
ctx.arc(r, r, r - w, 0, 2 * Math.PI, false);
//設(shè)置一個(gè)原點(diǎn)(110,110),半徑為100的圓的路徑到當(dāng)前路徑
ctx.stroke();//對(duì)當(dāng)前路徑進(jìn)行描邊
ctx.draw();
},
/**
* el:畫圓的元素
* r:圓的半徑
* w:圓的寬度
* step:圓的弧度 (0-2)
* 功能:彩色圓環(huán)
*/
drawCircle: function (el, r, w, step) {
var context = wx.createCanvasContext(el,this);
// 設(shè)置漸變
var gradient = context.createLinearGradient(2 * r, r, 0);
gradient.addColorStop("0", "#2661DD");
gradient.addColorStop("0.5", "#40ED94");
gradient.addColorStop("1.0", "#5956CC");
context.setLineWidth(w);
context.setStrokeStyle(gradient);
context.setLineCap('round')
context.beginPath();//開始一個(gè)新的路徑
// step 從0到2為一周
context.arc(r, r, r - w, -Math.PI / 2, step * Math.PI - Math.PI / 2, false);
context.stroke();//對(duì)當(dāng)前路徑進(jìn)行描邊
context.draw()
}
},
lifetimes: {
// 生命周期函數(shù),可以為函數(shù),或一個(gè)在methods段中定義的方法名
attached: function () {
const _this = this;
//獲取屏幕寬度
wx.getSystemInfo({
success: function(res) {
_this.setData({
screenWidth: res.windowWidth
});
},
});
//初始化
const el = _this.data.draw; //畫板元素
const per = _this.data.per; //圓形進(jìn)度
const r = Number(_this.data.r); //圓形半徑
_this.setData({
step: (2 * Number(_this.data.per)) / 100,
txt: _this.data.per
});
//獲取屏幕寬度(并把真正的半徑px轉(zhuǎn)成rpx)
let rpx = (_this.data.screenWidth / 750) * r;
//計(jì)算出畫板大小
this.setData({
size: rpx * 2
});
const w = 4;//圓形的寬度
//組件入口,調(diào)用下面即可繪制 背景圓環(huán)和彩色圓環(huán)。
_this.drawCircleBg(el + 'bg', rpx, w);//繪制 背景圓環(huán)
_this.drawCircle(el, rpx, w, _this.data.step);//繪制 彩色圓環(huán)
}
}
})
circle.wxml :
<!-- components/circle/circle.wxml -->
<view class="circle_box" style="width:{{size}}px;height:{{size}}px">
<canvas class="circle_bg" canvas-id="{{draw}}bg" style="width:{{size}}px;height:{{size}}px"></canvas>
<canvas class="circle_draw" canvas-id="{{draw}}" style="width:{{size}}px;height:{{size}}px"></canvas>
<text class='circle_txt'> {{txt}}% </text>
</view>
circle.json :
{
"component": true,
"usingComponents": {}
}
circle.wxss :
.circle_box,.circle_draw{ position: relative; }
.circle_bg{position: absolute;}
.circle_box{
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.circle_txt{
position: absolute;
font-size: 28rpx;
}
調(diào)用 :
在所需頁(yè)面的XXX.json 先引入 組件
{
"usingComponents": {
"circle": "/components/circle/circle"
}
}
wxml 使用組件
<circle draw='circwewle1' per = '40' r = '50'/>
<circle draw='circwewle2' per = '10' r = '30'/>
<circle draw='circwewle3' per = '20' r = '100'/>
<circle draw='circwewle' per = '50' r = '60'/>
<circle draw='circwewle' per = '90' r = '120'/>
draw : 確定 canvas的id
per : 進(jìn)度百分比 (1-100)
r: 圓的半徑 (按px,最終轉(zhuǎn)化成rpx)
結(jié)果:

image.png
轉(zhuǎn) :
https://segmentfault.com/a/1190000013219501
https://segmentfault.com/a/1190000013242747?utm_source=tag-newest
參考微信自定義組件講解 : https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/