微信小程序之生成朋友圈分享图,了解一下?

分享图.png

这里是 Geek 小程序的源码,点击查看 github 源码

前言

  • 在开发小程序的过程中,你是否有将页面生成分享图并引导用户转发至朋友圈的需求?有,那就进来看看,应该是你想要的结果。

  • 在分享上,就目前来说,小程序是不能直接分享到朋友圈的,微信官方只开放了分享到好友和群聊的 API。对于分享到朋友圈,现在大多数小程序所采用的方式,就是根据不同的需求生成一张带小程序码的图片引导用户分享至朋友圈。

  • 当然分享图也可以在后台生成,但是你懂得,基本没有那个后台大哥愿意为你去用代码写一张图出来,所以,咱们还是自给自足,😆。

欢迎大家使用微信扫描【组件库小程序码】(或者微信直接搜索组件库演示)查看运行效果

组件库演示小程序.png

生成分享图大致流程如下~

image.png

官方文档

关于生成二维码

  • 微信官方获取二维码 API
  • 如果每一次分享的二维码不同,需要要生成 带参数的二维码 (采用接口B)
  • 生成的二维码需要下载到本地
  • 别忘了在 小程序微信公众平台后台 - 设置 - 开发设置 - 服务器域名 - downloadFile 合法域名 中添加域名

1. 使用 canvas 进行绘制

我们知道小程序是支持将 canvas 直接转换为图片的,我们可以充分利用这个先决条件

1.1 拿到设计的效果图,我们可以先按标注计算出每个元素的宽高以及在画布中的位置,建议使用 百分比,这样可以对所有的屏幕大小进行适配

示例代码如下:

const temp = 0.01;
//图片长宽比
const scale = 1.78;
//背景图高度
const bgScale = 0.5;
//头像和宽的比
const avatarWidthScale = 0.368;
const avatarHeightScale = 0.117;
//头像白色圆形背景
const avatarBgWidthScale = 0.38;
const avatarStrokeWidth = 4;
//昵称高度比
const nicknameHeightScale = 0.34 + 5 * temp;
//第一行文字高度
const topTextScale = 0.515 + 3 * temp;
//分享内容
const contentScale = 0.585 + 3 * temp;
const contentScale2 = 0.620 + 3 * temp;
//二维码直径
const qrCodeWidthScale = 0.341;
//二维码高度
const qrCodeHeightScale = 0.69;
//极客文字
const bpbScale = 0.91 + temp * 2;
//识别文字
const decodeScale = 0.935 + temp * 2;

1.2 涉及到图片绘制

  • 本地图片可以直接绘制
  • 如果要绘制的元素中含有网络图片,需要先将图片下载到本地,不然在真机上无法显示(亲测在模拟器上可以绘制,但在 iPhone6s 真机上无法显示)
  • 贴上头像下载代码:
/**
   * 下载头像
   */
  downloadAvatar: function () {
    var that = this;
    wx.downloadFile({
      url: that.data.avatar,
      success: function (res) {
        that.setData({
          avatarPath: res.tempFilePath
        })
        that.drawImage();
      },
      fail: function () {
        that.showErrorModel();
      }
    })
  },

1.3 对各个元素进行绘制

  • 对于文字过长省略...,目前没有好的办法,暂时采用的是设置最大文字长度,超出截断,并手动添加....
  • 对于生成圆形头像,可参考例子实现
drawImage: function () {
    var that = this;
    const ctx = wx.createCanvasContext('myCanvas', this);
    var bgPath = '../../image/share-bg.png';
    //设置 canvas 背景,不然生成的图片背景会有黑色底
    ctx.setFillStyle(WHITE);
    ctx.fillRect(0, 0, windowWidth, windowHeight);

    //绘制背景图片
    ctx.drawImage(bgPath, 0, 0, windowWidth, windowHeight * bgScale);

    //头像背景圆
    ctx.arc(windowWidth / 2, avatarWidthScale / 2 * windowWidth + avatarHeightScale * windowHeight, (avatarWidthScale / 2) * windowWidth + avatarStrokeWidth, 0, 2 * Math.PI);
    ctx.setFillStyle(WHITE);
    ctx.fill();

    //先绘制圆,裁剪成圆形图片
    ctx.save();
    ctx.beginPath();
    //圆的原点x坐标,y坐标,半径,起始弧度,终止弧度
    ctx.arc(windowWidth / 2, avatarWidthScale / 2 * windowWidth + avatarHeightScale * windowHeight, (avatarWidthScale / 2) * windowWidth, 0, 2 * Math.PI);
    ctx.setStrokeStyle(WHITE);
    ctx.stroke();
    ctx.clip();
    //绘制头像
    //图片路径,左上角x坐标,左上角y坐标,宽,高
    var avatarWidth = avatarWidthScale * windowWidth;//头像半径
    ctx.drawImage(that.data.avatarPath, windowWidth * (0.5 - avatarWidthScale / 2), avatarHeightScale * windowHeight, avatarWidth, avatarWidth);
    ctx.restore();

    //绘制 content
    ctx.setFillStyle(GRAY_COLOR);
    ctx.setFontSize(18);
    ctx.setTextAlign('center');
    ctx.fillText(that.data.detailStr.content, windowWidth / 2, contentScale * windowHeight);
    ctx.setFillStyle(GRAY_COLOR);
    ctx.setFontSize(18);
    ctx.setTextAlign('center');
    ctx.fillText(that.data.detailStr.contentOther, windowWidth / 2, contentScale2 * windowHeight);

    //绘制二维码
    ctx.drawImage(that.data.QRPath, windowWidth * (0.5 - qrCodeWidthScale / 2), qrCodeHeightScale * windowHeight, qrCodeWidthScale * windowWidth, qrCodeWidthScale * windowWidth);
    console.log('font------------>' + wx.canIUse('canvasContext.font'));

    //绘制 按压提示文字
    ctx.setFillStyle(TINT_COLOR);
    ctx.setFontSize(14);
    ctx.setTextAlign('center');
    ctx.fillText(that.data.detailStr.clickToMini, windowWidth / 2, decodeScale * windowHeight);

    //绘制加粗文字--------------------------------------------------------------
    //绘制昵称
    that.setFontStyle(ctx, 'bold');
    ctx.setFillStyle(WHITE);
    ctx.setFontSize(20);
    ctx.setTextAlign('center');
    ctx.fillText(stringUtil.substringStr(that.data.nickname), windowWidth / 2, nicknameHeightScale * windowHeight);

    //绘制文字
    ctx.setFillStyle(THEME_COLOR);
    ctx.setFontSize(24);
    ctx.setTextAlign('center');
    ctx.fillText(that.data.detailStr.tip, windowWidth / 2, topTextScale * windowHeight);

    //绘制 Geek小程序
    ctx.setFillStyle(TINT_COLOR);
    ctx.setFontSize(16);
    ctx.setTextAlign('center');
    ctx.fillText(that.data.detailStr.bpbMini, windowWidth / 2, bpbScale * windowHeight);

    //绘制到 canvas 上
    ctx.draw(false, function () {
      console.log('callback--------------->');
      that.saveCanvasImage();
    });
  }

