小程序開發(fā)中劝枣,如果需要做一些生成海報 / 插入文字.圖片的功能汤踏,這個時候canvas控件可以實(shí)現(xiàn)你想要的效果√蛱冢基礎(chǔ)的用法我就不多說了溪胶,難度系不高,下面說兩個我使用canvas做海報功能的時候遇到的3個大坑和多行文本繪制稳诚。
1.canvas中使用 canvas.drawImage() 方法
小程序中canvas.drawImage(imagePaht, 0, 0, 100, 100)里面哗脖,添加畫布基礎(chǔ)圖片只有兩種方式:
第一種:把圖片加載到小程序文件夾中,直接通過image路徑調(diào)用采桃。(圖片少且小可以使用)
第二種:使用云端存儲的圖片地址懒熙。(圖片多且大使用url圖片)
使用第二種方式會出現(xiàn)一個問題,canvas.drawImage()不支持直接使用url圖片地址普办,不會報錯工扎,畫布只會出現(xiàn)繪制上去的圖片/文字,沒有url基礎(chǔ)圖片衔蹲。這個時候我們需要繞過這個url的方法肢娘,把圖片下載到本地緩存呈础,然后取出來使用,看下面代碼橱健。
//url圖片下載到本地
wx.downloadFile({
url: "https://www.image.com",
success: function (sres) {
console.log(sres.tempFilePath);
//確保圖片已下載到本地而钞,再開始進(jìn)行canvas操作
if (sres.tempFilePath){
that.createNewImage(sres.tempFilePath);
}
}, fail: function (fres) {
}
})
/* 處理圖片/文字繪制 */
createNewImage: function (urlPath){
var that = this;
var content = wx.createCanvasContext('mycanvas')
// 把模板圖片繪制到canvas上
content.drawImage(urlPath, 0, 0, 750, 2540);//使用下載的本地圖片
this.setCarName(content);
content.draw();//繪制圖片
//把生成好的圖片保存到本地
xxxxxxxxxxxxxxxxxxxxxxxxx
},
?
2.canvas繪制的海報圖片和想要的效果不一致
一般會出現(xiàn)兩種情況,第一海報只展示了一部分拘荡,第二畫布上的文字/圖片位置沒有出現(xiàn)在規(guī)定的位置臼节,問題出在wxml中canvas的大小 和js中 canvas.drawImage()大小設(shè)置不一致,看代碼
wxml:
<view class='canvas-box'>
<canvas style='width:750px; height:2540px' canvas-id='mycanvas'></canvas>
</view>
js:
canvas.drawImage(urlPath, 0, 0, 750, 2540);
?
3.安卓設(shè)備使用canvas崩潰
canvas繪制的時候有使用大圖進(jìn)行繪制的場景珊皿,這個時候發(fā)現(xiàn)一個奇怪的問題网缝,ios系統(tǒng)加載大圖繪制沒毛病,安卓設(shè)備剛進(jìn)頁面就crash蟋定,不管安卓設(shè)備多牛逼還是會crash粉臊。這個時候需要好好看下官方組件,Bug中明確說到“避免設(shè)置過大的寬高驶兜,在安卓下會有crash的問題”扼仲,所以要好好看文檔,畢竟ios和安卓不是一個媽生的抄淑。
安卓設(shè)備到底多大會crash呢屠凶,我給一個大概的數(shù)字“1200px / 4000px”,在這個范圍內(nèi)應(yīng)該是安全的肆资。
iOS設(shè)備多大會crash呢阅畴,我也不知道啊迅耘!我設(shè)置了“1920px / 9420px”大小的canvas,這么大的像素一點(diǎn)毛病都沒有监署,大家可以試試看極限在哪里颤专。
?
4.canvas繪制多行文本
canvas中繪制多行文本,并不能自動實(shí)現(xiàn)文本換行钠乏。文本的高度和寬度栖秕,換行的位置都需要我們自己處理,下面介紹兩種情況換行處理晓避。
代碼如下:
var str = this.data.importDta.textarea;
var color = app.changeRgbColorToHex('rgb(254, 250, 169)');
var canvasWidth = 550;//計(jì)算canvas的寬度
var initHeight = 2200;//繪制字體距離canvas頂部初始的高度
content.setFontSize(60);//文本字體大小
content.setFillStyle(color);//文本字體顏色
this.drawText(content, str, initHeight, canvasWidth);//文本換行顯示處理方法
content.stroke();
(1)無換行符
整段文字簇捍,固定寬高顯示區(qū)域自動換行
/**
* 繪制多行文本
* @param content canvas對象
* @param str 文本內(nèi)容
* @param initHeight 文本繪制在畫布中的初始高度
* @param canvasWidth 文本繪制的最大寬度
*/
drawText: function (content, str, initHeight, canvasWidth) {
var lineWidth = 0;
var lastSubStrIndex = 0; //每次開始截取的字符串的索引
for (let i = 0; i < str.length; i++) {
lineWidth += content.measureText(str[i]).width;
if (lineWidth > canvasWidth) {
content.fillText(str.substring(lastSubStrIndex, i), 420, initHeight);//繪制截取部分
initHeight += 70;//60為字體的高度
lineWidth = 0;
lastSubStrIndex = i;
}
if (i == str.length - 1) {//繪制剩余部分
content.fillText(str.substring(lastSubStrIndex, i + 1), 420, initHeight);
}
}
}
(2)有換行符
文字中間有換行符 \n , 自動換行+換行符換行
/**
* 繪制多行文本
* @param str 文本內(nèi)容
* @param leftMargin 文本繪制的初始左邊距
* @param initHeight 文本繪制的初始高度
* @param canvasWidth 文本的寬度
*/
//有“\n”換行符的處理方式
drawText: function (content, str, leftMargin, initHeight, canvasWidth) {
var lineWidth = 0
var lastSubStrIndex = 0; //每次開始截取的字符串的索引
for (let i = 0; i < str.length; i++) {
lineWidth += content.measureText(str[i]).width
if (str[i] == "\n") {
content.fillText(str.substring(lastSubStrIndex, i), leftMargin, initHeight);//繪制截取部分
initHeight += 84//文字+間距的高度
lineWidth = 0
lastSubStrIndex = i + 1;
}else if (lineWidth > canvasWidth) {
content.fillText(str.substring(lastSubStrIndex, i), leftMargin, initHeight);//繪制截取部分
initHeight += 84//文字+間距的高度
lineWidth = 0
lastSubStrIndex = i
}
if (i == str.length - 1) {//繪制剩余部分
content.fillText(str.substring(lastSubStrIndex, i + 1), leftMargin, initHeight);
}
}
}
目前只發(fā)現(xiàn)這三個坑,后面有坑會繼續(xù)補(bǔ)充俏拱,希望大家能夠合理的避開這三個坑暑塑,寫出優(yōu)秀的小程序應(yīng)用!