评论

小程序分享图生成指南:告别 Canvas 踩坑,轻松实现朋友圈分享

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

由于微信小程序无法直接分享到朋友圈,业界普遍采用 Canvas 生成带小程序码的图片,引导用户保存后分享,相信不少开发者在绘制分享图时都曾遇到过各种 Canvas 的“彩蛋”(坑)。
今天推荐一个开源组件:Painter,它能够帮助我们轻松实现分享图绘制,并且已在支付宝小程序中验证可用。

快速开始

第一步:创建自定义组件

在组件的 JSON 文件中引入 Painter:

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

第二步:编写组件 WXML

将 Painter 组件定位在屏幕外,避免影响用户界面:

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

第三步:实现组件逻辑

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') 
    }
  }
})

如何使用

1. 引入组件

在页面的 JSON 文件中引入封装好的分享组件:

{
  "usingComponents": {
    "share-box": "/components/shareBox/index"
  }
}

2. 页面布局

<!-- 触发按钮 -->
<button class="intro" bindtap="getUserInfo">点我生成分享图</button>

<!-- 分享组件 -->
<share-box 
  isCanDraw="{{isCanDraw}}" 
  userInfo="{{userInfo}}" 
  bind:initData="handleClose" 
/>

3. 页面逻辑

Page({
  data: {
    isCanDraw: false,
    userInfo: {}
  },

  // 重置绘制状态
  handleClose() {
    this.setData({
      isCanDraw: false
    })
  },

  // 获取用户信息并开始绘制
  getUserInfo() {
    wx.getUserProfile({
      desc: "获取您的头像昵称信息",
      success: (res) => {
        const { userInfo = {} } = res
        this.setData({
          userInfo,
          isCanDraw: true // 触发绘制
        })
      },
      fail: (err) => {
        console.log('获取用户信息失败:', err)
      }
    })
  }
})

效果展示

完成上述步骤后,即可生成如下的分享图片:

实用技巧

  • 文字居中:通过设置 align: 'center' 和合适的left值实现
  • 文字换行:设置widthmaxLines 属性,当 maxLines: 1 时,超出一行会显示为省略号

资源链接

常见问题

Q:为什么图片无法加载?

A:需要在小程序后台配置 downloadFile 合法域名:

Q:真机调试注意事项?

A:开发者工具中可在「详情」→「本地设置」中开启「不校验合法域名」,真机调试时需开启调试模式。

通过以上步骤,你就可以轻松实现小程序分享图生成功能了。如有任何问题,欢迎在评论区留言讨论!

最后一次编辑于  11-13  
点赞 127
收藏
评论

