美文网首页
微信小程序+七牛云水印功能 实现自定义图片分享

微信小程序+七牛云水印功能 实现自定义图片分享

作者: zain小宇 | 来源:发表于2020-09-29 10:08 被阅读0次

    需求说明 :

    一个社交 小程序,用户发表动态之后,要求实现点击分享按钮,根据动态内容 生成图片并自定义分享。如果 动态是 文字的话,需要将动态文字 和 ui 给定的背景图 合并生成新的图片,如果动态有图片的情况,需要 将动态第一张图,和ui 给定的背景 合并生成新的图片,替换 onShareAppMessage return 方法中 imageUrl字段。

    WechatIMG206.jpeg
    WechatIMG204.jpeg
    WechatIMG203.jpeg

    踩坑 :

    小程序页面分享很容易实现,只需要在 onShareAppMessagereturn自定义 分享内容就好了,但是如果使用 button 按钮 的 开放能力open-type:share去自定义分享,就会出现问题:button按钮的share 能力,点击button 立即调起 好友列表,并同时触发 onShareAppMessage方法,且事件不可控,无法做延迟操作。也就是说 无法!先本地生成图片,然后替换 自定义图片地址!并且,如果在本地点一个 分享 就生成一个分享图 ,canvas绘制性能太慢,大大影响体验。

    寻找实现方式:

    首先想到的是,在 发表 动态的时候,本地生成分享图,然后 在发表动态接口传给后端,然后前端在 点击 share button 的时候 直接 拿后端 shareimg 地址 替换 onShareAppMessageimgUrl字段。这样都是同步操作,便可以实现 不同动态,不同的分享图片。但是经过后端交涉,认为这种方案,白白浪费服务器资源,每次都生成一个无用的分享图。不值得。

    于是,我就去 找业内 别人的实现方式。 我找的 小打卡小程序。当我用charles 抓包他们点击动态分享时候请求的数据,看到了一个 分享图链接 如下 :

    WechatIMG302.png
    分享图链接:
    http://img-union-cdn.sharedaka.com/noteshare/txt_bg_0.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s=,size_28,text_5omT5Y2h56ys5Zub5aSpICAgIDnmnIgxOOaXpSAg,color_FFFFFF,shadow_0,t_100,g_nw,x_42,y_62/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s=,size_28,text_6ZuoCgrpmIXor7vkuabnsY3vvJrjgIrpnZ7mmrTlipvmsp8=,color_FFFFFF,shadow_0,t_100,g_nw,x_42,y_106/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s=,size_28,text_6YCa44CLCgrnq6DoioLvvJrnrKzkuInnq6DigJzljLrliIY=,color_FFFFFF,shadow_0,t_100,g_nw,x_42,y_150/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s=,size_28,text_6KeC5a-f5ZKM6K-E6K664oCdCgrmkZjlvZXvvJrpnZ7mmrQ=,color_FFFFFF,shadow_0,t_100,g_nw,x_42,y_194/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s=,size_28,text_5Yqb5rKf6YCa55qE56ys5LiA5Liq6KaB57Sg5piv6KeCLi4u,color_FFFFFF,shadow_0,t_100,g_nw,x_28,y_238
    于是我看到http://img-union-cdn.sharedaka.com/noteshare/txt_bg_0.png后面 跟着 一大堆参数,x-oss-process=image/watermark 原来是图片水印。

    于是 我就找到了七牛云 生成水印的地方---图片处理 https://portal.qiniu.com/dora/fop/imageprocess

    image.png

    实现:

    1. 将图片背景图 上传至七牛云
    2. 用可视化编辑器 将 文字 作为水印合成到图片上
    3. 图片同理
      技术文档:https://developer.qiniu.com/dora/api/1316/image-watermarking-processing-watermark
      4 、注意 文字 需要 base64 转码并替换 + /
      image.png

    实现代码 :

    <button data-courseid="{{homeworkData.courseId}}" data-taskid="{{homeworkData.id}}" data-notetext="{{homeworkData.content}}" data-noteimg="{{homeworkData.imgList}}" data-taskname='{{homeworkData.wxNickName}}' open-type="share" hover-start-time="100" class="shareComment" plain="{{true}}" style="border:none">
            <image class="shareIcon" src="./img/work_share.png"></image>
            <text class="samllText">分享</text>
     </button>
    
      onShareAppMessage: function (res) {
        if (res.from == 'button') {
    
    
          let noteImg = res.target.dataset.noteimg
          let notetext = res.target.dataset.notetext
          let shareImgUrl = ''
    
    
          if ((noteImg.length > 0 && notetext) || (notetext && noteImg.length == 0)) {
            // 没有图的情况
            console.log(notetext)
            shareImgUrl = base64Until.dealShareText(notetext)
          } else {
            // 有图的情况
            shareImgUrl = base64Until.dealShareImg(noteImg[0].imgPath)
          }
    
         let shareUrl = `pages/homework/homeworkShare?taskId=${res.target.dataset.taskid}&courseid=${res.target.dataset.courseid}&campClassStudentId=${this.data.indexData.campClassStudentId}`
     
          return {
            title: `${res.target.dataset.taskname}的作业` || '训练营主页',
            path: shareUrl,
            imageUrl: shareImgUrl || ''
          }
        } 
    
      },
    
    
    /*
      *  base64编码(编码,配合encodeURIComponent使用)
      *  @parm : str 传入的字符串
      *  使用:
            1、引入util.js(路径更改) :const util  = require('../../utils/util.js');
            2、util.base64_encode(util.utf16to8('base64 编码'));
     */
    function base64_encode(str) {
      //下面是64个基本的编码
      var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      var out, i, len;
      var c1, c2, c3;
      len = str.length;
      i = 0;
      out = "";
      while (i < len) {
        c1 = str.charCodeAt(i++) & 0xff;
        if (i == len) {
          out += base64EncodeChars.charAt(c1 >> 2);
          out += base64EncodeChars.charAt((c1 & 0x3) << 4);
          out += "==";
          break;
        }
        c2 = str.charCodeAt(i++);
        if (i == len) {
          out += base64EncodeChars.charAt(c1 >> 2);
          out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
          out += base64EncodeChars.charAt((c2 & 0xF) << 2);
          out += "=";
          break;
        }
        c3 = str.charCodeAt(i++);
        out += base64EncodeChars.charAt(c1 >> 2);
        out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
        out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
        out += base64EncodeChars.charAt(c3 & 0x3F);
      }
      return out;
    }
    /*
      *  base64编码(编码,配合encodeURIComponent使用)
      *  @parm : str 传入的字符串
     */
    function utf16to8(str) {
      var out, i, len, c;
      out = "";
      len = str.length;
      for (i = 0; i < len; i++) {
        c = str.charCodeAt(i);
        if ((c >= 0x0001) && (c <= 0x007F)) {
          out += str.charAt(i);
        } else if (c > 0x07FF) {
          out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
          out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
          out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
        } else {
          out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
          out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
        }
      }
      return out;
    }
    
    /*
      *  base64解码(配合decodeURIComponent使用)
      *  @parm : input 传入的字符串
      *  使用:
            1、引入util.js(路径更改) :const util  = require('../../utils/util.js');
            2、util.base64_decode('YmFzZTY0IOe8lueggQ==');
     */
    function base64_decode(input) {
      var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
      var output = "";
      var chr1, chr2, chr3;
      var enc1, enc2, enc3, enc4;
      var i = 0;
      input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
      while (i < input.length) {
        enc1 = base64EncodeChars.indexOf(input.charAt(i++));
        enc2 = base64EncodeChars.indexOf(input.charAt(i++));
        enc3 = base64EncodeChars.indexOf(input.charAt(i++));
        enc4 = base64EncodeChars.indexOf(input.charAt(i++));
        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;
        output = output + String.fromCharCode(chr1);
        if (enc3 != 64) {
          output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
          output = output + String.fromCharCode(chr3);
        }
      }
      return utf8_decode(output);
    }
    
    /*
      *  utf-8解码
      *  @parm : utftext 传入的字符串
     */
    function utf8_decode(utftext) {
      var string = '';
      let i = 0;
      let c = 0;
      let c1 = 0;
      let c2 = 0;
      while (i < utftext.length) {
        c = utftext.charCodeAt(i);
        if (c < 128) {
          string += String.fromCharCode(c);
          i++;
        } else if ((c > 191) && (c < 224)) {
          c1 = utftext.charCodeAt(i + 1);
          string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
          i += 2;
        } else {
          c1 = utftext.charCodeAt(i + 1);
          c2 = utftext.charCodeAt(i + 2);
          string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
          i += 3;
        }
      }
      return string;
    }
    
    /*
        * base64编码函数封装
        * @parm: str(传入要编成base64的内容)
        * 使用:
            1、引入util.js(路径更改) :const util  = require('../../utils/util.js');
            2、util.baseEncode('base64 编码');
    */
    function baseEncode(str) {
      return base64_encode(utf16to8(str));
    }
    
    
    
    function dealShareText(text){
      // 先看一下 text 的长度,如果大于 30 返回  三段  ,
      console.log(text)
      let length = text.length
      let str1 = ''
      let str2 = ''
      let str3 = ''
      let  url = ''
      console.log(length)
      let baseUrl = 'http://img.yi-chuangxin.com/Fn64f5WddnKWXTy5tu1kCdCmcAan?imageView2/1/w/500/h/400/q/100'
      if(length>30){
        let str = text.substr(0,27)+'...'
        str1  = str.substr(0,10)
        str2 = str.substr(10,10)
        str3 = str.substr(20,10)
        str1 = baseEncode(str1).replace(/\+/g,'-').replace(/\//g,'_')
        str2 = baseEncode(str2).replace(/\+/g,'-').replace(/\//g,'_')
        str3 = baseEncode(str3).replace(/\+/g,'-').replace(/\//g,'_')
         url  = `${baseUrl}|watermark/2/text/${str1}/font/6buR5L2T/fontsize/600/fill/IzE4M0Y4Qg==/dissolve/100/gravity/North/dx/10/dy/100|watermark/2/text/${str2}/font/6buR5L2T/fontsize/600/fill/IzE4M0Y4Qg==/dissolve/100/gravity/North/dx/10/dy/160|watermark/2/text/${str3}/font/6buR5L2T/fontsize/600/fill/IzE4M0Y4Qg==/dissolve/100/gravity/North/dx/10/dy/220`
      }else if(length>20&&length<=30){
        str1  = text.substr(0,10)
        str2 = text.substr(10,10)
        str3 = text.substr(20,10)
         url  = `${baseUrl}|watermark/2/text/${baseEncode(str1).replace(/\+/g,'-').replace(/\//g,'_')}/font/6buR5L2T/fontsize/600/fill/IzE4M0Y4Qg==/dissolve/100/gravity/North/dx/10/dy/100|watermark/2/text/${baseEncode(str2).replace(/\+/g,'-').replace(/\//g,'_')}/font/6buR5L2T/fontsize/600/fill/IzE4M0Y4Qg==/dissolve/100/gravity/North/dx/10/dy/160|watermark/2/text/${baseEncode(str3).replace(/\+/g,'-').replace(/\//g,'_')}/font/6buR5L2T/fontsize/600/fill/IzE4M0Y4Qg==/dissolve/100/gravity/North/dx/10/dy/220`
      }else if(length>10&&length<=20){
        str1  = text.substr(0,10)
        str2 = text.substr(10,10)
        url  = `${baseUrl}|watermark/2/text/${baseEncode(str1).replace(/\+/g,'-').replace(/\//g,'_')}/font/6buR5L2T/fontsize/600/fill/IzE4M0Y4Qg==/dissolve/100/gravity/North/dx/10/dy/100|watermark/2/text/${baseEncode(str2).replace(/\+/g,'-').replace(/\//g,'_')}/font/6buR5L2T/fontsize/600/fill/IzE4M0Y4Qg==/dissolve/100/gravity/North/dx/10/dy/160`
      }else if(length<=10){
        str1  = text.substr(0,10)
        url  = `${baseUrl}|watermark/2/text/${baseEncode(str1).replace(/\+/g,'-').replace(/\//g,'_')}/font/6buR5L2T/fontsize/600/fill/IzE4M0Y4Qg==/dissolve/100/gravity/North/dx/10/dy/100`
      }
    
      return url 
    
    }
    
    function dealShareImg(imgUrl){
      let imgurl = `${imgUrl}?imageView2/1/w/460/h/364/q/75`
    
      let baseUrl = 'http://img.yi-chuangxin.com/Fihxh0GqlfTrWC45qfGP9Z_lT5U0?imageView2/1/w/500/h/400/q/75'
      let url = `${baseUrl}|watermark/1/image/${baseEncode(imgurl).replace(/\+/g,'-').replace(/\//g,'_')}/dissolve/100/gravity/Center/dx/10/dy/10`
    
      return url
    }
    
    
    
    /*
        * base64解码函数封装
        * @parm: str(传入要解为正常字体)
        * 使用:
            1、引入util.js(路径更改) :const util  = require('../../utils/util.js');
            2、util.baseDecode(util.baseEncode('base64 编码'))
    */
    function baseDecode(str) {
      return base64_decode(str);
    }// 抛出函数使用
    module.exports = {
      baseEncode: baseEncode,
      baseDecode: baseDecode,
      dealShareText:dealShareText,
      dealShareImg:dealShareImg
    }
    
    

    总结:
    用同样的方法 ,可以生产任何海报内容,无需canvas 生成,生成速度快,不占用服务器资源

    相关文章

      网友评论

          本文标题:微信小程序+七牛云水印功能 实现自定义图片分享

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