先說一下做功能前的感受,簡直一臉懵逼,第一次用canvas,只知道是個畫布,其余什么都不知道…琢磨了一天才畫出來…
開始之前百度了很久,想看看別人怎么寫的,但是目前網(wǎng)上基本上用的都是wx.createCanvasContext這個api,但是這個api已經(jīng)停止維護了,要求使用canvas代替,
?https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.createCanvasContext.html
上面是官方文檔的出處,只好開始硬懟canvas文檔,言歸正傳,下面是我的代碼。
第一步是先創(chuàng)建canvas標簽;
?
<canvas wx:if="{{isshow}}" type="2d" id="Canvas" canvas-id="Canvas" style="width: {{ windowW }}px; height: {{ windowH }}px;"></canvas>
第二步是獲取手機系統(tǒng)信息,拿到手機屏幕的寬高以及設備像素比
getSystemInfo() {
let that = this
wx.getSystemInfo({
success: function (res) {
console.log(res);
that.setData({
windowW: res.windowWidth,
windowH: res.windowHeight,
pixelRatio: res.pixelRatio
})
},
})
},
第三步是拿到canvas對象實例返回用于在畫布上的環(huán)境,這里拿canvas節(jié)點實例用到wx.createSelectorQuery()這個api,拿到畫布后就可以開始插入圖片,繪制矩形等操作,這里要注意小程序要先縮放畫布,如果不縮放,會導致畫布過大不適應手機屏幕,canvas的像素單位是px,所以不能自適應屏幕,需要做換算,我換算的原理是設計稿的寬度是750,所以我按照設計稿的寬度進行換算,后來聽我?guī)煾嫡f用rem也可以,但是懶得換了,就沒換了哈哈哈。
?
createcanvas: function () {
this.setData({
isshow: true
})
let that = this,
windowW = that.data.windowW,
windowH = that.data.windowH;
const query = wx.createSelectorQuery() //獲取對象實例
query.select('#Canvas') //選擇獲取canvas對象實例
.fields({ //獲取節(jié)點的相關信息。需要獲取的字段在fields中指定。
node: true,
size: true
})
.exec((res) => {
console.log(res);
const canvas = res[0].node //拿到canvas對象
that.setData({ //這里保存canvas對象是因為下面保存相片要用這個對象
canvas
})
const ctx = canvas.getContext('2d') //返回用于在畫布上繪圖的環(huán)境
const dpr = that.data.pixelRatio //拿到設備像素比
canvas.width = res[0].width * dpr //縮放畫布
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr)
//1、繪制背景圖(本地圖片)
const imgbg = canvas.createImage()
imgbg.onload = (e) => {
console.log(1);
ctx.drawImage(imgbg, 0.133 * windowW, (windowW - 100) * 0.2, (windowW - 100), (windowW - 100) * 1.38) //50
//繪制上半部內(nèi)容背景區(qū)域
that.roundRect(ctx, 0.16 * windowW, (windowW - 100) * 0.25, (windowW - 122), (windowW - 100) * 0.89, 8, '#fff') // 59
//繪制下半部內(nèi)容背景區(qū)域
that.roundRect(ctx, 0.16 * windowW, (windowW - 100) * 1.19, (windowW - 122), (windowW - 100) * 0.33, 8, '#fff') //59
//2、繪制商品圖片及文字
const imggood = canvas.createImage()
imggood.onload = (e) => {
console.log(2);
ctx.drawImage(imggood, 0.205 * windowW, (windowW - 100) * 0.28, (windowW - 154), (windowW - 100) * 0.61)
//設置文字
let str = '50元購100元代金券,任何商品可使用。具體解釋權歸商場所有。'
let chr = str.split(""); //這個方法是將一個字符串分割成字符串數(shù)組
let temp = "";
let row = [];
ctx.font = "12px";
ctx.fillStyle = "#313648";
// console.log(ctx.measureText(str)); //查看文本長度
//如果文字過長設置為兩行
for (let a = 0; a < chr.length; a++) {
if (ctx.measureText(temp).width < (windowW - 184)) {
temp += chr[a];
} else {
a--; //這里添加了a-- 是為了防止字符丟失,效果圖中有對比
row.push(temp);
temp = "";
}
}
row.push(temp);
if (row.length > 2) {
let rowCut = row.slice(0, 2);
let rowPart = rowCut[1];
let test = "";
let empty = [];
for (let a = 0; a < rowPart.length; a++) {
if (ctx.measureText(test).width < (windowW - 184)) {
test += rowPart[a];
} else {
break;
}
}
empty.push(test);
let group = empty[0] + "..." //這里只顯示兩行,超出的用...表示
rowCut.splice(1, 1, group);
row = rowCut;
}
for (let b = 0; b < row.length; b++) {
// console.log(row[b]);
ctx.fillText(row[b], 0.23 * windowW, (windowW - 100) * 1 + b * 20); //85
}
//3、繪制底部數(shù)據(jù)
const imgava = canvas.createImage()
imgava.onload = (e) => {
console.log(3);
//繪制頭像
ctx.drawImage(imgava, 0.24 * windowW, (windowW - 100) * 1.24, windowW * 0.06, windowW * 0.06) // 90
//繪制微信名
ctx.font = "12px";
ctx.fillStyle = "#313648";
ctx.fillText('梅梅', 0.333 * windowW, (windowW - 100) * 1.29); //125
}
imgava.src = '../../images/phone.png'
//4、繪制搶購價圖片
const imgqgj = canvas.createImage()
imgqgj.onload = (e) => {
console.log(4);
//繪制頭像
ctx.drawImage(imgqgj, 0.24 * windowW, (windowW - 100) * 1.35, 0.101 * windowW, 0.04 * windowW) //90
//繪制價格
ctx.font = "14px sans-serif";
ctx.fillStyle = "#e62e0a";
ctx.fillText('¥98.00', 0.368 * windowW, (windowW - 100) * 1.395); //138
//繪制喜歡的人
ctx.font = "12px sans-serif";
ctx.fillStyle = "#e62e0a";
ctx.fillText('11846人喜歡', 0.24 * windowW, (windowW - 100) * 1.47); //90
//繪制小程序二維碼圖片
const imgqrcode = canvas.createImage()
imgqrcode.onload = (e) => {
console.log(5);
//繪制二維碼
ctx.drawImage(imgqrcode, 0.64 * windowW, (windowW - 100) * 1.225, 0.144 * windowW, 0.144 * windowW)
//繪制長按購買
that.roundRect(ctx, 0.624 * windowW, (windowW - 100) * 1.44, 0.182 * windowW, 0.043 * windowW, 16, '#d94413')
//繪制文字
ctx.font = "10px sans-serif";
ctx.fillStyle = "#fff";
ctx.fillText('長按立即購買', 0.64 * windowW, (windowW - 100) * 1.48);
}
imgqrcode.src = '../../images/2ava.jpg'
}
imgqgj.src = '../../images/qgj.png'
}
imggood.src = '../../images/good.png'
}
imgbg.src = '../../images/1bg.png'
})
},
/**
* 繪制圓角矩形
* @param {Object} ctx - canvas組件的繪圖上下文
* @param {Number} x - 矩形的x坐標
* @param {Number} y - 矩形的y坐標
* @param {Number} w - 矩形的寬度
* @param {Number} h - 矩形的高度
* @param {Number} r - 矩形的圓角半徑
* @param {String} [c = 'transparent'] - 矩形的填充色
*/
roundRect(ctx, x, y, w, h, r, c = '#fff') {
if (w < 2 * r) {
r = w / 2;
}
if (h < 2 * r) {
r = h / 2;
}
ctx.beginPath();
ctx.fillStyle = c;
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
ctx.moveTo(x + r, y);
ctx.lineTo(x + w - r, y);
ctx.lineTo(x + w, y + r);
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2);
ctx.lineTo(x + w, y + h - r);
ctx.lineTo(x + w - r, y + h);
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5);
ctx.lineTo(x + r, y + h);
ctx.lineTo(x, y + h - r);
ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI);
ctx.lineTo(x, y + r);
ctx.lineTo(x + r, y);
ctx.fill();
ctx.closePath();
},
代碼很長,上面的兩處代碼我是百度兩位博主粘貼得來的,比如文字過長分為兩段顯示的代碼、繪制圓角矩形的代碼,但是真不記得是哪位博主了…當時并沒有做記錄,所以如果你看到了,請諒解…
另外我這里的圖片都是線下的圖片,不是線上請求的,因為這個時候后端接口還沒寫好,后期線上圖片有了再更新
第四步是保存圖片到手機
這里主要用到三個api,第一個是wx.canvasToTempFilePath(把當前畫布指定區(qū)域的內(nèi)容導出生成指定大小的圖片),第二個wx.getSetting(這里是查看是否有相冊權限),第三個是wx.saveImageToPhotosAlbum(保存到相冊),這里canvas生成圖片對于2d畫布使用的是canvas屬性,而不是canvasId屬性,要求傳一個對象 這里就是我們在獲取canvas實例的時候保存的canvas,下面是代碼。文章來源:http://www.zghlxwxcb.cn/news/detail-512113.html
//點擊保存海報
savepic() {
let that = this
wx.showLoading({
title: '正在保存',
mask: true
})
console.log(that.data.windowW - 0.133 * that.data.windowW, that.data.windowY - (that.data.windowW - 100) * 0.2);
wx.canvasToTempFilePath({
canvas: that.data.canvas,
x: 0.133 * that.data.windowW,
y: (that.data.windowW - 100) * 0.2,
width: that.data.windowW - 100,
height: (that.data.windowW - 100) * 1.38,
success: function (res) {
console.log(res);
wx.hideLoading()
let tempFilePath = res.tempFilePath
that.checkWritePhotosAlbum(tempFilePath)
},
fail: function (err) {
console.log(err)
wx.showToast({
title: '保存失敗!請重新保存',
icon: 'none'
})
wx.hideLoading()
}
})
},
//查看是否有相冊權限
checkWritePhotosAlbum: function (filePath) {
let that = this
wx.getSetting({
success(res) {
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
that.saveToPhoto(filePath)
},
fail() {
wx.openSetting({
success(res) {
if (res.authSetting['scope.writePhotosAlbum']) {
that.saveToPhoto(filePath)
}
},
fail(res) {
wx.showToast({
title: '您沒有授權,無法保存到相冊!',
icon: 'none'
})
}
})
}
})
} else {
that.saveToPhoto(filePath)
}
}
})
},
//保存到相冊
saveToPhoto: function (filePath) {
let that = this;
wx.saveImageToPhotosAlbum({
filePath: filePath,
success(res) {
wx.showModal({
content: '圖片已保存到相冊,前往相冊即可查看!',
showCancel: false,
confirmText: '好的',
confirmColor: '#333',
success: function (res) {
console.log(res)
that.close()
},
fail: function (res) {
console.log(res)
}
})
},
fail: function (res) {
wx.showToast({
title: res.errMsg,
icon: 'none',
duration: 2000
})
}
})
},
?文章來源地址http://www.zghlxwxcb.cn/news/detail-512113.html
到了這里,關于小程序使用canvas標簽生成海報并保存圖片的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!