最近开发了一款自己的小程序,名字叫做哎呦天气,在这个小程序中有两处使用到了画布canvas,所以在此总结一下。首先看一下我用canvas做的两个效果:
第一张截屏中的折线图和第二张截屏中的带有二维码的图片都是使用canvas生成。
OK,开始使用canvas,我们先从简单的做起,先画出带有二维码、地址、温度、背景图的这个图片:
首先生成一个CanvasContext:
const ctx = wx.createCanvasContext('qrCanvas')
那字符串qrCanvas是怎么来的呢,其实是在wxml文件中定义的:
可以看到canvas-id就为qrCanvas.
得到CanvasContext之后呢,我们先画背景图,就是那张漂亮的风景图,主要代码如下:
let width = systemInfo.windowWidth
let height = 300
ctx.drawImage(bgPicturePath, 0, 0, width, height)
重点代码为ctx.drawImage,它有五个参数,第一个背景图地址(必须为本地地址,网络地址不可以),第二个和第三个为起点坐标,第四个和第五个为图片的宽高。
下面我们画一个白色的长方形,位于背景图的下面,里面有二维码图片等:
ctx.setFillStyle('white')//填充白色
ctx.fillRect(0, height - 60, width, 60)//坐标x:0,y:height-60 宽高。。。
然后吧二维码在画上去:
ctx.drawImage(qrPicturePath, 5, height - 57, 55, 55)
下面我们就开始画文字了,
ctx.moveTo(width / 2, 20)//画笔移动到垂直居中位置(高度20不重要,我随便写的)
ctx.setTextAlign('center')//设置文字要垂直居中
ctx.setFillStyle('#333')//字体颜色
ctx.setFontSize(15)//字体大小
ctx.fillText("哎呦天气,不错哦!", width / 2, height - 25)//字体内容和位置
然后画地址、温度、风向等:
ctx.setFillStyle('white')
//地址
ctx.setFontSize(13)
ctx.fillText('上海', width / 2, 30)
//温度
ctx.setFontSize(50)
ctx.fillText(currentTmp, width / 2, 120)
//天气
ctx.setFontSize(15)
ctx.fillText(cond, width / 2, 160)
//风向
ctx.setFontSize(15)
ctx.fillText(wind, width / 2, 190)
最后呢,调用
ctx.draw()
就可以展示在Page上了,那怎么保存成一张图片呢:
wx.canvasToTempFilePath({
canvasId: 'qrCanvas',
success: function (res) {
console.log(res)
wx.hideLoading()
wx.previewImage({
urls: [res.tempFilePath]
})
}
})
下面的方法就是把画布生成图片并预览。
OK 下面介绍温度折线图的制作,直接上代码吧:
wxml中:
js中:
function drawForecastView(forecast){//参数forecast为数据模型
const forecastCtx = wx.createCanvasContext('forcastCanvas')
console.log("forecastWeather", forecast)
let width = systemInfo.windowWidth
let height = 130
let dot = width / 12
let maxTmp = parseInt(forecast[0].tmp_max)
let minTmp = parseInt(forecast[0].tmp_min)
forecast.forEach((item)=>{
if (maxTmp < parseInt(item.tmp_max)){
maxTmp = parseInt(item.tmp_max)
}
if (minTmp > parseInt(item.tmp_min)) {
minTmp = parseInt(item.tmp_min)
}
})
let average = (minTmp + maxTmp) / 2 //此温度在height/2的位置
let dValue = maxTmp - average
let gradient = 4;
while (gradient * dValue > height / 2 - 30){
gradient = gradient - 0.5
}
console.log('倍数', gradient)
let flag = 1
forecastCtx.beginPath()
//最高温度
forecast.forEach((item)=>{
let x1 = flag * dot;
let y1 = height / 2 - (parseInt(item.tmp_max) - average) * gradient
item.maxX = x1
item.maxY = y1
//画线
if (flag == 1){
forecastCtx.moveTo(x1, y1)
}else{
forecastCtx.lineTo(x1, y1)
}
//画圆圈
forecastCtx.arc(x1, y1, 3, 0, 2 * Math.PI)
flag = flag + 2
})
forecastCtx.setStrokeStyle("#FF8C00");
forecastCtx.stroke()
//最低温度
forecastCtx.beginPath()
flag = 1
forecast.forEach((item) => {
let x2 = flag * dot;
let y2 = height / 2 + (average - parseInt(item.tmp_min)) * gradient
item.minX = x2
item.minY = y2
//画线
if (flag == 1) {
forecastCtx.moveTo(x2, y2)
} else {
forecastCtx.lineTo(x2, y2)
}
//画圆圈
forecastCtx.arc(x2, y2, 3, 0, 2 * Math.PI)
flag = flag + 2
})
forecastCtx.setStrokeStyle("#7cb5ec");
forecastCtx.stroke()
console.log(forecast)
forecastCtx.setFontSize(12)
forecastCtx.setTextAlign('center')
//画文字
for (var i = 0; i < forecast.length; i++) {
forecastCtx.moveTo(forecast[i].maxX, 20)
forecastCtx.fillText(" " + forecast[i].tmp_max + "°", forecast[i].maxX, forecast[i].maxY - 10)
forecastCtx.fillText(" " + forecast[i].tmp_min + "°", forecast[i].minX, forecast[i].minY + 20)
}
forecastCtx.draw()
}
最后呢附上我的小程序的二维码:
微信搜索黑白色调关注我吧