前一陣有完成在小程序內(nèi)動態(tài)生成圖片再進(jìn)行分享的需求,是很常見的場景,因此我抽出了一個小工具CanvasPainter.js,囊括在小程序內(nèi)canvas畫圖基本需求:
-
用配置形式繪圖(暫支持單行及多行文本,矩形,圓形,圖片及圓形圖片類型),以及支持后續(xù)預(yù)覽及保存成圖片,且皆為Promise格式。
-
canvas尺寸以一般設(shè)計稿的750px為準(zhǔn)(可配),在不同屏幕機(jī)型下等比縮放。
-
生成圖片時,支持圖片預(yù)下載,及在一個小程序周期內(nèi)緩存圖片下載的tmp路徑。
demo地址

用法
使用也很簡單~無需染指到wx.各種api,直接配置初始化+調(diào)用對應(yīng)方法即可,一條龍服務(wù)美滋滋~
import CanvasPainter from './CanvasPainter';
const config = [
{type:'rect, width: 640, height: 560, x: 0, y: 0, color: '#fff'},
{type: 'text', text: '測試文本', color: '#1499f8',size: 50, x: 30,y: 100}
]
// 初始化
const painter = new CanvasPainter({
canvasId: `canvasId`,
context: this, // 組件內(nèi)使用需傳this
config //畫圖路徑
});
painter.loadImgInAdvance(); //預(yù)下載圖片到本地;如不主動調(diào)用,則draw的時候會再下載。
// 更新畫圖路徑
painter.resetConfig(newConfig);
// 畫圖
painter.draw().then(() => {
console.log('畫圖完成');
}).catch(e => {
console.log('生成圖片失敗', e);
});
// 預(yù)覽
painter.preview();
// 保存
painter.save().then(() => {
console.log('保存完成');
}).catch(e => {
console.log('保存失敗', e);
});
復(fù)制代碼
|
開發(fā)過程中遇到的要點記錄如下:
-
如何等比縮放
因為canvas繪圖時的長度單位為px,所以可以利用小程序的canvas.scale()來解決。
const scale = wx.getSystemInfoSync().windowWidth / 750;
this.ctx.scale(scale, scale); // 這樣可以實現(xiàn)以750px尺寸的ui圖等比縮放
復(fù)制代碼
-
繪制圖片預(yù)下載及緩存
調(diào)用ctx.drawImage()時,圖片需要先下載到本地臨時路徑,這一步耗時較長,所以建議前置進(jìn)行。臨時路徑的有效期為一個小程序周期,所以完全可以緩存本地臨時路徑。這樣重復(fù)生成canvas時只會下載動態(tài)圖片,復(fù)用固定圖片路徑,避免重復(fù)下載~
另外圖片域名需配置在小程序后臺,為避免意外,下載圖片前應(yīng)先對圖片url做一次校驗,校驗失敗直接跳過下載或換用兜底圖。
-
下載圖片到本地
在save圖片前,需要先調(diào)用wx.getSetting()來獲取用戶是否已允許下載圖片到本地權(quán)限,或是喚起請求權(quán)限彈窗。如果權(quán)限被拒絕,則最好給出toast提示,同時把下載按鈕重置為open-type="openSetting",用戶再次點擊時,引導(dǎo)跳轉(zhuǎn)至授權(quán)頁面。
另外使用時也有兩點不溫馨提示:
-
canvas組件顯隱控制
不建議將canvas組件用wx:if控制顯隱,因為將canvas組件掛載至頁面后,要經(jīng)過200ms左右的延遲才能draw()成功。建議直接用display:none/block來控制,這樣也方便實現(xiàn)圖片預(yù)下載。
-
結(jié)合業(yè)務(wù)抽離組件
建議結(jié)合當(dāng)前業(yè)務(wù)將生成分享圖功能進(jìn)一步抽離成組件,包括內(nèi)嵌點擊canvas預(yù)覽圖片,保存canvas為圖片按鈕(兼容未授權(quán)下載圖片跳轉(zhuǎn)授權(quán)頁情況)等。亦可更靈活的自由控制畫圖及更新畫圖的時機(jī)。
注意到這兩點后,就可以分分鐘擼出一個動態(tài)生成圖啦~
附:完整API
初始化
new CanvasPainter(options)
options
canvsId: canvas-id。
context: canvas使用時上下文,在組件內(nèi)使用時傳入this即可。
config: Array[]。繪圖路徑。支持類型如下:
rect 矩形
完整配置:{
type: 'rect',
width: 640,
height: 560,
x:0,
y:0,
color: '#fff', // fill下為填充顏色,storke下為筆跡顏色
stroke(可選): true, // 代表模式為fill還是stroke。默認(rèn)false,即fill狀態(tài)。
round(可選): true, // 代表是否為圓形。默認(rèn)false。
}
復(fù)制代碼
text 文本
完整配置:{
type: 'text',
x:0,
y:30,
color: '#fff', // 字色
font: 'xx', // 字體
size: 20, //字號
align: 'center', //對齊。默認(rèn)left。
decoration(可選): 'line-through', // 暫時只有中劃線模式哈哈哈
}
復(fù)制代碼
multiline_text 多行文本
完整配置:{
type: 'multiline_text',
line_limit: 30, //每行字?jǐn)?shù)
line_height: 20, //行高
... //其余都與text一致
}
復(fù)制代碼
image 圖片
完整配置:{
type: 'image',
url: '', //圖片路徑
x: '', y: '', width: '', height:'',
round(可選): true, // 圓形。默認(rèn)false。
}
復(fù)制代碼
|
預(yù)下載圖片:
canvasPainter.loadImgInAdvance()??稍趯嵗疌anvasPainter后立即調(diào)用。
繪圖:
canvasPainter.draw()
預(yù)覽大圖:
canvasPainter.preview()
保存成圖片:
canvasPainter.save()
更改config:
canvasPainter.resetConfig(newConfig)
|