小程序canvas制作表盘
小程序中使用canvas如何制作表盘呢?刚开始接触小程序canvas的时候,脑袋都大了一圈,实现功能了又太耗性能,优化了性能,功能又出问题了。刚好手上有个实时监测pm2.5的项目,花了点时间把其中的canvas表盘扣出来做了一个组件
实现思路
-
画背景
先画圆(刻度间有间隔)——> 再给每个方位设置上刻度值(坐标点调了半天) -
实现进度动画
设定区间变更的颜色 ——> 根据开始的值与结束的值开个定时任务,10ms更新一次画布 -
动态更新开始的值与结束的值
组件代码详解
实时接收调用组件的数值变化
//实时接收调用组件的数值变化
observers: {
'end': function(end) {
this.setData({
count: this.properties.start
})
clearInterval(this.data.countTimer)
this.startProgress(this.properties.start, this.properties.end);
}
},
根据pm2.5的值获取颜色跟状态
//根据pm2.5的值获取颜色跟状态
pmtocolor(pm) {
let color = ""
let status = ""
let language = this.properties.language
if (pm <= 50 && pm >= 0) {
color = this.data.colors[0]
status = 0
} else if (pm <= 100 && pm >= 51) {
color = this.data.colors[1]
status = 1
} else if (pm <= 150 && pm >= 101) {
color = this.data.colors[2]
status = 2
} else if (pm <= 200 && pm >= 151) {
color = this.data.colors[3]
status = 3
} else if (pm <= 300 && pm >= 201) {
color = this.data.colors[4]
status = 4
} else if (pm >= 300) {
color = this.data.colors[5]
status = 5
}
return [color, status]
},
绘制表盘背景
//绘制背景
drawProgressbg() {
var context = wx.createCanvasContext('canvasProgressbg', this);
var start = 0.5 * Math.PI;
var point = {
x: this.rpxtopx(this.properties.size / 2 + 25),
y: this.rpxtopx(this.properties.size / 2 + 25)
};
var size = this.rpxtopx(this.properties.size + 50);
let end = 0;
var radius = this.rpxtopx(this.properties.size / 2 - this.properties.long);
for (var i = 1; i < 351; i++) {
context.beginPath();
if (i % 2 == 0) {
end = i / 350 * 2 * Math.PI + 0.5 * Math.PI;
context.setStrokeStyle('rgba(0,0,0,0)');
context.setLineWidth(this.properties.long + 2);
} else {
end = (i - 0.5) / 350 * 2 * Math.PI + 0.5 * Math.PI;
context.setStrokeStyle(this.properties.colorBg);
context.setLineWidth(this.properties.long);
}
context.arc(point.x, point.y, radius, start, end, false);
context.stroke();
start = end;
}
let translates = []
let rotates = []
let texts = []
let device = this.device()
let system = device.system
let width = device.width
translates.push([(size / 229) * 110.5, (size / 229) * 227])
translates.push([(size / 229) * 41, (size / 229) * 188])
translates.push([(size / 229) * 11, (size / 229) * 104.5])
translates.push([(size / 229) * 56, (size / 229) * 28])
translates.push([(size / 229) * 146.5, (size / 229) * 16])
translates.push([(size / 229) * 212, (size / 229) * 78.5])
translates.push([(size / 229) * 203, (size / 229) * 170])
rotates.push(0 * Math.PI / 180)
rotates.push(230 * Math.PI / 180)
rotates.push(282 * Math.PI / 180)
rotates.push(332 * Math.PI / 180)
rotates.push(22 * Math.PI / 180)
rotates.push(78 * Math.PI / 180)
rotates.push(129 * Math.PI / 180)
texts.push('0')
texts.push('50')
texts.push('100')
texts.push('150')
texts.push('200')
texts.push('250')
texts.push('300')
for (let i = 0; i < texts.length; i++) {
this.addFont(context, translates[i], rotates[i], texts[i])
}
context.draw()
},
//动态添加字体
addFont(context, translate, rotate, fillText) {
context.save()
context.translate(translate[0], translate[1]);
context.rotate(rotate);
context.setFillStyle(this.properties.colorBg);
context.setFontSize(12);
context.fillText(fillText, 0, 0);
context.restore();
},
绘制表盘进度动画
/**
* 画progress进度
*/
drawCircle(step) {
// 使用 wx.createContext 获取绘图上下文 context
var context = wx.createCanvasContext('canvasProgress', this);
let color = this.pmtocolor(step)[0]
var start = 0.5 * Math.PI;
var point = {
x: this.rpxtopx(this.properties.size / 2 + 25),
y: this.rpxtopx(this.properties.size / 2 + 25)
};
let end = 0;
var radius = this.rpxtopx(this.properties.size / 2 - this.properties.long);
for (var i = 1; i < step + 1; i++) {
context.beginPath();
if (i % 2 == 0) {
end = i / 350 * 2 * Math.PI + 0.5 * Math.PI;
context.setStrokeStyle('rgba(0,0,0,0)');
context.setLineWidth(this.properties.long + 2);
} else {
end = (i - 0.5) / 350 * 2 * Math.PI + 0.5 * Math.PI;
context.setStrokeStyle(color);
context.setLineWidth(this.properties.long);
}
context.arc(point.x, point.y, radius, start, end, false);
context.stroke();
context.save()
context.restore();
start = end;
}
context.draw();
},
开始表盘进度动画
startProgress(start, end) {
let count = this.data.count
if (start < end) {
this.setData({
index: this.pmtocolor(end)[1],
color: this.pmtocolor(end)[0],
countTimer: setInterval(res => {
if (count < end) {
this.drawCircle(count)
if (end - count > 10) {
count = count + 10;
} else {
count = count + 1;
}
}
}, 10)
})
} else if (start > end) {
this.setData({
color: this.pmtocolor(end)[0],
index: this.pmtocolor(end)[1],
countTimer: setInterval(res => {
if (count > end) {
this.drawCircle(count)
if (count - end > 10) {
count = count - 10;
} else {
count = count - 1;
}
}
}, 10)
})
}
}
组件使用方法
1.下载
npm下载插件
npm install jox-wxapp --save
git下载
git clone https://github.com/jon-son/jox-wxapp.git
2.并将本项目的dist复制进你的项目文件夹根目录
3.页面中调用
demo示例
结尾
一只小菜鸡,欢迎各位大佬指正,github链接:https://github.com/jon-son/jox-wxapp