近期在做一个读书类的小程序,这时需要作出一个半圆形的进度条,等级进度条,就想着用canvas来完成,在网上百度了一下,参阅了这这篇博客博客地址,在结合实际需求加以修改。
这是ui的图片,一看就能知道这个需要自定义标题栏,然后这是一个长图,标题栏和下面的进度条的背景得分开来。上进度条的代码,
wxml
wxss
.progress {
width: 90%;
margin: 0 auto;
height: 470rpx;
position: relative;
}
.canvasI {
width: 470rpx;
height: 470rpx;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin: auto auto;
}
.canvasII {
width: 470rpx;
height: 470rpx;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin: auto auto;
}
让这两个canvas重叠在一起
js
const ctx = wx.createCanvasContext("bgCanvas"); //创建一个全局的canvas绘图上下文
const ctx2 = wx.createCanvasContext("runCanvas");
let mytime = "";
let n = 0;
var w = "";
var h = "";
Page({
/**
* 页面的初始数据
*/
data: {
resurl: app.globalData.resurl,
percent_30: 30,
percent_80: 80,
c_val: 20,
suffix: 300,
menuBarHeight: app.globalData.menuBarHeight,
statusBarHeight: app.globalData.statusBarHeight,
runCanvas:true,
bgCanvas:true
},
run(e) {
let that = this;
let src = that.data.src; //总共需要绘制的弧度
let allSrc = that.data.allSrc; //每个间隔所需绘制的弧度所占比例
n++;
if (src * n > allSrc) {
console.log('结束');
clearInterval(mytime); //如果绘制完成,停掉计时器,绘制结束
n = 0;
//转化成图片
wx.canvasToTempFilePath({
canvasId: 'runCanvas',
success: function(res) {
var tempFilePath = res.tempFilePath;
console.log('图片' + tempFilePath);
that.setData({
runCanvas:false,
runCanvasImg: tempFilePath
})
wx.canvasToTempFilePath({
canvasId: 'bgCanvas',
success:function(succ){
that.setData({
bgCanvas: false,
bgCanvasImg: succ.tempFilePath
})
}
})
},
fail: function(res) {
console.log(res);
}
})
return;
}
let ntitle = that.data.ntitle;
let score = that.data.score;
let count = that.data.count;
let left = that.data.left;
let utitle = that.data.utitle;
ctx2.arc(w, h, w - 8, 0.93 * Math.PI, (0.93 + src * n) * Math.PI); //每个间隔绘制的弧度
ctx2.setStrokeStyle("#27C761");
ctx2.setLineWidth("8");
ctx2.setLineCap("round");
ctx2.stroke();
ctx2.beginPath();
ctx2.setFontSize(24);
ctx2.setFillStyle("#27c761");
ctx2.fillText(ntitle, 95, 60);
ctx2.setFontSize(15);
ctx2.setFillStyle("#27c761");
ctx2.fillText(score, 85, 85);
ctx2.setFillStyle("#fff");
if (count == -1) {
ctx2.fillText('/ ∞', 110, 85);
ctx2.setFontSize(12);
ctx2.fillText('你已经是最高等级' + ntitle, 55, 120);
} else {
ctx2.fillText('/ ' + count, 110, 85);
ctx2.setFontSize(12);
ctx2.fillText('只需' + left + '点积分即可升级为' + utitle, 30, 120);
}
ctx2.draw();
},
canvasTap() {
let that = this;
clearInterval(mytime);
mytime = setInterval(that.run, 5)
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
let that = this;
getLevel({
op: 'grade'
}, function(res) {
let allSrc = res.myself.score / res.myself.count;//计算需要绘制的比例
let count = res.myself.count;//最大的比例
let src = allSrc / 100
if (count == -1) src = 1;
that.setData({
ntitle: res.myself.ntitle,
score: res.myself.score,
count: count,
left: res.myself.left,
utitle: res.myself.utitle,
src: src,
allSrc: allSrc,
upgradeList: res.grade,
myself: res.myself,
explain: res.explain,
})
that.canvasTap();
});
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function() {
var context = wx.createCanvasContext('firstCanvas')
context.draw();
wx.createSelectorQuery().select('#canvas-one').boundingClientRect(function(rect) { //监听canvas的宽高
//获取canvas宽的的一半
w = parseInt(rect.width / 2);
//获取canvas高的一半,
h = parseInt(rect.height / 2);
//获取宽高的一半是为了便于找到中心点
ctx.arc(w, h, w - 8, 0.93 * Math.PI, 2.08 * Math.PI); //绘制圆形弧线
ctx.setStrokeStyle("#dddddd"); //设置填充线条颜色
ctx.setLineWidth("8"); //设置线条宽度
ctx.setLineCap("round"); //设置线条端点样式
ctx.stroke(); //对路径进行描边,也就是绘制线条。
ctx.draw(); //开始绘制
}).exec()
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function() {
},
我这里转换成图片是因为这是一个长图,需要滚动,canvas的层级太高会遮挡标题栏,尝试用cover-view来写标题栏,但是cover-view不能用背景图片,所以把canvas转化成图片就不会被自定义标题栏遮挡了