前一陣有完成在小程序內動態生成圖片再進行分享的需求,是很常見的場景,所以我抽出了一個小工具CanvasPainter.js,囊括在小程序內canvas畫圖基本需求:git
demo地址github
使用也很簡單~無需染指到wx.各類api
,直接配置初始化+調用對應方法便可,一條龍服務美滋滋~canvas
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, // 組件內使用需傳this
config //畫圖路徑
});
painter.loadImgInAdvance(); //預下載圖片到本地;如不主動調用,則draw的時候會再下載。
// 更新畫圖路徑
painter.resetConfig(newConfig);
// 畫圖
painter.draw().then(() => {
console.log('畫圖完成');
}).catch(e => {
console.log('生成圖片失敗', e);
});
// 預覽
painter.preview();
// 保存
painter.save().then(() => {
console.log('保存完成');
}).catch(e => {
console.log('保存失敗', e);
});
複製代碼
開發過程當中遇到的要點記錄以下:小程序
如何等比縮放api
由於canvas繪圖時的長度單位爲px,因此能夠利用小程序的canvas.scale()來解決。緩存
const scale = wx.getSystemInfoSync().windowWidth / 750;
this.ctx.scale(scale, scale); // 這樣能夠實現以750px尺寸的ui圖等比縮放
複製代碼
繪製圖片預下載及緩存bash
調用ctx.drawImage()
時,圖片須要先下載到本地臨時路徑,這一步耗時較長,因此建議前置進行。臨時路徑的有效期爲一個小程序週期,因此徹底能夠緩存本地臨時路徑。這樣重複生成canvas時只會下載動態圖片,複用固定圖片路徑,避免重複下載~工具
另外圖片域名需配置在小程序後臺,爲避免意外,下載圖片前應先對圖片url作一次校驗,校驗失敗直接跳過下載或換用兜底圖。測試
下載圖片到本地字體
在save圖片前,須要先調用wx.getSetting()
來獲取用戶是否已容許下載圖片到本地權限,或是喚起請求權限彈窗。若是權限被拒絕,則最好給出toast提示,同時把下載按鈕重置爲open-type="openSetting"
,用戶再次點擊時,引導跳轉至受權頁面。
另外使用時也有兩點不舒適提示:
canvas組件顯隱控制
不建議將canvas組件用wx:if控制顯隱,由於將canvas組件掛載至頁面後,要通過200ms左右的延遲才能draw()成功。建議直接用display:none/block來控制,這樣也方便實現圖片預下載。
結合業務抽離組件
建議結合當前業務將生成分享圖功能進一步抽離成組件,包括內嵌點擊canvas預覽圖片,保存canvas爲圖片按鈕(兼容未受權下載圖片跳轉受權頁狀況)等。亦可更靈活的自由控制畫圖及更新畫圖的時機。
注意到這兩點後,就能夠分分鐘擼出一個動態生成圖啦~
new CanvasPainter(options)
options
canvsId
: canvas-id。
context
: canvas使用時上下文,在組件內使用時傳入this便可。
config
: Array[]。繪圖路徑。支持類型以下:
rect 矩形
完整配置:{
type: 'rect',
width: 640,
height: 560,
x:0,
y:0,
color: '#fff', // fill下爲填充顏色,storke下爲筆跡顏色
stroke(可選): true, // 表明模式爲fill仍是stroke。默認false,即fill狀態。
round(可選): true, // 表明是否爲圓形。默認false。
}
複製代碼
text 文本
完整配置:{
type: 'text',
x:0,
y:30,
color: '#fff', // 字色
font: 'xx', // 字體
size: 20, //字號
align: 'center', //對齊。默認left。
decoration(可選): 'line-through', // 暫時只有中劃線模式哈哈哈
}
複製代碼
multiline_text 多行文本
完整配置:{
type: 'multiline_text',
line_limit: 30, //每行字數
line_height: 20, //行高
... //其他都與text一致
}
複製代碼
image 圖片
完整配置:{
type: 'image',
url: '', //圖片路徑
x: '', y: '', width: '', height:'',
round(可選): true, // 圓形。默認false。
}
複製代碼
saleBase(可選)
: 按設計稿尺寸來,默認750。
canvasPainter.loadImgInAdvance()
。可在實例化CanvasPainter後當即調用。
canvasPainter.draw()
canvasPainter.preview()
canvasPainter.save()
canvasPainter.resetConfig(newConfig)