业务场景

在微信中 小程序无法分享到朋友圈,目前大部分的解决方案都是,canvas动态绘制 生成图片后,保存到用户相册,用户进行分享照片到朋友圈,朋友圈打开图片后识别二维码进入小程序,达到分享目的

github源码链接

https://github.com/richard1015/canvas

微信IDE代码预览

https://developers.weixin.qq.com/s/DBZhf8mB7qaD

海报需求设计图分析

图1分析: 可以看到海报 要求宽750 高1218(当然了数据是动态的,高度肯定不会固定值,需要我们动态去计算)

图2分析:矩形框 宽高为固定值 320 背景颜色#fff 圆角10

图3分析:矩形框 上半部分 宽320 高125 背景颜色#f7f7f7

代码逻辑实现

1.模板逻辑 wxml添加canvas公用组件
  1. <!--pages/index/index.wxml-->
  2. <view class='index'>
  3. <!-- 公用canvas share -->
  4. <import src="../common/canvasShare.wxml" />
  5. <template data="{{shareCanvasItem}}" is="canvas-share" />
  6. <!-- content 内容预显示 begin -->
  7. <view class='content'>
  8. <view class='content_header'>
  9. <view class='left' bindtap='toChoiceBank'>
  10. <text>中国银行(测试数据)</text>
  11. </view>
  12. </view>
  13. <view class='content_item'>
  14. ...此处省略
  15. </view>
  16. </view>
  17. <!-- content end -->
  18. <import src="../common/footerShare.wxml" />
  19. <template is="footer-share" />
  20. </view>
  21. 复制代码
2.canvas公用模板设计
  1. <template name="canvas-share">
  2. <!-- <view style='width:0px;height:0px;overflow:hidden;opacity: 0;'> -->
  3. <canvas style="height:{{shareCanvasItem.Height}}px !important;" class='shareCanvas' canvas-id="shareCanvas" binderror="canvasIdErrorCallback"></canvas>
  4. <!-- </view> -->
  5. </template>
  6. 复制代码

