1.注意事项 canvas中使用的网络图片地址, 必须在微信小程序后台设置下载白名单 , 就是后台返回的url地址域名
3.canvas中直接使用微信头像地址会报错 , 需要使用 wx.downloadFile把微信头像地址下载下来转换成临时地址, 然后在ctx.drawImage中使用
<template>
<view>
<view @click="handleShowPoster">生成海报</view>
<uni-popup ref="haibao" type="bottom">
<view class="haibao_cent">
<image style="width: 96%; height:90vh;margin-left: 2%;" @click="shibie(canvasToTempFilePath)" :src="canvasToTempFilePath" mode=""></image>
<view class="saveFn">
<view @click="saveShareImg(canvasToTempFilePath)">保存图片</view>
<view @click="handleCancel">取 消</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
export default {
data() {
return {
userName:'微信昵称111',
codeUrl : 'https://gx.cnncb.com/api/order/hx_qrcode.html?order_no=16424131343910&shop_id=1&time=1642413134',
coverUrl : 'https://thirdwx.qlogo.cn/mmopen/vi_32/geD3fBVGs5X4kcAkV2Nd56IAAtF8mr5cOQgLaCGoYiaszKv11UPhicltOEAQm6RUNX4gOicS0owicmp9NjqkT3Lxqw/132',
headUrl : 'https://gx.cnncb.com/132.jpg',
ratio: 1,
ctx: null, // 创建canvas对象
canvasToTempFilePath: null, // 保存最终生成的导出的图片地址
openStatus: true // 声明一个全局变量判断是否授权保存到相册
}
},
onShow() {
this.getUserInfo();
},
methods: {
handleShowPoster() {
this.$refs.haibao.open();
},
handleCancel() {
this.$refs.haibao.close();
},
getUserInfo(){
this.$api.userInfo().then(res =>{
wx.downloadFile({//下载
url: res.data.avatar,//服务器上的pdf地址
success: function (res1) {
//console.log('头像临时地址',res1)
that.headUrl = res1.tempFilePath
}
})
})
},
shibie(url){
wx.previewImage({
current: url, // 当前显示图片的http链接
urls: [url], // 需要预览的图片http链接列表
})
},
// 生成海报
async createCanvasImage() {
let self = this;
// 点击生成海报数据埋点
if (!self.ctx) {
wx.showLoading({
title: '生成中...'
});
let code = new Promise(function(resolve) {
wx.getImageInfo({
src: that.codeUrl,
success: function(res) {
resolve(res.path);
},
fail: function(err) {
console.log(err);
wx.showToast({
title: '网络错误请重试',
icon: 'loading'
});
}
});
});
let cover = new Promise(function(resolve) {
wx.getImageInfo({
src: that.coverUrl,
success: function(res) {
resolve(res.path);
},
fail: function(err) {
console.log(err);
wx.showToast({
title: '网络错误请重试',
icon: 'loading'
});
}
});
});
// 头像
let headImg = new Promise(function(resolve) {
wx.getImageInfo({
src: that.headUrl,
success: function(res) {
resolve(res.path);
},
fail: function(err) {
console.log(err);
wx.showToast({
title: '网络错误请重试',
icon: 'loading'
});
}
});
});
Promise.all([headImg, code,cover]).then(function(result) {
const ctx = wx.createCanvasContext('myCanvas');
console.log(ctx, self.ratio, 'ctx');
let canvasWidthPx = 690 * self.ratio,
canvasHeightPx = 1040 * self.ratio,
avatarurl_width = 110, //绘制的头像宽度
avatarurl_heigth = 110, //绘制的头像高度
avatarurl_x =65, //绘制的头像在画布上的位置
avatarurl_y = 15, //绘制的头像在画布上的位置
codeurl_width = 180, //绘制的二维码宽度
codeurl_heigth = 180, //绘制的二维码高度
codeurl_x = 450, //绘制的二维码在画布上的位置
codeurl_y = 680, //绘制的二维码在画布上的位置
coverurl_width = 610, //绘制的封面宽度
coverurl_heigth = 500, //绘制的封面高度
coverurl_x = 40, //绘制的封面在画布上的位置
coverurl_y = 160; //绘制的封面在画布上的位置
ctx.drawImage('/static/hbbj.png', 0, 0, 690, 1040); // 背景图片需要本地
// 白底
ctx.setFillStyle('#ffffff')
ctx.fillRect(25, 150, 640, 900)
ctx.save(); // 先保存状态 已便于画完圆再用
ctx.beginPath(); //开始绘制
//先画个圆 前两个参数确定了圆心 (x,y) 坐标 第三个参数是圆的半径 四参数是绘图方向 默认是false,即顺时针
ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);
ctx.clip(); //画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
ctx.drawImage(result[0], avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推进去图片
ctx.restore(); //恢复之前保存的绘图上下文状态 可以继续绘制
ctx.font = 'normal bold 35px sans-serif';
ctx.setFillStyle('#ffffff'); // 文字颜色
ctx.fillText(that.userName, 240, 65); // 绘制文字
ctx.setFillStyle('#ffffff'); // 文字颜色
ctx.setFontSize(30); // 文字字号
ctx.fillText('向您推荐精美商品', 240, 110); // 绘制文字
// 白底
ctx.setFillStyle('#CBE6FE')
ctx.fillRect(28, 880, 636, 160)
ctx.drawImage('/static/logo.png', 70, 900, 120, 120); // 背景图片需要本地
ctx.font = 'normal bold 30px sans-serif';
ctx.setFillStyle('#222222');
ctx.fillText('郑州知网文化传播有限公司', 220, 950);
ctx.font = 'normal normal 26px sans-serif';
ctx.setFillStyle('#666666'); // 文字颜色
ctx.fillText('郑州市紫荆山路62号兴达国贸2416室', 220, 1000); // 绘制文字
ctx.beginPath();
// 设置线宽
// ctx.lineWidth = 1;
// // 设置间距(参数为无限数组,虚线的样式会随数组循环)
// ctx.setLineDash([10, 10]);
// // 移动画笔至坐标 x20 y20 的位置
// ctx.moveTo(30, 830);
// // 绘制到坐标 x20 y100 的位置
// ctx.lineTo(660, 830);
// // 填充颜色
// ctx.strokeStyle="#aaaaaa";
// 开始填充
ctx.stroke();
ctx.closePath();
ctx.font = 'normal normal 36px sans-serif';
ctx.setFillStyle('#E65449'); // 文字颜色
ctx.fillText('长按识别', 40, 740); // 绘制孩子百分比
ctx.font = 'normal normal 36px sans-serif';
ctx.setFillStyle('#222222'); // 文字颜色
ctx.fillText('小程序码', 200, 740); // 绘制孩子百分比
ctx.font = 'normal normal 36px sans-serif';
ctx.setFillStyle('#222222'); // 文字颜色
ctx.fillText('查看商品详情信息', 50, 800); // 绘制孩子百分比
console.log('result[1]',result[1])
ctx.drawImage(result[2], coverurl_x, coverurl_y, coverurl_width, coverurl_heigth); // 绘制封面
ctx.drawImage(result[1], codeurl_x, codeurl_y, codeurl_width, codeurl_heigth); // 绘制头像
ctx.draw(false, function() {
// canvas画布转成图片并返回图片地址
wx.canvasToTempFilePath({
canvasId: 'myCanvas',
success: function(res) {
self.canvasToTempFilePath = res.tempFilePath;
self.showShareImg = true;
console.log(res.tempFilePath, 'canvasToTempFilePath');
wx.showToast({
title: '绘制成功'
});
},
fail: function() {
wx.showToast({
title: '绘制失败'
});
},
complete: function() {
wx.hideLoading();
wx.hideToast();
}
});
});
});
}
},
// 保存到系统相册
saveShareImg: function(canvasToTempFilePath) {
let self = this;
// 保存海报
self.saveId = '保存海报';
// 获取用户是否开启用户授权相册
if (!self.openStatus) {
wx.openSetting({
success: result => {
if (result) {
if (result.authSetting['scope.writePhotosAlbum'] === true) {
self.openStatus = true;
self.$refs.haibao.close();
wx.saveImageToPhotosAlbum({
filePath: canvasToTempFilePath,
success() {
self.showShareImg = false;
wx.showToast({
title: '图片保存成功,快去分享到朋友圈吧~',
icon: 'none',
duration: 2000
});
},
fail() {
wx.showToast({
title: '保存失败',
icon: 'none'
});
}
});
}
}
},
fail: () => {},
complete: () => {}
});
} else {
wx.getSetting({
success(res) {
// 如果没有则获取授权
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
self.openStatus = true;
wx.saveImageToPhotosAlbum({
filePath: canvasToTempFilePath,
success() {
self.showShareImg = false;
self.$refs.haibao.close();
wx.showToast({
title: '图片保存成功,快去分享到朋友圈吧~',
icon: 'none',
duration: 2000
});
},
fail() {
wx.showToast({
title: '保存失败',
icon: 'none'
});
}
});
},
fail() {
// 如果用户拒绝过或没有授权,则再次打开授权窗口
self.openStatus = false;
console.log('请设置允许访问相册');
wx.showToast({
title: '请设置允许访问相册',
icon: 'none'
});
}
});
} else {
// 有则直接保存
self.openStatus = true;
wx.saveImageToPhotosAlbum({
filePath: canvasToTempFilePath,
success() {
self.showShareImg = false;
wx.showToast({
title: '图片保存成功,快去分享到朋友圈吧~',
icon: 'none',
duration: 2000
});
},
fail() {
wx.showToast({
title: '保存失败',
icon: 'none'
});
}
});
}
},
fail(err) {
console.log(err);
}
});
}
}
},
}
</script>
<style lang="scss" scoped>
.haibao_cent{
width: 100%;
height: 100vh;
.saveFn{
padding: 0 3%;
display: flex;
margin-top: 10px;
justify-content: space-between;
view:nth-child(1){
width: 120px;
height: 40px;
padding: 0 10px;
line-height: 40px;
background-image: linear-gradient(to right, #FF582E, #FE462A, #FE2923, #FE0D1D);
text-align: center;
color:#FFFFFF;
border-radius: 20px;
};
view:nth-child(2){
width: 120px;
height: 40px;
padding: 0 10px;
line-height: 40px;
text-align: center;
color:#000;
border-radius: 20px;
font-weight: 600;
background-image: linear-gradient(to right, #e4d7d4, #cebebc, #e0d4d4, #efe3e5);
}
}
}
}
</style>