现在好些小程序都会出现这个功能,在使用canvas生成海报时应注意一下几个问题:
1、如果海报中有图片,尽量使用异步,等图片加载完毕在进行画图,这样可以避免海报加载不出来或者空白等问题
2、海报中的图片可为本地图片或者线上图片,本地图片没什么问题;线上图片:首先要考虑图片的域名是否已经配置,这个在测试中最好关闭本地设置中的不合法域名校验,这个以避免本地运行正常,上线后海报无法生成问题
3、下载海报时应注意小程序是否有图库的访问权限
好的,问题说完了,看一下代码吧(PS:代码会生成海报以及一个转发分享按钮):
1、点击界面上分享按钮
share:function(e){
var that = this;
wx.getUserInfo({
success: res => {
this.setData({
avatarPhonto: res.userInfo.avatarUrl
});
}
})
var userName = e.currentTarget.dataset.item.userName;
that.setData({
nowId: e.currentTarget.dataset.id,
maskHidden: true
});
wx.showLoading({
title: '努力生成中...',
})
setTimeout(function () {
that.createNewImg(userName);
}, 1000)
},
createNewImg: function (userName){
var that = this;
var avatarPhonto = that.data.avatarPhonto;
let avatvarImg = new Promise(function (resolve, reject) {
wx.getImageInfo({
src: avatarPhonto,
success: function (res) {
that.setData({
avatar: res.path
})
resolve(res);
}
})
});
Promise.all([avatvarImg]).then(res => {
const context = wx.createCanvasContext('mycanvas');
context.drawImage(that.data.lookingShareBg, 0, 0, 400, 320)
/*画头像*/
context.save();
context.beginPath();
context.arc(69, 70, 45, 0, 90, false);
context.setStrokeStyle('#ffffff');
context.clip();
context.drawImage(that.data.avatar, 24, 25, 90, 90);
context.restore();
context.stroke();
/*绘制姓名*/
context.setFontSize(24);
context.setFillStyle('#fff');
context.setTextAlign('left');
var name = that.fittingString(context, userName, 260);
context.fillText(name, 126, 60);
context.stroke();
context.draw(true, function () {
wx.canvasToTempFilePath({
canvasId: 'mycanvas',
success: function (res) {
var tempFilePath = res.tempFilePath;
that.setData({
imagePath: tempFilePath
});
wx.hideLoading()
},
fail: function (res) {
console.log(res)
}
})
})
})
},
注意:在生成海报的过程中,文字可以多行显示,代码如下:
/*画图文字隐藏*/
fittingString(_ctx, str, maxWidth) {
let strWidth = _ctx.measureText(str).width;
const ellipsis = '…';
const ellipsisWidth = _ctx.measureText(ellipsis).width;
if (strWidth <= maxWidth || maxWidth <= ellipsisWidth) {
return str;
} else {
var len = str.length;
var str = str.replace(/\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F]/g, "");
while (strWidth >= maxWidth - ellipsisWidth && len-- > 0) {
str = str.slice(0, len);
strWidth = _ctx.measureText(str).width;
}
return str + ellipsis;
}
},
2、现在海报已经生成,点击点击保存到相册并转发分享按钮并调取微自带的转发分享功能,同时关闭海报生成弹框:
//关闭弹层
closeImg: function () {
this.setData({
maskHidden: false
})
},
//点击保存到相册
baocun: function () {
var that = this;
that.setData({
maskHidden: false
})
/*调取转发分享功能即可*/
},
3、好了,一个完整的转发分享功能就做好啦,下面记录一下wxml文件以及CSS文件:
wxml:
<view class='imagePathBox' hidden="{{maskHidden == false}}" bindtap="closeImg">
<image src="{{imagePath}}" class='shengcheng'></image>
<button class='baocun' open-type="share" catchtap='baocun'>分享找活卡片</button>
</view>
<view hidden="{{maskHidden == false}}" class="mask"></view>
<view class="canvas-box">
<canvas style="width: 400px;height: 320px;position:fixed;top:9999px" canvas-id="mycanvas"/>
</view>
CSS文件:
.imagePathBox{
position: fixed;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.7);
top: 0;
left: 0;
display:-webkit-flex;
display:flex;
align-items: center;
justify-content: center;
z-index: 998;
align-content:center;
flex-wrap:wrap;
}
.shengcheng{
width: 640rpx;
height:512rpx;
z-index: 999;
background:#fff;
/* background-image: linear-gradient(to top right, #5aa6fc, #157aea); */
}
.baocun{
width:80%;
height:80rpx;
line-height:80rpx;
color:#fff;
font-size:30rpx;
background-image: linear-gradient(to top right, #5f57ea, #607bee);
display: flex;
align-items: center;
justify-content: center;
margin:40rpx auto 0rpx auto;
}
button[class="baocun"]::after{
border: 0;
}
JS文件中初始配置:maskHidden: false
最后,这是个人用法,如有不当之处欢迎大家进行指正!