作者:小白

https://segmentfault.com/a/1190000019083548

项目需求写完有一段时间了,但是还是想回过来总结一下,一是对项目的回顾优化等,二是对坑的地方做个记录,避免以后遇到类似的问题。

需求

利用微信强大的社交能力通过小程序达到裂变的目的,拉取新用户。
生成的海报如下

需求分析

1、利用小程序官方提供的api可以直接分享转发到微信群打开小程序
2、利用小程序生成海报保存图片到相册分享到朋友圈,用户长按识别二维码关注公众号或者打开小程序来达到裂变的目的(关注公众号 逆锋起笔,回复 pdf,下载你需要的各种学习资料。)

实现方案

一、分析如何实现

相信大家应该都会有类似的迷惑,就是如何按照产品设计的那样绘制成海报,其实当时我也是不知道如何下手,认真想了下得通过canvas绘制成图片,这样用户保存这个图片到相册,就可以分享到朋友圈了。但是要绘制的图片上面不仅有文字还有数字、图片、二维码等且都是活的,这个要怎么动态生成呢。认真想了下,需要一点一点的将文字和数字,背景图绘制到画布上去,这样通过api最终合成一个图片导出到手机相册中。

二、需要解决的问题

1、二维码的动态获取和绘制(包括如何生成小程序二维码、公众号二维码、打开网页二维码)
2、背景图如何绘制,获取图片信息
3、将绘制完成的图片保存到本地相册
4、处理用户是否取消授权保存到相册

三、实现步骤

这里我具体写下围绕上面所提出的问题,描述大概实现的过程

①首先创建canvas画布,我把画布定位设成负的,是为了不让它显示在页面上,是因为我尝试把canvas通过判断条件动态的显示和隐藏,在绘制的时候会出现问题,所以采用了这种方法,这里还有一定要设置画布的大小。

<canvas canvas-id="myCanvas" style="width: 690px;height:1085px;position: fixed;top: -10000px;"></canvas>

②创建好画布之后,先绘制背景图,因为背景图我是放在本地,所以获取 <canvas> 组件 canvas-id 属性,通过createCanvasContext创建canvas的绘图上下文 CanvasContext 对象。使用drawImage绘制图像到画布,第一个参数是图片的本地地址,后面两个参数是图像相对画布左上角位置的x轴和y轴,最后两个参数是设置图像的宽高。

const ctx = wx.createCanvasContext('myCanvas')ctx.drawImage('/img/study/shareimg.png', 0, 0, 690, 1085)

③创建好背景图后,在背景图上绘制头像,文字和数字。通过getImageInfo获取头像的信息,这里需要注意下在获取的网络图片要先配置download域名才能生效,具体在小程序后台设置里配置。

获取头像地址,首先量取头像在画布中的大小,和x轴Y轴的坐标,这里的result[0]是我用promise封装返回的一个图片地址

let headImg = new Promise(function (resolve) {wx.getImageInfo({src: `${app.globalData.baseUrl2}${that.data.currentChildren.headImg}`,success: function (res) {resolve(res.path)},fail: function (err) {console.log(err)wx.showToast({title: '网络错误请重试',icon: 'loading'})}})})let avatarurl_width = 60, //绘制的头像宽度avatarurl_heigth = 60, //绘制的头像高度avatarurl_x = 28, //绘制的头像在画布上的位置avatarurl_y = 36; //绘制的头像在画布上的位置ctx.save(); // 先保存状态 已便于画完圆再用ctx.beginPath(); //开始绘制//先画个圆   前两个参数确定了圆心 (x,y) 坐标  第三个参数是圆的半径  四参数是绘图方向  默认是false,即顺时针ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);ctx.clip(); //画了圆 再剪切  原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内ctx.drawImage(result[0], avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推进去图片

这里举个例子说下如何绘制文字,比如我要绘制如下这个“字”,需要动态获取前面字数的总宽度,这样才能设置“字”的x轴坐标,这里我本来是想通过measureText来测量字体的宽度,但是在iOS端第一次获取的宽度值不对,关于这个问题,我还在微信开发者社区提了bug,所以我想用另一个方法来实现,就是先获取正常情况下一个字的宽度值,然后乘以总字数就获得了总宽度,亲试是可以的。

