最近接手开发了一个小程序项目,里面有一个分享封面图功能,做的过程中遇到了一些问题,特此记录
因为目前在小程序中是没有截屏功能的,如果我们需要生成一张完整的封面图做分享,前端最方便的方案大概就是使用canvas了,利用canvas的图片导出功能,可以很方便的生成一张完整的图出来,下面就记录一下过程中遇到的问题
rpx转px
因为canvas中是没有rpx这个单位的,所以当我们在绘制的过程中,先要把rpx转为px
rpxToPx(rpx) {
let px = Math.ceil(rpx / 750 * windowWidth) // windowWidth可以在全局变量中先存储
return px
}
绘制单行文字
这里一共用到了小程序里面的两个api,和一个属性
ctx.setFillStyle
: 设置字体颜色 ctx.setFillStyle(color)
ctx.font
: 设置字体属性 normal weight 16px sans-serif
ctx.fillText
绘制字体 这个api需要注意的是,x和y的坐标是定在文字的左下角的,我们一般画图的x和y都是左上角。当我们画文字时,y的坐标就需要加上文字的行高 ctx.fillText(text, x, y + text.lineHeight)
绘制多行文字
当我们如果需要绘制的文字过长,但是canvas里面又没有自动换行的功能,这时就需要我们手动计算每行文字的显示长度,然后进行截取,这里用到了一个api
measureText
: 它可以测量文本尺寸信息,返回当前文字的宽度
width = ctx.measureText(str).width
然后我们进行累加,当中宽度超出最大宽度的时候,就进行截取,然后重新计算宽度,示例代码
let lastSubStrIndex = 0
let lineHeight = item.lineHeight
let initHeight = item.y
for(let i = 0; i < str.length; i++){
lineWidth += ctx.measureText(str[i]).width
if(lineWidth > maxWidth){
ctx.fillText(str.substring(lastSubStrIndex, i), item.x, initHeight)
initHeight += lineHeight
lastSubStrIndex = i
lineWidth = 0
}
if (i == str.length - 1) {//绘制剩余部分
ctx.fillText(str.substring(lastSubStrIndex, i + 1), item.x, initHeight)
}
}
圆角矩形
drawRect(ctx,obj){
let x = obj.x // x坐标
let y = obj.y // y坐标
let w = obj.w // 宽度
let h = obj.h // 高度
let r = obj.r // 半径
ctx.beginPath();
ctx.setFillStyle('#fff');
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
ctx.moveTo(x + r, y);
ctx.lineTo(x + w - r, y);
ctx.lineTo(x + w, y + r);
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2);
ctx.lineTo(x + w, y + h - r);
ctx.lineTo(x + w - r, y + h);
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5);
ctx.lineTo(x + r, y + h);
ctx.lineTo(x, y + h - r);
绘图
在小程序中,我们如果想把网络图片绘制到canvas中,事先需要先把图片缓存下来,可以使用getImageInfo先把图片缓存下来
wx.getImageInfo({
src: imgUrl,
success: (res) => {
imgUrl = res.path
}
})
保存图片
function savePicToAlbum(tempFilePath,callback) {
let that = this;
wx.getSetting({
success(res) {
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
wx.saveImageToPhotosAlbum({
filePath: tempFilePath,
success(res) {
wx.showToast({
title: '保存成功'
});
callback && callback()
}
})
},
fail() {
// 用户拒绝授权,打开设置页面
wx.openSetting({
success: function (data) {
console.log("openSetting: success");
},
fail: function (data) {
console.log("openSetting: fail");
}
});
}
})
} else {
wx.saveImageToPhotosAlbum({
filePath: tempFilePath,
success(res) {
wx.showToast({
title: '保存成功',
});
},
fail(res) {
console.log(res);
}
})
}
},
fail(res) {
console.log(res);
}
})
}
最后推荐一个小程序里面的图片裁剪组件we-cropper