3.js 逻辑实现

  1. // 调用公用组件
  2. let {
  3. CanvasUtil,
  4. util
  5. } = getApp();
  6. // 测试数据引入
  7. const testData= require('../../test.js');
  8. Page({
  9. /**
  10. * 页面的初始数据
  11. */
  12. data: {
  13. shareCanvasItem: {
  14. Height: 5000
  15. },//初始canvas高度,设置背景黑,此高度必须大于 动态生成内容高度,否则 无法全面覆盖背景
  16. items: [],
  17. },
  18. onLoad: function() {
  19. this.getList();
  20. },
  21. //获取列表数据
  22. getList() {
  23. var self = this;
  24. // purchasePrice 汇买价
  25. // cashPrice 钞买价
  26. // sellingPrice 汇卖价
  27. // banknotePrice 钞卖价
  28. //赋值过滤健全item
  29. self.setData({
  30. items: testData
  31. });
  32. },
  33. /* 分享事件 */
  34. share: function() {
  35. console.log('分享');
  36. var self = this;
  37. let titleTemp = `今日中行外汇牌价`;
  38. let tips = '*以上为保存时间的牌价,成交价格以实际交易为准';
  39. // 获取设备宽高
  40. var res = wx.getSystemInfoSync();
  41. var canvasWidth = res.windowWidth;
  42. var canvasHeight = self.data.shareCanvasItem.Height;
  43. // 获取canvas的的宽 自适应宽(设备宽/750) px
  44. var Rpx = (canvasWidth / 750).toFixed(2);
  45. //上边距
  46. var paddingTop = Rpx * 20;
  47. //左边距
  48. var paddingLeft = Rpx * 20;
  49. //右边距
  50. var paddingRight = Rpx * 20;
  51. //当前编写高
  52. var currentLineHeight = Rpx * 33;
  53. var context = wx.createCanvasContext('shareCanvas');
  54. //全局背景颜色默认填充
  55. context.setFillStyle('#333333');
  56. context.fillRect(0, 0, canvasWidth, canvasHeight);
  57. //字体颜色
  58. context.setFillStyle('#999999');
  59. context.setTextAlign('center');
  60. context.font = `${(Rpx * 36).toFixed(0)}px PingFangSC-Regular`;
  61. //内容行边距计算
  62. currentLineHeight += Rpx * 36;
  63. //标题文本 绘制
  64. context.fillText(titleTemp, canvasWidth / 2, currentLineHeight);
  65. context.setTextAlign('left');
  66. //内容行边距计算
  67. currentLineHeight += Rpx * 34;
  68. //item白色背景 矩形左右边距
  69. let padingLeftRightRect = Rpx * 40,
  70. rectRadius = Rpx * 10, //圆角10
  71. rectWidth = Rpx * 320, //宽
  72. rectHeight = Rpx * 320, //高
  73. topRectHeight = Rpx * 125; //美元上部分
  74. self.data.items.forEach((item, index) => {
  75. //保存上次绘制图,进行本次操作
  76. // context.save();
  77. //每两次进行换行逻辑
  78. if (index > 1 && index % 2 === 0) {
  79. //行高换行
  80. currentLineHeight += rectHeight + Rpx * 40;
  81. //边距重置
  82. padingLeftRightRect = Rpx * 40;
  83. }
  84. //局部 y currentLineHeight
  85. //局部 x padingLeftRightRect
  86. // 偶数为 left 处理逻辑 奇数为right 处理逻辑
  87. //left
  88. if (index % 2 === 0) {
  89. } else {
  90. //right 坐标 = 加矩形宽 + 中间距30
  91. padingLeftRightRect += rectWidth + Rpx * 30;
  92. }
  93. //矩形颜色设置
  94. context.setFillStyle('#ffffff');
  95. //调用绘制圆角矩形
  96. CanvasUtil.drawRoundedRect(context, padingLeftRightRect, currentLineHeight, rectWidth, rectHeight, rectRadius, true);
  97. //矩形上变背景颜色生成
  98. context.setFillStyle('#f7f7f7');
  99. //调用绘制圆角矩形
  100. CanvasUtil.drawRoundedRect(context, padingLeftRightRect, currentLineHeight, rectWidth, topRectHeight, rectRadius, true);
  101. //币种字体颜色
  102. context.setFillStyle('#333333');
  103. context.font = `${(Rpx * 34).toFixed(0)}px PingFangSC-Regular`;
  104. //币种文本绘制
  105. context.fillText(item.chName, padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34);
  106. //币种英文绘制
  107. context.fillText(item.abridge, padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
  108. //绘制币种图案
  109. context.drawImage(`/currencyImg/${item.iconName}`, padingLeftRightRect + Rpx * 226, currentLineHeight + Rpx * 35, Rpx * 64, Rpx * 64);
  110. //价格字体颜色
  111. context.setFillStyle('#666666');
  112. context.font = `${(Rpx * 26).toFixed(0)}px PingFangSC-Regular`;
  113. context.fillText('钞买价', padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 70, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
  114. context.fillText('汇买价', padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 110, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
  115. context.fillText('钞卖价', padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 150, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
  116. context.fillText('汇卖价', padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 190, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
  117. //价格值字体颜色
  118. context.setFillStyle('#333333');
  119. //钞买价
  120. context.fillText(item.cashPrice, padingLeftRightRect + Rpx * 204, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 70, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
  121. // 汇买价
  122. context.fillText(item.purchasePrice, padingLeftRightRect + Rpx * 204, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 110, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
  123. //钞卖价
  124. context.fillText(item.banknotePrice, padingLeftRightRect + Rpx * 204, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 150, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
  125. //汇卖价
  126. context.fillText(item.sellingPrice, padingLeftRightRect + Rpx * 204, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 190, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
  127. //操作完成后恢复上次值
  128. // context.restore();
  129. });
  130. //行高换行
  131. currentLineHeight += rectHeight + Rpx * 40;
  132. //字体颜色
  133. context.setFillStyle('#999999');
  134. context.setTextAlign('center');
  135. context.font = `${(Rpx * 28).toFixed(0)}px PingFangSC-Regular`;
  136. //领取提示文本 绘制
  137. context.fillText(tips, canvasWidth / 2, currentLineHeight);
  138. //行高换行
  139. currentLineHeight += Rpx * 30;
  140. //qrcode生成图片
  141. context.drawImage('/imgs/qrcode.png', paddingLeft, currentLineHeight, canvasWidth - paddingLeft - paddingRight, Rpx * 200);
  142. context.setTextAlign('left');
  143. //字体颜色
  144. context.setFillStyle('#EEC62E');
  145. context.font = `${(Rpx * 32).toFixed(0)}px PingFangSC-Regular`;
  146. //领取提示文本 绘制
  147. context.fillText('测试canvas', paddingLeft + Rpx * 43, currentLineHeight + Rpx * 90);
  148. //字体颜色
  149. context.setFillStyle('#999999');
  150. context.font = `${(Rpx * 28).toFixed(0)}px PingFangSC-Regular`;
  151. //领取提示文本 绘制
  152. context.fillText('出境游、炒汇必备神器', paddingLeft + Rpx * 43, currentLineHeight + Rpx * 130);
  153. //内容行高控制
  154. currentLineHeight += Rpx * 220;
  155. //设置最终canvas高度
  156. self.setData({
  157. shareCanvasItem: {
  158. Height: currentLineHeight
  159. }
  160. });
  161. //绘制完成
  162. context.draw();
  163. //调用公共组件保存图片
  164. util.saveImg();
  165. },
  166. /**
  167. * 生命周期函数--监听页面初次渲染完成
  168. */
  169. onReady: function() {},
  170. /**
  171. * 生命周期函数--监听页面显示
  172. */
  173. onShow: function() {},
  174. /**
  175. * 生命周期函数--监听页面隐藏
  176. */
  177. onHide: function() {},
  178. /**
  179. * 生命周期函数--监听页面卸载
  180. */
  181. onUnload: function() {},
  182. /**
  183. * 页面上拉触底事件的处理函数
  184. */
  185. onReachBottom: function() {},
  186. /**
  187. * 用户点击右上角分享
  188. */
  189. onShareAppMessage: function(res) {}
  190. })
  191. 复制代码

CanvasUtil testData 数据代码省略... 请查看顶部源码链接

微信小程序分享朋友圈 长海报 canvas 动态高度计算的更多相关文章

  1. 微信小程序分享朋友圈的实现思路与解决办法

    实现思路 那么既然小程序没有分享到朋友圈的api,我们怎么实现分享到朋友圈呢,下面我介绍一下实现思路. 既然没有捷径,那就走复杂一点的路线,那就是需要用户手动分享到朋友圈,问题又来了,用户手动分享的话 ...

  2. 微信小程序分享朋友圈

    原理:canvas生成图片再保存到手机 JS onShow: function () { var that = this; //1. 请求后端API生成小程序码 // that.getQr(); // ...

  3. 微信小程序仿朋友圈功能开发(发布、点赞、评论等功能)

    微信小程序仿朋友圈功能开发(发布.点赞.评论等功能) 1.项目分析 项目整体分为三个部分 发布 展示 详情页 graph LR 朋友圈发布 --内容发布--> 内容展示 内容展示 --点击展示卡 ...

  4. golang-vue实现微信小程序分享到朋友圈

    最近涉及到微信小程序分享到朋友圈,不知道微信为什么不直接接口分享,咱也不敢佛,咱也不敢问,只能百度问度娘,看官方文档,网上的一些分享五花八门,每一个重点的,所以整理了一下到底怎样生成二维码分享图片才是 ...

  5. 微信小程序分享至朋友圈的方法

    最近研究怎么实现微信小程序分享至朋友圈,对就是朋友圈. 微信小程序目前没有直接提供方法来将小程序分享至朋友圈,不过可以采用曲线救国的方式来达到目的. 方法分两步: 1.通过浏览器将希望分享的东西风向至 ...

  6. 微信小程序--分享功能

    微信小程序--分享功能 微信小程序前段时间开放了小程序右上角的分享功能, 可以分享任意一个页面到好友或者群聊, 但是不能分享到朋友圈 这里有微信开发文档链接:点击跳转到微信分享功能API 入口方法: ...

  7. 关于微信小程序分享/转发功能的实现方法

    实现微信小程序分享,可以有两个入口: 1. 小程序右上角菜单自带的分享 这个入口是默认关闭的,需要在当前页面中调用showShareMenu方法,开启分享 onLoad: function () { ...

  8. 微信小程序分享转发用法大全——自定义分享、全局分享、组合分享

    官方提供的自定义分享 使用隐式页面配置函数实现的全局分享-推荐 使用隐式路由实现的全局分享-不推荐,仅供了解隐式路由 前言: 目前微信小程序只开放了页面自定义分享的API,为了能够更灵活的进行分享配置 ...

  9. 微信小程序把玩(四十一)canvas API

    原文:微信小程序把玩(四十一)canvas API 绘图是每个移动应用必备的技术,基本上和Android,IOS,等移动开发都是相同的,创建个上下文,给你个画布再上画,官网给的小例子都比较全了自己去看 ...

随机推荐

  1. EIGENSTRAT计算PCA的显著性

    之前我写过一篇文章群体遗传分析分层校正,该选用多少个PCA?,里面提到可以通过EIGENSTRAT软件确定显著的主成分,后续就可以将显著的主成分加入协变量中. 这篇文章主要是讲如何通过EIGENSTR ...

  2. windows中怎么添加定时任务

    linux中有crontab定时任务,很方便 其实windows也有类似的 需求:定时执行python脚本 1.Windows键+R,调出此窗口,输入compmgmt.msc 2. 每分钟都执行一次脚 ...

  3. 2017ACM/ICPC广西邀请赛 1004 Covering

    Covering Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  4. grok语法定义

    grok默认表达式 Logstash 内置了120种默认表达式,可以查看patterns,里面对表达式做了分组,每个文件为一组,文件内部有对应的表达式模式.下面只是部分常用的. 常用表达式 表达式标识 ...

  5. Java开发笔记(一百一十八)AWT按钮

    前面介绍了如何通过AWT显示程序的窗口界面,那么要怎样在该窗口上面添加丰富多样的控件呢?注意Frame类是个窗口工具,它由窗楣(标题栏)与窗体(窗口主界面)两部分组成,故而Frame类只对整个窗口统筹 ...

  6. 在iis中部署网站出现的错误

    第一次错误: 解决的方案:点击网站新建一个同名的应用池,选择网站的基本设置,选中同名的应用池 接下来可能会有第二个错误 错误摘要HTTP 错误 500.21 - Internal Server Err ...

  7. c++基础(七)——面向对象程序设计

    面向对象程序设计(Object-oriented programming)的核心思想是数据抽象,继承,和动态绑定. 1. 继承 在C++语言中,基类将类型相关的函数与派生类不做改变直接继承的函数区分对 ...

  8. XGBoost对波士顿房价进行预测

    import numpy as np import matplotlib as mpl mpl.rcParams["font.sans-serif"] = ["SimHe ...

  9. SQL Server 索引优化——无用索引

    我们知道,合理的索引能大幅提升性能,但冗余的索引也会降低数据库性能.随着我们业务的发展,数据库的中的表.表结构.查询的内容都有可能发生变化.这样,有的索引就可能不再使用了,需要删除(因为维护索引即浪费 ...

  10. 7.1 为什么bulk使用奇特的json格式?

    回顾: bulk的语法要求:每个json串都不能换行,不同json串之间,必须换行   为什么不用标准json数组呢?如: [     {         "create":{.. ...