let allReading = 97 / 6 / app.globalData.ratio * wordNumber.toString().length + 325;
ctx.font = 'normal normal 30px sans-serif';
ctx.setFillStyle('#ffffff')
ctx.fillText('字', allReading, 150);

④绘制公众号二维码,和获取头像是一样的,也是先通过接口返回图片网络地址,然后再通过getImageInfo获取公众号二维码图片信息

⑤如何绘制小程序码,具体官网文档也给出生成无限小程序码接口,通过生成的小程序可以打开任意一个小程序页面,并且二维码永久有效,具体调用哪个小程序二维码接口有不同的应用场景,具体可以看下官方文档怎么说的,也就是说前端通过传递参数调取后端接口返回的小程序码,然后绘制在画布上(和上面写的绘制头像和公众号二维码一样的)

ctx.drawImage('小程序码的本地地址', x轴, Y轴, 宽, 高)

⑥最终绘制完把canvas画布转成图片并返回图片地址

        wx.canvasToTempFilePath({canvasId: 'myCanvas',success: function (res) {canvasToTempFilePath = res.tempFilePath // 返回的图片地址保存到一个全局变量里that.setData({showShareImg: true})wx.showToast({title: '绘制成功',})},fail: function () {wx.showToast({title: '绘制失败',})},complete: function () {wx.hideLoading()wx.hideToast()}})

⑦保存到系统相册;先判断用户是否开启用户授权相册,处理不同情况下的结果。比如用户如果按照正常逻辑授权是没问题的,但是有的用户如果点击了取消授权该如何处理,如果不处理会出现一定的问题。所以当用户点击取消授权之后,来个弹框提示,当它再次点击的时候,主动跳到设置引导用户去开启授权,从而达到保存到相册分享朋友圈的目的。

// 获取用户是否开启用户授权相册if (!openStatus) {wx.openSetting({success: (result) => {if (result) {if (result.authSetting["scope.writePhotosAlbum"] === true) {openStatus = true;wx.saveImageToPhotosAlbum({filePath: canvasToTempFilePath,success() {that.setData({showShareImg: false})wx.showToast({title: '图片保存成功,快去分享到朋友圈吧~',icon: 'none',duration: 2000})},fail() {wx.showToast({title: '保存失败',icon: 'none'})}})}}},fail: () => { },complete: () => { }});} else {wx.getSetting({success(res) {// 如果没有则获取授权if (!res.authSetting['scope.writePhotosAlbum']) {wx.authorize({scope: 'scope.writePhotosAlbum',success() {openStatus = truewx.saveImageToPhotosAlbum({filePath: canvasToTempFilePath,success() {that.setData({showShareImg: false})wx.showToast({title: '图片保存成功,快去分享到朋友圈吧~',icon: 'none',duration: 2000})},fail() {wx.showToast({title: '保存失败',icon: 'none'})}})},fail() {// 如果用户拒绝过或没有授权,则再次打开授权窗口openStatus = falseconsole.log('请设置允许访问相册')wx.showToast({title: '请设置允许访问相册',icon: 'none'})}})} else {// 有则直接保存openStatus = truewx.saveImageToPhotosAlbum({filePath: canvasToTempFilePath,success() {that.setData({showShareImg: false})wx.showToast({title: '图片保存成功,快去分享到朋友圈吧~',icon: 'none',duration: 2000})},fail() {wx.showToast({title: '保存失败',icon: 'none'})}})}},fail(err) {console.log(err)}})}

总结

至此所有的步骤都已实现,在绘制的时候会遇到一些异步请求后台返回的数据,所以我用promise和async和await进行了封装,确保导出的图片信息是完整的。在绘制的过程确实遇到一些坑的地方。比如初开始导出的图片比例大小不对,还有用measureText测量文字宽度不对,多次绘制(可能受网络原因)有时导出的图片上的文字颜色会有误差等。如果你也遇到一些比较坑的地方可以一起探讨下做个记录。

1. JavaScript 重温系列(22篇全)

2. ECMAScript 重温系列(10篇全)

3. JavaScript设计模式 重温系列(9篇全)

4. 正则 / 框架 / 算法等 重温系列(16篇全)

5. Webpack4 入门(上)|| Webpack4 入门(下)

6. MobX 入门(上) ||  MobX 入门(下)

7. 80+篇原创系列汇总

回复“加群”与大佬们一起交流学习~

点击“阅读原文”查看 80+ 篇原创文章

【小程序】728- 小程序如何生成海报分享朋友圈相关推荐

  1. 【微信小程序】用painter插件生成海报分享朋友圈简单教程

    第一步:去Git下载插件 1.这是核心插件 需要下载全部内容 https://github.com/Kujiale-Mobile/PainterCore 2.官方文档 https://github.c ...

  2. 微信小程序-运用painter插件生成海报分享朋友圈--比canvas好用

    微信小程序-运用painter插件生成海报–比canvas好用 先放插件地址:https://github.com/Kujiale-Mobile/Painter 还有个可视化把海报生成代码的地址:ht ...

  3. 小程序如何生成海报分享朋友圈,android移动开发技术与应用

    openStatus = false console.log('请设置允许访问相册') wx.showToast({ title: '请设置允许访问相册', icon: 'none' }) } }) ...

  4. 微信小程序Canvas绘制图案(生成海报、朋友圈海报)

    现在小程序生成海报是很常见的,例如生成打卡海报.生成文案.生成宣传图.生成推广图等,都是少不了一个技术,就是图片绘制,有些是通过前端Canvas绘制,有些是通过后端绘制,当然前端Canvas绘制是比较 ...

  5. 微信小程序:一个json帮你完成分享朋友圈图片

    写在前面 最近在做小程序,发现制作分享到朋友圈图片是每个项目必须的.遇到坑比较多,写起来也比较繁琐,也没有找到类似组件,所以就自己动手写了一个. 演示 左侧是 canvasdrawer 绘制的,右侧是 ...

  6. uniapp 微信小程序分享好友和分享朋友圈

    1. 需要在mounted中调用uni.showShareMenu使小程序的原生菜单中显示分享按钮 onMounted(() => {uni.showShareMenu({withShareTi ...

  7. 微信小程序分享链接及分享朋友圈,及mpvue无法指定分享名的bug修复方法

    分享链接 参数携带: <button open-type="share" hover-class="none">分享</button>o ...

  8. 微信小程序webview页面使用painter生成海报

    微信小程序webview页面使用painter生成海报 因为要在webview下生成海报,需要使用cover-view,根据接口返回数据动态更新海报内容,微信小程序生成海报组件有wxa-plugin- ...

  9. 小程序画布Canvas生成海报,分享朋友圈

    一 使用场景: 小程序内,想要分享海报到朋友圈,附带小程序码,达到转发引流的目的. /*** 用户点击右上角分享*/onShareAppMessage: function() {},shareBook ...

最新文章

  1. JavaScript与Java函数的比较
  2. 计算体系架构研究综述与思考
  3. Android应用资源---布局资源类型(Layout)
  4. python翻页_python实现电子书翻页小程序
  5. mysql 体重 类型 身高_体重较轻,身高较高的身材怎样挑选单板?
  6. MySQL分页查询方法及优化
  7. C++中回调函数(CALLBACK)初探
  8. android导航工厂设置密码,导航工厂设置密码大全,所有导航工厂密码多少
  9. Linux小游戏——单机掷骰子
  10. 如何永久关闭QQ广告弹窗
  11. 史上最详细的WinHex数据恢复大师(六大章节)视频教程
  12. 微信小程序开发工具报错对应的服务器证书无效
  13. vim 常用功能大全
  14. Linux粘滞位(粘着位)
  15. 提高文章阅读量的最新技巧
  16. android 调出键盘表情_android高仿微信表情输入与键盘输入代码(详细实现分析)
  17. java二维数奇数组金字塔_金字塔内神秘的数字~世界末日真的存在?
  18. 《剩女郎》的艺术魅力
  19. OpenCV实战(16)——角点检测详解
  20. 高中新课标教材:四省营销 端倪初露

热门文章

  1. 小程序跳转到京东小程序 / 其他小程序
  2. 数学建模案例MATLAB实例
  3. 浪潮服务器U盘安装系统无法识别到电脑硬盘问题的解决
  4. halcon图像缩放
  5. 如何实现简单计算器(附代码)
  6. 计算机课作文200字,玩电脑日记200字
  7. G - Godsend CodeForces - 841B
  8. echarts结合poi-word导出的简单处理
  9. 档案装订需要使用计算机吗,会计档案的装订包括什么
  10. 退休的同事去西藏了,我也很想去,是不是对身体素质要求比较高?