评论

如何实现快速生成朋友圈海报分享图

如何快速实现朋友圈海报分享图~

由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 Canvas 功能生成一张带有小程序码的图片,然后引导用户下载图片到本地后再分享到朋友圈。相信大家在绘制分享图中应该踩到 Canvas 的各种(坑)彩dan了吧~

这里首先推荐一个开源的组件:painter(通过该组件目前我们已经成功在支付宝小程序上也应用上了分享图功能)

咱们不多说,直接上手就是干。

首先我们新增一个自定义组件,在该组件的json中引入painter

{
  "component": true,
  "usingComponents": {
    "painter": "/painter/painter"
  }
}

然后组件的WXML (代码片段在最后)

// 将该组件定位在屏幕之外,用户查看不到。
<painter style="position: absolute; top: -9999rpx;" palette="{{imgDraw}}" bind:imgOK="onImgOK" />

重点来了 JS (代码片段在最后)

Component({
  properties: {
    // 是否开始绘图
    isCanDraw: {
      type: Boolean,
      value: false,
      observer(newVal) {
        newVal && this.handleStartDrawImg()
      }
    },
    // 用户头像昵称信息
    userInfo: {
      type: Object,
      value: {
        avatarUrl: '',
        nickName: ''
      }
    }
  },
  data: {
    imgDraw: {}, // 绘制图片的大对象
    sharePath: '' // 生成的分享图
  },
  methods: {
    handleStartDrawImg() {
      wx.showLoading({
        title: '生成中'
      })
      this.setData({
        imgDraw: {
          width: '750rpx',
          height: '1334rpx',
          background: 'https://qiniu-image.qtshe.com/20190506share-bg.png',
          views: [
            {
              type: 'image',
              url: 'https://qiniu-image.qtshe.com/1560248372315_467.jpg',
              css: {
                top: '32rpx',
                left: '30rpx',
                right: '32rpx',
                width: '688rpx',
                height: '420rpx',
                borderRadius: '16rpx'
              },
            },
            {
              type: 'image',
              url: this.data.userInfo.avatarUrl || 'https://qiniu-image.qtshe.com/default-avatar20170707.png',
              css: {
                top: '404rpx',
                left: '328rpx',
                width: '96rpx',
                height: '96rpx',
                borderWidth: '6rpx',
                borderColor: '#FFF',
                borderRadius: '96rpx'
              }
            },
            {
              type: 'text',
              text: this.data.userInfo.nickName || '青团子',
              css: {
                top: '532rpx',
                fontSize: '28rpx',
                left: '375rpx',
                align: 'center',
                color: '#3c3c3c'
              }
            },
            {
              type: 'text',
              text: `邀请您参与助力活动`,
              css: {
                top: '576rpx',
                left: '375rpx',
                align: 'center',
                fontSize: '28rpx',
                color: '#3c3c3c'
              }
            },
            {
              type: 'text',
              text: `宇宙最萌蓝牙耳机测评员`,
              css: {
                top: '644rpx',
                left: '375rpx',
                maxLines: 1,
                align: 'center',
                fontWeight: 'bold',
                fontSize: '44rpx',
                color: '#3c3c3c'
              }
            },
            {
              type: 'image',
              url: 'https://qiniu-image.qtshe.com/20190605index.jpg',
              css: {
                top: '834rpx',
                left: '470rpx',
                width: '200rpx',
                height: '200rpx'
              }
            }
          ]
        }
      })
    },
    onImgErr(e) {
      wx.hideLoading()
      wx.showToast({
        title: '生成分享图失败,请刷新页面重试'
      })
      //通知外部绘制完成,重置isCanDraw为false
      this.triggerEvent('initData') 
    },
    onImgOK(e) {
      wx.hideLoading()
      // 展示分享图
      wx.showShareImageMenu({
        path:  e.detail.path,
        fail: err => {
          console.log(err)
        }
      })
      //通知外部绘制完成,重置isCanDraw为false
      this.triggerEvent('initData') 
    }
  }
})

那么我们该如何引用呢?

首先json里引用我们封装好的组件share-box
{
  "usingComponents": {
    "share-box": "/components/shareBox/index"
  }
}
以下示例为获取用户头像昵称后再生成图。
<button class="intro" bindtap="getUserInfo">点我生成分享图</button>
<share-box isCanDraw="{{isCanDraw}}" userInfo="{{userInfo}}"  bind:initData="handleClose" />
调用的地方:
const app = getApp()

