相信对于小程序开发得人来说,大家都知道小程序里面的内容分享到朋友圈,只能通过生成一张海报保存到手机然后在进行分享,下面是我在生成海报是遇到的一些问题。
下面这张图呢 就是通过canvas绘制出来的
基本思路是先将内容用canvas排好版,然后把该canvas转化成图片
<!-- 海报 -->
<view class="modal-qrcode" @tap="closeQR" v-if="qrCode" catchtouchmove="preventTouchMove"></view>
<view class="" v-if="qrCode" catchtouchmove="preventTouchMove">
<canvas canvas-id="canvas" @longtap="saveImage"></canvas>
</view>
.modal-qrcode {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: #000;
opacity: 0.7;
overflow: hidden;
z-index: 200;
color: #fff;
}
canvas {
width: 600upx;
height: 900upx;
background: #fff;
border-radius: 10upx;
/* margin: 100upx auto; */
box-shadow: 1upx 1upx 4upx 4upx rgba(0, 0, 0, 0.2);
z-index: 250;
position: fixed;
left: 75upx;
top: 8%;
}
// #ifdef MP-WEIXIN
/**
* 分享到朋友圈
*/
friend: function() {
this._data.qrCode = true;
var ctx = uni.createCanvasContext('canvas');
uni.showLoading({
title: '加载中...',
mask: false
});
// 设置背景颜色
ctx.setFillStyle('#ffffff');
ctx.fillRect(0, 0, 300, 450);
// 背景图
ctx.drawImage(this._data.bgImg, 0, 0, 300, 140);
// 标题
ctx.setFontSize(17); //字体大小
ctx.setFillStyle('#FFFFFF');
textHandle(this.details.new_title, 10, 90, 270, 30);
// 日期
ctx.setFontSize(13);
ctx.setFillStyle('#666');
ctx.fillText(this.details.new_created_at,10, 170, 270, 20);
// 阅读
ctx.setFontSize(13);
ctx.setFillStyle('#666');
ctx.fillText("阅读"+this.details.new_view_count, 230, 170, 270, 20);
// 内容
ctx.setFontSize(15);
ctx.setFillStyle('#000');
textHandle1(this.details.new_desc, 10, 200, 270, 30);
// 二维码文字
ctx.setFontSize(13);
ctx.setFillStyle('#666666');
ctx.fillText('长按保存分享朋友圈', 130, 380);
// 二维码文字
ctx.setFontSize(13);
ctx.setFillStyle('#666666');
ctx.fillText('分享自[IT界的老男孩]', 130, 410);
// 二维码
let id = this._data.id
api.getwxacode(id,res=>{
this.codeQRURL = api.qrURL + res.data.qr_code;
// 服务器返回的二维码
console.log("codeQRURL",this.codeQRURL)
// 给图片一个临时路径
uni.getImageInfo({
src: this.codeQRURL,
success: (res) => {
this.QRURL = res.path
console.log("res",this.QRURL)
ctx.drawImage(res.path, 40, 350, 80, 80)
// 恢复之前保存的绘图
ctx.restore()
// 绘制到canvas
ctx.draw()
}
})
// 隐藏loading提示框
uni.hideLoading()
})
// ctx.drawImage(this._data.img, 10, 360, 80, 80);
function textHandle(text, numX, numY, textWidth, lineHeight) {
var chr = text.split(''); // 将一个字符串分割成字符串数组
var temp = '';
var row = [];
for (var a = 0; a < chr.length; a++) {
if (ctx.measureText(temp).width < textWidth) {
temp += chr[a];
} else {
a--; // 添加a--,防止字符丢失
row.push(temp);
temp = '';
}
}
row.push(temp);
// 如果数组长度大于2 则截取前两个
if (row.length > 2) {
var rowCut = row.slice(0, 2);
var rowPart = rowCut[1];
var test = '';
var empty = [];
for (var a = 0; a < rowPart.length; a++) {
if (ctx.measureText(test).width < textWidth - 10) {
test += rowPart[a];
} else {
break;
}
}
empty.push(test);
var group = empty[0] + '...'; // 这里只显示两行,超出的用...展示
rowCut.splice(1, 1, group);
row = rowCut;
}
for (var b = 0; b < row.length; b++) {
ctx.fillText(row[b], numX, numY + b * lineHeight);
}
}
function textHandle1(text, numX, numY, textWidth, lineHeight) {
var chr = text.split(''); // 将一个字符串分割成字符串数组
var temp = '';
var row = [];
for (var a = 0; a < chr.length; a++) {
if (ctx.measureText(temp).width < textWidth) {
temp += chr[a];
} else {
a--; // 添加a--,防止字符丢失
row.push(temp);
temp = '';
}
}
row.push(temp);
// 如果数组长度大于2 则截取前两个
if (row.length > 5) {
var rowCut = row.slice(0, 5);
var rowPart = rowCut[4];
var test = '';
var empty = [];
for (var a = 0; a < rowPart.length; a++) {
if (ctx.measureText(test).width < textWidth - 10) {
test += rowPart[a];
} else {
break;
}
}
empty.push(test);
var group = empty[0] + '...'; // 这里只显示两行,超出的用...展示
rowCut.splice(3, 3, group);
row = rowCut;
}
for (var b = 0; b < row.length; b++) {
ctx.fillText(row[b], numX, numY + b * lineHeight);
}
}
},
/**
* 长按保存海报
*/
saveImage: function() {
uni.canvasToTempFilePath({
canvasId: 'canvas',
success(res) {
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success(res) {
uni.showToast({
title: '保存成功',
icon: 'success',
duration: 2000,
mask: true
});
}
});
}
});
},
// #endif
完整的代码已经贴出来了,相信大家看完之后觉得并不是很难,在这我遇到了两个坑:
坑一:
之前由于没有写ctx.restore(),在ctx.draw()把二维码绘制到画布上后你之前绘制的那些东西都会消失只留二维码在上面,经过各种方法,各种百度后解决了,这绝对是个大坑
坑二:
返回的图片路径直接插进ctx.drawImage里,在真机上显示不了。
解决方案:利用uni.getImageInfo()这个方法,给图片一个临时路径,然后放到ctx.drawImage()上就行了。
api.getwxacode(id,res=>{
this.codeQRURL = api.qrURL + res.data.qr_code;
// 服务器返回的二维码
console.log("codeQRURL",this.codeQRURL)
// 给图片一个临时路径
uni.getImageInfo({
src: this.codeQRURL,
success: (res) => {
this.QRURL = res.path
console.log("res",this.QRURL)
ctx.drawImage(res.path, 40, 350, 80, 80)
// 恢复之前保存的绘图
ctx.restore()
// 绘制到canvas
ctx.draw()
}
})
// 隐藏loading提示框
uni.hideLoading()
})