欠下的生成海报的功能终于补上了
周末花了点时间把小程序版博客中的生成海报的功能给完成了,对于新手的我来说遇到的问题还是挺多的,这里简单记录下坑。
首先看下效果图:
效果截图
思路
还是比较简单,主要就是利用微信提供的画布canvas
来动态构造海报。引导用户保存至本地相册,用于分享。
主要涉及小程序画布和图片相关的API,若是不太熟悉的话可以优先参考下文档。
资源准备
首先需要准备构成海报的一些资源,比如文章的首图,标题,需要分享的小程序码。对于文章的首图,是从腾讯云的对象存储中获取,需要在开发设置中配置好downloadFile合法域名
,至于为什么转战腾讯云对象存储可以参考免费的对象存储——七牛云还是腾讯云
获取图片可直接通过wx.getImageInfo
,对应的API还是比较简单的:
wx.getImageInfo({
src: url,
success (res) {
console.log(res.path)
}
})
至于小程序码,目前使用的是小程序本身的,暂时没有动态生成,后期会迭代。直接将小程序码上传至云存储上,获取时也比较简单:
代码语言:javascript复制wx.cloud.downloadFile({
fileID: fileID
}).then(res => {
console.log(res.tempFilePath)
})
最后,其他需要在海报上展现的内容,根据实际情况进行获取。
生成海报
资源准备完之后,就需要利用画布进行构造海报了。
在wxml添加canvas元素,需要注意的是避免在页面上展示,可以将位置设置在屏幕之外,比如top:99999rpx
<!--画布:生成海报-->
<view class="canvas-box">
<canvas style="width: 600px;height: 970px;" canvas-id="mycanvas" />
</view>
然后需要了解下canvas相关API和属性了。
优先创建canvas的绘图上下文CanvasContext
对象,然后通过CanvasContext中的属性进行绘制,最后通过draw()
将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中。具体可以参考下面的代码,结合注释和官方文档很容易理解:
var context = wx.createCanvasContext('mycanvas');
context.setFillStyle('#ffffff');//设置填充色
context.fillRect(0, 0, 600, 970);//填充一个矩形。用 setFillStyle 设置矩形的填充色
context.drawImage(postImageLocal, 0, 0, 600, 300); //绘制首图
context.drawImage(qrcodeLoal, 210, 650, 180, 180); //绘制二维码
context.setFillStyle("#000000");
context.setFontSize(20);//设置字体大小
context.setTextAlign('center');//设置字体对齐
context.fillText("阅读文章,请长按识别二维码", 300, 895);
context.setFillStyle("#000000");
context.beginPath() //分割线
context.moveTo(30, 620)
context.lineTo(570, 620)
context.stroke();
context.setTextAlign('left');
context.setFontSize(40);
if (title.lengh <= 12) {
context.fillText(title, 40, 360);//文章标题
} else {
context.fillText(title.substring(0, 12), 40, 360);
context.fillText(title.substring(12, 26), 40, 410);
}
context.setFontSize(20);
if (custom_excerpt.lengh <= 26) {
context.fillText(custom_excerpt, 40, 470);//文章描述
} else {
context.fillText(custom_excerpt.substring(0, 26), 40, 470);
context.fillText(custom_excerpt.substring(26, 50) '...', 40, 510);
}
context.draw();
这里需要注意的是填写文字时,画布是不会自动换行的,所以这里需要根据字体大小和字体多少来自行控制换行。
在填充完canvas之后,通过wx.canvasToTempFilePath
来生成图片,并保存在临时路径下,具体代码如下:
wx.canvasToTempFilePath({
canvasId: 'mycanvas',
success: function(res) {
var tempFilePath = res.tempFilePath;
wx.hideLoading();
console.log("海报图片路径:" res.tempFilePath);
that.setData({
showPosterPopup: true,//展示弹窗
showPosterImage: res.tempFilePath //对应路径
})
},
fail: function(res) {
console.log(res);
}
});
到这里,最简单的海报生成完成了,接下来就是涉及交互了。
交互样式
首先利用zanui的zan-popup
来实现弹出层,还是比较方便的。具体样式就不贴了,可以直接看我的源码。
弹出层中加载生成好的海报图片,通过按钮引导用户保存至本地相册,在保存相册时,需要用户授权本地相册的权限,这里需要做好交互,当用户拒绝之后再次想保存时,让他重新授权。
第一次保存图片时
当用户取消时,再次提醒:
再次引导授权
具体代码如下,供参考:
代码语言:javascript复制/**
* 保存海报图片
*/
savePosterImage: function() {
let that = this
wx.saveImageToPhotosAlbum({
filePath: that.data.showPosterImage,
success(result) {
console.log(result)
wx.showModal({
title: '提示',
content: '二维码海报已存入手机相册,赶快分享到朋友圈吧',
showCancel: false,
success: function(res) {
that.setData({
showPosterPopup: false
})
}
})
},
fail: function(err) {
console.log(err);
if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
console.log("再次发起授权");
wx.showModal({
title: '用户未授权',
content: '如需保存海报图片到相册,需获取授权.是否在授权管理中选中“保存到相册”?',
showCancel: true,
success: function(res) {
if (res.confirm) {
console.log('用户点击确定')
wx.openSetting({
success: function success(res) {
console.log('打开设置', res.authSetting);
wx.openSetting({
success(settingdata) {
console.log(settingdata)
if (settingdata.authSetting['scope.writePhotosAlbum']) {
console.log('获取保存到相册权限成功');
} else {
console.log('获取保存到相册权限失败');
}
}
})
}
});
}
}
})
}
}
});
}
到这里,小程序的生成海报功能基本上就完成了。
总结
其实生成海报的功能还有很多小问题,由于最近项目比较紧匆匆上了,后面找时间会优化。
通过生成海报的功能,主要还是学习了画布的API,并通过实战也基本可以上手canvas,至于画布上排版,样式就需要自己耐心了,尤其是一些小地方。
程序上线后我才发现,海报上的标题,由于有中英文,所占的字符不同,所以换行的处理过于草率了,导致有英文的标题在位置上存在偏差。
后期有空的话再持续改善吧~