微信小程序canvas生成分享图到相册

作者: 柚子胖鸡_ | 来源:发表于2018-03-15 17:32 被阅读6066次

    小程序的入口主要集中了以下3个:

    • 二维码
    • 搜索栏
    • 聊天转发

    然而并没有流量大户——朋友圈;虽然小程序不能分享到朋友圈,但其并没有把长按识别二维码的功能阉割;于是乎在朋友圈疯狂转发的便成了一张带小程序码的图片;
    这个功能的实现,在我第一次写小程序的时候困扰了很久;最开始想的重点都在带参数的小程序码上,查资料的时候偏离了轨道,一番搜索之后无疾而终,遂把这锅扔给了服务端,但仍耿耿于怀;第二次又是一番搜索,理清了头绪,就是canvas画一张图的事儿,但canvas我很少写,带着恐惧便没多尝试,一半demo被搁置;N天之后,又想起这事,豁然开朗:)

    思路分解

    源码见文章底部
    1. 二维码如果带有参数 就有服务端发送过来 我们需要的只是图片的url;
    2. 把用到的图片和文字绘制到画布上 wx.createCanvasContext()
    3. 用户点击生成分享图的时候。把画布转成图片wx.canvasToTempFilePath()一直到这里,以上操作对用户都是不可见的,此时生成图片后API会返回图片的路径url,这时可以把拿到的图片url放到一个<image>里展示给用户了;
    4. 再来一个按钮把展示的图片调用wx.saveImageToPhotosAlbum()保存到相册中,完结撒花;

    canvas生成分享图

    真的只是canvas画张图的事儿啊!!!为什么之前脑子像堵塞一般?现在切入正题,一步一步实现生成分享图并保存到相册的功能;

    1. 准备工作

    当然是准备一张画布了 o( ̄︶ ̄)o 顺便把页面结构一起画一下···

    <!-- canvas.wxml -->
    <!-- 画布大小按需定制 这里我按照背景图的尺寸定的  -->
    <canvas  canvas-id="shareImg" style="width:545px;height:771px"></canvas>
    
    <!-- 生成分享图 这里的操作是把canvas绘制的图预览出来  -->
    <button class='share' type='primary' bindtap='share'>生成分享图</button>
    
    <!-- 预览分享图 这里就是上图展示的效果   -->
    <!-- 刚开始是隐藏的 生成分享图之后显示, 用一个布尔变量来控制 这里的样式大家看图就写出来了 -->
    <view hidden='{{hidden}}' class='preview'>
      <image src='{{prurl}}' mode='widthFix'></image>
      <button type='primary' size='mini' bindtap='save'>保存分享图</button>
    </view>
    
    /* pages/canvas/canvas.wxss */
    canvas{
      position: fixed;
      top: 0;
      left: 999px;
    }
    /* 画布绘制过程不能隐藏 但是又不能被用户看见 所以定位在用户看不到地方 */
    

    2. 绘制画布内容

    以图中为例,画布分为三部分: 背景图 、二维码图、描述文字;
    绘图和文字的方法 看小程序开发文档即可 写的很清楚;
    这里注意绘制图片到画布之前 要先调用wx.getImageInfo()获取图片信息;
    废话不多说,直接上代码;

    /* promise可以忽略 是用来改善异步回调执行顺序 与本功能没有大的关系 */
    
    let promise1 = new Promise(function (resolve, reject) {
    
        /* 获得要在画布上绘制的图片 */
        wx.getImageInfo({
            src: '../../public/pics/qrcode.jpg',
            success: function (res) {
              console.log(res)
              resolve(res);
            }
       })
    });
    let promise2 = new Promise(function (resolve, reject) {
        wx.getImageInfo({
            src: '../../public/pics/qrbg.png',
            success: function (res) {
              console.log(res)
              resolve(res);
            }
       })
     });
    
    /* 图片获取成功才执行后续代码 */
     Promise.all(
       [promise1,promise2]
     ).then(res => {
        console.log(res)
    
        /* 创建 canvas 画布 */
        const ctx = wx.createCanvasContext('shareImg')
    
        /* 绘制图像到画布  图片的位置你自己计算好就行 参数的含义看文档 */
        /* ps: 网络图片的话 就不用加../../路径了 反正我这里路径得加 */
        ctx.drawImage('../../' + res[0].path, 158, 190, 210, 210)
        ctx.drawImage('../../'+res[1].path, 0, 0, 545, 771)
      
        /* 绘制文字 位置自己计算 参数自己看文档 */
        ctx.setTextAlign('center')                        //  位置
        ctx.setFillStyle('#ffffff')                       //  颜色
        ctx.setFontSize(22)                               //  字号
        ctx.fillText('分享文字描述', 545 / 2, 130)         //  内容  不会自己换行 需手动换行
        ctx.fillText('分享文字描述', 545 / 2, 160)         //  内容
        
        /* 绘制 */
        ctx.stroke()
        ctx.draw()
        })
    

    3. 画布生成图片

    点击生成分享图时候触发该事件;
    直接调用APIwx.canvasToTempFilePath()即可;
    附上链接wx.canvasToTempFilePath() ;

    var that =this
    wx.canvasToTempFilePath({
          x: 0,
          y: 0,
          width: 545,
          height: 771,
          destWidth: 545,
          destHeight: 771,
          canvasId: 'shareImg',
          success: function (res) {
            console.log(res.tempFilePath);
            /* 这里 就可以显示之前写的 预览区域了 把生成的图片url给image的src */
            that.setData({
              prurl: res.tempFilePath,
              hidden:false
            })
          },
          fail: function (res) {
            console.log(res)
          }
        })
    

    4. 保存图片到相册

    保存图片到相册,这里记得要获取授权(^U^)ノ~YO
    直接调用APIwx.canvasToTempFilePath()即可;
    附上链接wx.saveImageToPhotosAlbum() ;

    var that =this
      wx.saveImageToPhotosAlbum({
          filePath: that.data.prurl,
          success(res) {
            wx.showModal({
              content: '图片已保存到相册,赶紧晒一下吧~',
              showCancel: false,
              confirmText: '好的',
              confirmColor: '#333',
              success: function (res) {
               if (res.confirm) {
                  console.log('用户点击确定');
                  /* 该隐藏的隐藏 */
                  that.setData({
                    hidden:true
                  })
                }
              }
            })
          }
      })
    

    ^ _ ^ 完结撒花,是不是非常简单

    以上代码仅供参考,剩下的全靠freestyle了,有任何问题可与我留言;记得点赞哦
    demo:github 源码地址

    P·S 一个重要问题:圆角头像以及带用户头像的小程序码以下代码放在绘制canvas的最后步骤。头像调好大小位置覆盖在二维码中间位置就好了。

          ctx.save() //这句很重要  保存之前的绘制
          var r = 105
          var cx = 158 + r
          var cy = 190 + r
          ctx.arc(cx, cy, r, 0, 2 * Math.PI)
          ctx.clip()
          ctx.drawImage("图片path", 158, 190, 210, 210)
          ctx.restore() 
          ctx.draw()
    

    版权声明:本文原创,转载请注明出处 https://www.jianshu.com/p/01f526a4f948

    相关文章

      网友评论

      • 工程设计:https://blog.csdn.net/hotqin888/article/details/83044584
        根据大神的程序,总算搞定了,不容易。
        涉及到本地图片,网络图片问题;清晰度问题;html2canvas问题
        柚子胖鸡_:大神不敢当 菜鸟一只 !一起进步
      • chinaz:你好,请问下本地图片换成网络图片后为何无法显示了呢
        苏敏:转成服务端地址或者本地然后download方法即可
      • c2da42007a59:请问一下 小程序中 canvas绘制出来的图片的清晰度 如何提高 在h5端 有一个插件可以实现 但是在小程序中不好用
        柚子胖鸡_:@都是酸奶何必装特仑苏_ce4f 这个没试过 如果你研究出来 还请告知共勉:yum:
        柚子胖鸡_:@都是酸奶何必装特仑苏_ce4f 根据背景尺寸 二维码尺寸 计算它的合适位置
        c2da42007a59:还有个问题 就是二维码的位置 那个258的大小 是从哪计算出来的
      • 渐渐懂了吧:写的很好,按照作者的案例成功实现了效果:+1::+1::+1:
      • 1ca30fbb78a9:想问一下。比如我原本页面上有一个输入框,然后生成图片的时候。想把那个输入框里面的值显示在图片中要怎么做?
        因为我直接 ctx.fillText(this.data.username, 210, 335) 这样没用
        1ca30fbb78a9:@Console_Iog 这个问题我又搞定了。。。:joy: :joy:
        就是在图片上加一个事件。。然后点击预览。如果图片上有小程序二维码是可以识别扫码的
        showImg: function(res){
        var that = this;
        console.log(that.data.prurl);
        wx.previewImage({
        current: that.data.prurl,
        urls: [that.data.prurl],
        })
        },
        然后我再问一个问题。希望大佬不要怪罪。
        因为生成的图片中的内容是要获取当前页面中的一些内容的,或者说一些值,然后我就想在点击按钮(您demo中“生成分享图”的按钮)的时候再去生成图片。但是我把第二点“绘制画布内容”放到那个按钮点击事件里面去执行,生成的是一张漆黑的图片(貌似有点透明)。。请问一下要怎么解决。。
        柚子胖鸡_:@曹超Cc 小程序里好像不能直接长按识别 , demo里已经实现预览功能
        1ca30fbb78a9:好吧。忽略我这个问题。。问一个新问题。。。自己解决了...
        生成后的图片怎么样可以点击预览,想做成那种直接长按识别二维码。:joy: :joy:
      • 808b2204ee0b:你好,怎么获取相册的授权啊
        柚子胖鸡_:官方文档里有
      • 独立寒秋一点点:能发一下完整案例么? 想学习一下 1055450488@qq.com
        独立寒秋一点点:@Console_Iog 额:cold_sweat:
        柚子胖鸡_:@独立寒秋一点点文中有代码链接,您能认真看吗,别上来就伸手。
      • 傫wht:你好,想问一下,canvas画布是在什么时机执行的呢?
        独立创业者案例:@Console_Iog 那如果我onload时要加载全部图片(图片不在同一页面,通过touchmove事件滑动切换),但总不能一次把所有画布全部画出来吧。所以我是在touchmove方法中绘制当前图片的画布。现在问题是:点生成图片第一次没反应,第二次才可以!
        柚子胖鸡_:@傫wht 页面onLoad或onShow时就开始绘制画布
      • 前端_攻城狮:点三次生成分享图 才能生成成功 怎么回事啊?怎么解?
        柚子胖鸡_:@傫wht :+1:
        傫wht:刚才试了一下,这个问题是生成图片和生成画布执行的时机导致的,可以将生成画布的操作放在onLoad中执行,就没问题了
        傫wht:我也遇到了这个问题,请问有解决方案了吗?
      • 小新子666:请问整个页面怎么绘制上去,不只是个图片
        小新子666:@Console_Iog 好的,谢谢
        柚子胖鸡_:@小新子666 那就把整个页面的结构布局在画布上重构一遍。
      • 窒息_2444:关注关注了~
        柚子胖鸡_:@窒息_2444 谢谢~~
      • 乔兰伊雪:我也在学小程序:stuck_out_tongue_closed_eyes:
        柚子胖鸡_:@乔兰伊雪 哈哈一起
      • 打完这仗回家结婚:刚好要用到,感谢

      本文标题:微信小程序canvas生成分享图到相册

      本文链接:https://www.haomeiwen.com/subject/kgkhqftx.html