目前全部的 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
});
复制代码