目前全部的 APP 或者 web 頁面均可以直接分享到朋友圈,從朋友圈看到一條分享動態,很難區別這條動態是公衆號文章,仍是一支 H5 的連接。javascript
相比之下,在朋友圈發一張圖片,會更容易吸引朋友的注意,內容也能夠更直接的曝光。同時微信能夠識別圖片中的二維碼,又能起到迴流做用。java
而單一的圖片又會缺少趣味性。所以,根據用戶的選擇,使用 Canvas 生成自定義的海報圖,成爲了目前主流的 H5 類別。git
瞭解如下 3 個步驟,就能夠完成繪製了:github
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
複製代碼
ctx.drawImage(imageElement,0,0);
ctx.fillText("Hello world", 10, 50);
複製代碼
const imageBase64 = canvas.toDataURL();
複製代碼
以上的步驟爲繪製的關鍵代碼,但實際繪製過程當中仍是會存在一些問題的:web
load
以後才能繪製:const imageElement = new Image();
imageElement.onload = ()=>{
ctx.drawImage(imageElement,0,0);
}
imageElement.src = imageAssetsURL;
複製代碼
那若是要繪製兩張圖片呢?npm
const imageElement = new Image();
imageElement.onload = ()=>{
ctx.drawImage(imageElement,0,0);
// 第一張繪製結束,開始繪製第二張圖片
const imageElementSecond = new Image();
imageElementSecond.onload = ()=>{
ctx.drawImage(imageElementSecond,0,0);
}
imageElementSecond.src = imageAssetsURLSecond;
}
imageElement.src = imageAssetsURL;
複製代碼
那若是要繪製 10 張圖片呢?canvas
使用回調,第二張圖片,只能等第一張圖片繪製完成後才能開始加載。promise
圖片資源是否是能夠同時開始加載?bash
ctx.save();
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = "36px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText("Hello world", 10, 50);
ctx.restore();
複製代碼
須要記憶的語法不少,若是要文本要加粗怎麼設置?微信
先 load
全部圖片,圖片加載完成後統一繪製。
使用 Promise
異步加載圖片,讓全部圖片同時開始加載:
function loadImages(...assetsArr){
const imageArr = [];
const promiseArr = [];
assetsArr.forEach((item,index)=>{
promiseArr.push(new Promise((resolve)=>{
const image = new Image();
imageArr.push(image);
image.onload = ()=>{
resolve(imageArr)
};
image.src = assetsArr[index];
}));
});
return Promise.all(promiseArr);
}
複製代碼
將文本繪製的內容、字體、行高等全部的基本樣式封裝成方法,經過修改對象參數來代替語法規則:
// 初始化默認值
const defaultFontStyle = {
fontStyle:'normal',
fontVariant:'normal',
fontWeight:'normal',
fontSize: 30,
lineHeight: 'normal',
fontFamily: 'Arial',
left: 0,
top: 300,
maxWidth:undefined,
content:'',
textAlign:'start',
textBaseline:'alphabetic',
direction:'inherit',
color: '#000000',
};
// 將文本繪製語法封裝
drawText(obj){
const prop = Object.assign({},defaultFontStyle,obj)
ctx.save();
ctx.fillStyle = prop.color;
ctx.font = `${prop.fontStyle} ${prop.fontVariant} ${prop.fontWeight} ${prop}px/${prop.lineHeight} ${prop.fontFamily}`;
ctx.textBaseline = prop.textBaseline;
ctx.textAlign = prop.textAlign;
ctx.direction = prop.direction;
ctx.fillText(item,prop.left,prop.top,prop.maxWidth);
ctx.restore();
}
// 使用
drawText({content:'Hello world'});
複製代碼
在以上簡單的封裝基礎上,咱們其實能夠加入一些更高級的用法,好比:
Promise
異步加載圖片;本文提到的內容,包括高級進階,能夠 點此 查看源碼。
若是須要直接使用,能夠經過 npm 直接安裝,使用說明以下:
npm i create-picture --save
複製代碼
import CreatePicture from 'create-picture';
// 初始化
const cp = new CreatePicture();
// 初始化(傳參)
const cp:CreatePicture = new CreatePicture({width:750,height:1448});
// 繪製圖片,參數1爲圖片路徑,其餘參數與 CanvasRenderingContext2D.drawImage() 參數相同
cp.drawImage(require('../assets/save_bg.jpg'),0,0);
// 繪製文本
cp.drawText({content:'文本'});
// 繪製文本,獲取文字寬度
const textWidth = cp.drawText({
content:'文本',
fontSize: 30,
top: 300,
color: '#ffffff',
});
// 獲取合成圖
cp.getPicture().then((picture)=>{
// picture 爲合成的 base 64
});
複製代碼