大致的效果如下
图中的扇形总共需要用到两个canvas
wxml
wxss因为两个canvas需要重合所以用ablolute
.progress {
position:absolute;
z-index: 1;
}
js里的内容比较多,首先要初始化然后将刷新动画写成函数形式
Page({
data: {
canvasWidth: 365,
canvasHeitht: 270,
radioPos: 98,
footNum: 0,
footNumAll: 0,
myTargetFoot: 10000,
degree: 210,
})
timer: undefined,
timerNum: undefined,
onLoad需要初始化背景即淡蓝色背景扇形
onLoad: function (options) {
let widthPX = wx.getSystemInfoSync().windowWidth;
let r = this.data.radioPos = widthPX * (365/750) * (270/365) * (2/3)
var context = wx.createCanvasContext('canvasProgress')
context.setStrokeStyle("#DBE9FF");
context.setLineWidth(1);
context.beginPath();
for (let i = 210 ; i >= -30 ; i -= 3){//每3度绘制一条线
let degree = i / 360 * Math.PI * 2
let radio = r * 0.87 - r * 0.05 * (210 - i) / 240
context.moveTo(r + radio * Math.cos(degree), r - radio * Math.sin(degree));//向量加减
context.lineTo(r + r * Math.cos(degree), r - r * Math.sin(degree));//向量加减
context.stroke();
}
context.draw();
},
首先要明白的一点就是canvas的单位是px而不是rpx,所以宽高半径都是需要从屏幕的宽度来手动设置的
这里稍微需要一些数学基础和向量加减运算
页面切换需要清理canvas并在进入当前页面重新绘制所以需要在onshow里做一些事
onShow: function () {
let that = this
//清理
var context = wx.createCanvasContext('canvasProgressReal')
context.clearRect(0, 0, this.data.canvasWidth, this.data.canvasHeitht)
context.draw({
reserve: true
})
//掉接口获取新数据后在回调函数里调用绘制函数
掉接口({
url:xxx,
header:xxxx,
success:function(){
that.walkAction()
}
})
}
调用已经封装好的动画函数
walkAction: function () {
console.log('walk')
this.setData({
degree: 210
})
let that = this
let r = this.data.radioPos
let widthPX = wx.getSystemInfoSync().windowWidth;
var context = wx.createCanvasContext('canvasProgressReal')
context.clearRect(0, 0, this.data.canvasWidth, this.data.canvasHeitht)
context.setStrokeStyle("#499AFF");
context.setLineWidth(1);
let degreeMax = 210 - (this.data.footNumAll / this.data.myTargetFoot) * 240;
if (Number.parseInt(this.data.footNumAll) >= Number.parseInt(this.data.myTargetFoot)) {
console.log('footNumAll is smaller than myTargetFoot')
degreeMax = -33
}
this.timer = setInterval(() => {
if (that.data.degree > degreeMax) {
context.beginPath();
let degreeOne = that.data.degree / 360 * Math.PI * 2
let radio = r * 0.87 - r * 0.05 * (210 - that.data.degree) / 240
context.moveTo(r + radio * Math.cos(degreeOne), r - radio * Math.sin(degreeOne));
context.lineTo(r + r * Math.cos(degreeOne), r - r * Math.sin(degreeOne));
context.stroke();
// context.draw({
// reserve: true
// })//这个方法真机上绘制有问题
wx.drawCanvas({
canvasId: 'canvasProgressReal',
actions: context.getActions(),
reserve: true
})
that.data.degree -= 3;
} else {
clearInterval(that.timer)
}
},50)
let tempTimes = 0;
let times = (this.data.footNumAll / this.data.myTargetFoot) * 240 / 3;
if (Number.parseInt(this.data.footNumAll) >= Number.parseInt(this.data.myTargetFoot)) {
times = 80
}
let step = this.data.footNumAll / times
this.timerNum = setInterval(() => {
if (tempTimes < times) {
that.setData({
footNum: Math.floor(that.data.footNum + step)
})
tempTimes += 1;
} else {
that.setData({
footNum: that.data.footNumAll
})
clearInterval(that.timerNum)
}
}, 50)
},
写的比较匆忙粗糙,想要理解的话还是需要一段时间的,若是有什么不足也欢迎交流