Page({
  data: {
    isCanDraw: false
  },
  // 组件内部关掉或者绘制完成需重置状态
  handleClose() {
    this.setData({
      isCanDraw: !this.data.isCanDraw
    })
  },
  getUserInfo(e) {
    wx.getUserProfile({
      desc: "获取您的头像昵称信息",
      success: res => {
        const { userInfo = {} } = res
        this.setData({
          userInfo,
          isCanDraw: true // 开始绘制海报图
        })
      },
      fail: err => {
        console.log(err)
      }
    })
  }
})

最后绘制分享图的自定义组件就完成啦~效果图如下:

tips:

  • 文字居中实现可以看下代码片段
  • 文字换行实现(maxLines)只需要设置宽度,maxLines如果设置为1,那么超出一行将会展示为省略号

代码片段:https://developers.weixin.qq.com/s/J38pKsmK7Qw5

附上painter可视化编辑代码工具:点我直达,因为涉及网络图片,代码片段设置不了downloadFile合法域名,建议真机开启调试模式,开发者工具 详情里开启不校验合法域名进行代码片段的运行查看。
最后看下面大家评论问的较多的问题:downLoadFile合法域名在小程序后台 开发>开发设置里配置,域名为你图片的域名前缀 比如我文章里的图https://qiniu-image.qtshe.com/20190605index.jpg。配置域名时填写https://qiniu-image.qtshe.com即可。如果你图片cdn地址为https://aaa.com/xxx.png, 那你就配置https://aaa.com即可。
最后一次编辑于  2022-01-20  
点赞 124
收藏
评论

