uniapp开发微信小程序canvas生成分享海报 , 一键保存图片, 长按识别小程序码

1.注意事项 canvas中使用的网络图片地址, 必须在微信小程序后台设置下载白名单 , 就是后台返回的url地址域名

2.微信头像域名也要设置下载白名单 , 就是获取到头像url地址的域名(https://thirdwx.qlogo.cn 或者 https://wx.qlogo.cn)

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>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容