1.4 兼容处理

  • 一些 API 属性是在高版本才有的,比如 文字加粗(基础库 1.9.90 开始支持,低版本需做兼容处理
  • 在使用之前用 wx.canIUse 判断
/**
   * 改变字体样式
   */
  setFontStyle: function (ctx, fontWeight) {
    if (wx.canIUse('canvasContext.font')) {
      ctx.font = 'normal ' + fontWeight + ' ' + '14px' + ' sans-serif';
    }
  },

1.5 不同机型适配

  • 可以拿主流的几款手机适配,包括 ios 和 Android,没有问题的话,就可以进行下一步了

2. 调整样式

  • 达到效果后修改 wxml 以及 wxss ,对 canvas 的样式调整
  • 确保 canvas 在屏幕可可显示区域外,因为 canvas 的层级是最高的,我们直接在上面显示图片是不能显示的,也不建议这么做(可以使用 cover-view
  • 这个自由发挥,可以将 canvas 的 position 设置为脱离文档流(fixed),只要 canvas 不在屏幕显示范围即可,确保离可见区域足够远
.canvas {
  width: 100%;
  position: fixed;
  top: 9999rpx;
  left: 0;
}

3. 将 canvas 保存为图片

  • 这是最后一步,给用户展示分享图片的同时,用户可以选择保存图片到手机相册

3.1 注意处理用户授权问题

  • 同时处理到用户同意和拒绝权限

  //转化为图片
  saveCanvasImage: function () {
    var that = this;
    wx.canvasToTempFilePath({
      canvasId: 'myCanvas',
      success: function (res) {
        console.log(res.tempFilePath);
        that.setData({
          targetSharePath: res.tempFilePath,
          realShow: true
        })
      },
      complete: function () {
        that.hideLoading();
      }
    }, this)
  },

  /**
   * 保存到相册
   */
  saveImageTap: function () {
    var that = this;
    that.requestAlbumScope();
  },


  /**
   * 检测相册权限
   */
  requestAlbumScope: function () {
    var that = this;
    // 获取用户信息
    wx.getSetting({
      success: res => {
        if (res.authSetting['scope.writePhotosAlbum']) {
          // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
          that.saveImageToPhotosAlbum();
        } else {
          wx.authorize({
            scope: 'scope.writePhotosAlbum',
            success(res) {
              that.saveImageToPhotosAlbum();
            },
            fail() {
              wx.showModal({
                title: '提示',
                content: '你需要授权才能保存图片到相册',
                success: function (res) {
                  if (res.confirm) {
                    wx.openSetting({
                      success: function (res) {
                        if (res.authSetting['scope.writePhotosAlbum']) {
                          that.saveImageToPhotosAlbum();
                        } else {
                          console.log('用户未同意获取用户信息权限-------->success');
                        }
                      },
                      fail: function () {
                        console.log('用户未同意获取用户信息权限-------->fail');
                      }
                    })
                  }
                }
              })
            }
          })
        }
      }
    })
  },

3.2 保存图片到相册


  saveImageToPhotosAlbum: function () {
    var that = this;
    wx.saveImageToPhotosAlbum({
      filePath: that.data.targetSharePath,
      success: function () {
        wx.showModal({
          title: '',
          content: '✌️图片保存成功,\n快去分享到朋友圈吧',
          showCancel: false
        })
        that.hideDialog();
      }
    })
  },
  • 下面我将讲解小程序自定义组件,以及对保存相册的封装,毕竟分享的地方会很多,封装成组件会大大简化我们的代码量以及工作量,这样就可以少加点班,哈哈

欢迎关注 stone 的简书!

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

推荐阅读更多精彩内容