121 个评论

  • 平行画
    平行画
    2020-07-16

    有个问题想问下,如果我要把头像和文字放一排,并且居中要怎么去写代码,文档没看太懂

    2020-07-16
    赞同
    回复 6
    • 平行画
      平行画
      2020-07-16
      文字的长度是动态的
      2020-07-16
      回复
    • TNT
      TNT
      2020-07-16
      文字长度 动态计算。根据文字数量去计算。然后设置width
      2020-07-16
      2
      回复
    • 平行画
      平行画
      2020-07-16回复TNT
      没太懂,根据文字数量计算长度可能不太准,每个字符的宽度应该不一样,字母,数字,汉字。然后是设置谁的width。
      2020-07-16
      回复
    • 平行画
      平行画
      2020-07-16回复平行画
      现在就是nickname和头像并排居中显示,啥字符都可能有。
      2020-07-16
      回复
    • TNT
      TNT
      2020-07-16回复平行画
      把这段文案 写到页面上,通过绝对定位 移到用户看不到的地方:比如left: -9999px。用view包裹。用serlectQuery拿到宽度。设置到绘图的样式里
      2020-07-16
      3
      回复
    查看更多(1)
  • zy
    zy
    发表于移动端
    2020-07-13
    请问如何能自动绘制多张图片?绘制单张我已经实现了,但是绘制多张没有思路去实现。
    2020-07-13
    赞同
    回复 3
    • TNT
      TNT
      2020-07-14
      多个painter
      2020-07-14
      1
      回复
    • zy
      zy
      2020-07-14回复TNT
      谢谢楼主  昨晚睡觉的时候我就相通了 神奇吧?加班思路就是堵住了。
      2020-07-14
      回复
    • TNT
      TNT
      2020-07-14回复zy
      666
      2020-07-14
      回复
  • 一骑白马开吴疆🐎
    一骑白马开吴疆🐎
    2020-07-06

    封装基本操作的实现https://github.com/MakerGYT/share/

    2020-07-06
    赞同
    回复
  • 修心养性
    修心养性
    2020-06-10

    share BOx中的js。关于text: 支持换行吗?如果可以的话 是什么语法呢?

    2020-06-10
    赞同
    回复 1
    • TNT
      TNT
      2020-06-10
      设置宽度。超过了就会换行。
      2020-06-10
      回复
  • jzning
    jzning
    2020-06-02

    请问有没有 支持 动态内容,动态高度的情况?

    2020-06-02
    赞同
    回复 9
    • jzning
      jzning
      2020-06-02回复TNT
      意思 是动态算 canvas的高度,
      2020-06-02
      回复
    • jzning
      jzning
      2020-06-02回复TNT
      我意思,生成的长图,宽度不变,高度可变,因为文案是用户输入的,可能几个字,可能几百个字。
      2020-06-02
      回复
    • TNT
      TNT
      2020-06-02回复jzning
      那个不行,你用wxmltocanvas吧
      2020-06-02
      1
      回复
    • TNT
      TNT
      2020-06-02回复jzning
      我的建议在绘制前 拿到用户输入的文案内容高度,做计算。
      2020-06-02
      回复
    • jzning
      jzning
      2020-06-02回复TNT
      wxmltocanvas 我 试了也不行。文本必须指定高。
      只能我自己写了。
      2020-06-02
      回复
    查看更多(4)
  • Wang
    Wang
    2020-05-22

    如果想把整个页面转为图片,通过canvas实现,有没有什么方法,页面长度比较长的那种

    2020-05-22
    赞同
    回复 6
    • TNT
      TNT
      2020-05-22
      用官方的 wxml-to-canvas https://developers.weixin.qq.com/miniprogram/dev/extended/component-plus/wxml-to-canvas.html
      2020-05-22
      1
      回复
    • Wang
      Wang
      2020-05-25回复TNT
      我看了这个组件,需要自己拼接wxml字符串和所有的css样式,页面长度很长,拼接wxml字符串的工作量比较大,同时,好像不支持自定义组件,页面中使用了大量的自定义组件,尴尬。
      2020-05-25
      回复
    • TNT
      TNT
      2020-05-25回复Wang
      那你只能手动画,微信没提供截屏的方法
      2020-05-25
      回复
    • zy
      zy
      2020-07-15
      兄弟 我告诉你,你这个功能就是我做的功能,巨长的页面需要用户下载为图片,而且还不止一张,把我画惨了,工作量太大了,但是我已经画完,不知道你遇到一个新问题没?——图片太长内容太多,导致绘制的时候页面某些图片没有呗绘制出来,而且绘制时间比较久。我可烦死了。
      2020-07-15
      回复
    • Wang
      Wang
      2020-07-15回复zy
      我没有使用这个组件去做,工作量太大了,同时不支持自定义组件,我选了跳转到h5然后去生成图片,web端的生成图片工具很多。
      2020-07-15
      回复
    查看更多(1)
  • 老程
    老程
    2020-05-16

    希望能帮助到你: https://developers.weixin.qq.com/community/develop/article/doc/0008ea33e18b6848a95aa6f6c5b013?from=tool&idescene=7

    2020-05-16
    赞同
    回复
  • Y
    Y
    2020-05-05

    想问下大佬,为什么生成图片出来会特别模糊,宽高比例放小字和图片也是模糊的。

    2020-05-05
    赞同
    回复 3
    • Y
      Y
      2020-05-05
      已经解决了,有参数可以配置,赞!
      2020-05-05
      回复
    • TNT
      TNT
      2020-05-06回复Y
      👌
      2020-05-06
      回复
    • 相识于江湖
      相识于江湖
      2020-08-07回复TNT
      请问怎么解决模糊的问题,这个参数有效吗
      2020-08-07
      回复
  • 小丫头
    小丫头
    2020-04-28

    感谢大佬分享。

    我想请教一个问题,750的画布,生成后的图片大小是多少呢?使用mode='widthFix',图片宽是320px。如果我将image的width设置为100%,图片就变模糊了。那如果要生成全屏的图片,画布该多大呢?

    2020-04-28
    赞同
    回复 4
    • TNT
      TNT
      2020-04-28
      你将宽度统一用750画。画成功后将宽度定为320px
      2020-04-28
      1
      回复
    • 小丫头
      小丫头
      2020-04-28回复TNT
      画布统一的750,画成功后,宽度为750的话,图片就变模糊了
      2020-04-28
      回复
    • TNT
      TNT
      2020-04-28回复小丫头
      画成功后将导出的图设置为320。你可以将画布按比例拉大比如宽1500。然后绘制后设置成320
      2020-04-28
      2
      回复
    • 相识于江湖
      相识于江湖
      2020-08-07回复TNT
      怎么吧图片存成320的尺寸?
      2020-08-07
      回复
  • leeyoung
    leeyoung
    2020-04-21

    分享到微信,PC端打开图片不正常了

    2020-04-21
    赞同
    回复 4
    • TNT
      TNT
      2020-04-21
      稍等我试下。
      2020-04-21
      回复
    • TNT
      TNT
      2020-04-26
      你用的px吗
      2020-04-26
      回复
    • leeyoung
      leeyoung
      2020-04-26回复TNT
      rpx
      2020-04-26
      回复
    • TNT
      TNT
      2020-04-26回复leeyoung
      用你的小程序问题复现了。。
      2020-04-26
      回复

正在加载...

登录 后发表内容