125 个评论

  • 刘亚磊
    刘亚磊
    2020-07-21

    我用这个方法做了个海报效果不错,已经上线了!

    

    2020-07-21
    赞同 4
    回复 18
    查看更多(13)
  • 精彩极了
    精彩极了
    2019-11-08

    不好意思,刚发现问题就删掉了评论发表

    2019-11-08
    赞同 3
    回复 11
    • 精彩极了
      精彩极了
      2019-11-08回复胃里养了只霸王龙
      本地图片可以加载绘制进来,就是有一点错误提示,不太友好,哈哈
      2019-11-08
      1
      回复
    • 精彩极了
      精彩极了
      2019-11-11回复胃里养了只霸王龙
      用painter连续加载了三次,生成了三张图片,生成时会闪屏,然后左右滑动时也会闪屏,求解啊大佬
      2019-11-11
      回复
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      2019-11-11
      canvas绘制图,性能本来就差点。你这个连续绘制3次。建议你写三个painter的内容。写三个canvas
      2019-11-11
      3
      回复
    • 精彩极了
      精彩极了
      2019-11-12回复胃里养了只霸王龙
      这样生成图片之后,把临时路径放到swiper里面去,就一直闪一直闪,部分手机是正常的,小米的就狂闪,不知道为什么
      2019-11-12
      2
      回复
    • 精彩极了
      精彩极了
      2019-11-12回复胃里养了只霸王龙
      看了一下生成的图片,都控制在1.5M以内
      2019-11-12
      回复
    查看更多(6)
  • 。。
    。。
    2023-08-17

    怎么把中间的收藏换成分享到朋友圈呢?

    2023-08-17
    赞同 1
    回复 2
  • 🇪 🇱 🇸 🇪
    🇪 🇱 🇸 🇪
    发表于移动端
    2022-10-23
    https://developers.weixin.qq.com/community/develop/article/doc/00066c5b5189807976befa6075bc13 参考
    2022-10-23
    赞同 1
    回复 2
    • 🍦🍦🍦
      🍦🍦🍦
      2022-10-24
      请问海报的尺寸大概是多少呢
      2022-10-24
      回复
    • 🇪 🇱 🇸 🇪
      🇪 🇱 🇸 🇪
      2022-10-24回复🍦🍦🍦
      根据屏幕宽度动态判断
      2022-10-24
      回复
  • core
    core
    2020-07-09

    想问下楼主,如果我不知道页面结构的情况下,能实现截取整个页面的功能吗?

    2020-07-09
    赞同 1
    回复 2
  • Mercury.
    Mercury.
    2020-05-11

    真机为什么不显示图片啊

    2020-05-11
    赞同 1
    回复 11
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      2020-05-11
      图片没配置合法域名。你试下开启调试是否可以显示了
      2020-05-11
      1
      回复
    • M_yyyyyy_
      M_yyyyyy_
      2020-06-24回复胃里养了只霸王龙
      您好,开启调试之后,可以显示了,但是关闭调试之后又不显示了;请问这个如何解决呢?
      2020-06-24
      回复
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      2020-06-24回复M_yyyyyy_
      小程序后台配置downloadFile合法域名。
      2020-06-24
      2
      回复
    • M_yyyyyy_
      M_yyyyyy_
      2020-06-24回复胃里养了只霸王龙
      您好,现在服务端下发给我的url是http,但是小程序后台配置的合法域名是https,开启调试之后,可以显示图片,但是关闭调试之后又不显示图片了,是和配置的https有关系么
      2020-06-24
      回复
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      2020-06-24回复M_yyyyyy_
      让你们后端返回的图片地址支持下https,downLoadFile域名都得是https的。http的不行
      2020-06-24
      2
      回复
    查看更多(6)
  • ccc
    ccc
    11-14

    在电脑端使用小程序生成海报会报这个错,,手机端正常

    11-14
    赞同
    回复 6
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      11-14
      当前网络状态不佳 是你返回的吗?还有就是判断下PC端,你自己写弹窗,调用wx.saveImageToPhotosAlbum 保存到电脑本地。
      11-14
      回复
    • ccc
      ccc
      11-14回复胃里养了只霸王龙
      不是我返回的,我猜可能是wx.showShareImageMenu方法返回的
      11-14
      回复
    • ccc
      ccc
      11-14
      保存图片功能是可以用的
      11-14
      回复
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      11-14回复胃里养了只霸王龙
      那你本地开发使用 PC预览下看看,因为这个api在pc上 发送给朋友等没法用。你可以换成wx.previewImage方法试试。
      11-14
      回复
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      11-14回复ccc
      判断pc 用previewImage,移动端还是用showShareImageMenu
      11-14
      回复
    查看更多(1)
  • ccc
    ccc
    11-13

    大佬那个图片保存到本地在真机调式模式下是可以的,但是上线以后就不行了

    11-13
    赞同
    回复 10
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      11-13
      隐私协议 没配置吧?你小程序后台设置下隐私协议
      11-13
      回复
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      11-13
      这个东西申请下
      11-13
      回复
    • ccc
      ccc
      11-13回复胃里养了只霸王龙
      好的,配置好了等他审核了,还有一个问题,就是上图有发送给朋友,分享朋友圈等5个功能,怎么去掉发表到公众号,这个功能不需要
      11-13
      回复
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      11-13回复ccc
      去不掉,这个是官方API自带的,不支持去掉某一个。
      11-13
      回复
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      11-13回复ccc
      官方的api是wx.showShareImageMenu()
      11-13
      回复
    查看更多(5)
  • ccc
    ccc
    11-12

    内容下方的长按二维码和小程序的图片在哪修改

    11-12
    赞同
    回复 4
  • 纪相成
    纪相成
    2024-09-25

    有两个问题请教:

    1、英文换行不是按照单词,是按照字母换行的,怎么设置单词换行。

    2、使用相对定位.bottom的时候,被参照的内容增加空格或者回车,这个.bottom的间距无故增大,有些奇怪。

    第二个问题的代码:

    2024-09-25
    赞同
    回复 5
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      2024-09-25
      提交issues吧。加下团队wx:chrispengtao 让他拉你进painter群反馈下。
      2024-09-25
      回复
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      2024-09-25
      提交issues吧。加下团队微x:chrispengtao 让他拉你进painter群反馈下。
      2024-09-25
      回复
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      2024-09-25
      提交issues吧。加下团队x:chrispengtao 让他拉你进painter群反馈下。
      2024-09-25
      回复
    • 胃里养了只霸王龙
      胃里养了只霸王龙
      2024-09-25
      提交issues吧。加下团队:chrispengtao 让他拉你进painter群反馈下。
      2024-09-25
      回复
    • 纪相成
      纪相成
      2024-09-25回复胃里养了只霸王龙
      好的~
      2024-09-25
      回复

正在加载...

登录 后发表内容