微信小程序分享朋友圈 长海报 canvas 动态高度计算

业务场景

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

github源码链接

https://github.com/richard1015/canvas

微信IDE代码预览

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

海报需求设计图分析

图1分析: 可以看到海报 要求宽750 高1218(当然了数据是动态的,高度肯定不会固定值,需要我们动态去计算)
图1
图2分析:矩形框 宽高为固定值 320 背景颜色#fff 圆角10
图2
图3分析:矩形框 上半部分 宽320 高125 背景颜色#f7f7f7
图3

代码逻辑实现

1.模板逻辑 wxml添加canvas公用组件
<!--pages/index/index.wxml-->
<view class='index'>

  <!-- 公用canvas share -->
  <import src="../common/canvasShare.wxml" />
  <template data="{{shareCanvasItem}}" is="canvas-share" />

  <!-- content 内容预显示 begin -->
  <view class='content'>
    <view class='content_header'>
      <view class='left' bindtap='toChoiceBank'>
        <text>中国银行(测试数据)</text>
      </view>
    </view>
    <view class='content_item'>
      ...此处省略
    </view>
  </view>
  <!-- content end -->
  <import src="../common/footerShare.wxml" />
  <template is="footer-share" />
</view>
2.canvas公用模板设计
<template name="canvas-share">
  <!-- <view style='width:0px;height:0px;overflow:hidden;opacity: 0;'> -->
    <canvas style="height:{{shareCanvasItem.Height}}px !important;" class='shareCanvas' canvas-id="shareCanvas" binderror="canvasIdErrorCallback"></canvas>
  <!-- </view> -->
</template>

3.js 逻辑实现

// 调用公用组件
let {
  CanvasUtil,
  util
} = getApp();
// 测试数据引入
const testData= require('../../test.js');
Page({
  /**
   * 页面的初始数据
   */
  data: {
    shareCanvasItem: {
      Height: 5000
    },//初始canvas高度,设置背景黑,此高度必须大于 动态生成内容高度,否则 无法全面覆盖背景
    items: [],
  },
  onLoad: function() {
    this.getList();
  },
  //获取列表数据
  getList() {
    var self = this;

    // purchasePrice 汇买价
    // cashPrice 钞买价
    // sellingPrice 汇卖价
    // banknotePrice 钞卖价
    //赋值过滤健全item
    self.setData({
      items: testData
    });
  },

  /* 分享事件 */
  share: function() {
    console.log('分享');
    var self = this;

    let titleTemp = `今日中行外汇牌价`;

    let tips = '*以上为保存时间的牌价,成交价格以实际交易为准';
    // 获取设备宽高
    var res = wx.getSystemInfoSync();
    var canvasWidth = res.windowWidth;
    var canvasHeight = self.data.shareCanvasItem.Height;
    // 获取canvas的的宽  自适应宽(设备宽/750) px
    var Rpx = (canvasWidth / 750).toFixed(2);
    //上边距
    var paddingTop = Rpx * 20;
    //左边距
    var paddingLeft = Rpx * 20;
    //右边距
    var paddingRight = Rpx * 20;
    //当前编写高
    var currentLineHeight = Rpx * 33;

    var context = wx.createCanvasContext('shareCanvas');

    //全局背景颜色默认填充
    context.setFillStyle('#333333');
    context.fillRect(0, 0, canvasWidth, canvasHeight);

    //字体颜色
    context.setFillStyle('#999999');
    context.setTextAlign('center');
    context.font = `${(Rpx * 36).toFixed(0)}px PingFangSC-Regular`;
    //内容行边距计算
    currentLineHeight += Rpx * 36;

    //标题文本 绘制
    context.fillText(titleTemp, canvasWidth / 2, currentLineHeight);
    context.setTextAlign('left');

    //内容行边距计算
    currentLineHeight += Rpx * 34;

    //item白色背景 矩形左右边距
    let padingLeftRightRect = Rpx * 40,
      rectRadius = Rpx * 10, //圆角10
      rectWidth = Rpx * 320, //宽
      rectHeight = Rpx * 320, //高
      topRectHeight = Rpx * 125; //美元上部分


    self.data.items.forEach((item, index) => {
      //保存上次绘制图,进行本次操作
      // context.save();
      //每两次进行换行逻辑
      if (index > 1 && index % 2 === 0) {
        //行高换行
        currentLineHeight += rectHeight + Rpx * 40;
        //边距重置
        padingLeftRightRect = Rpx * 40;
      }
      //局部 y  currentLineHeight
      //局部 x  padingLeftRightRect

      // 偶数为 left 处理逻辑  奇数为right 处理逻辑
      //left
      if (index % 2 === 0) {

      } else {
        //right 坐标 =  加矩形宽  + 中间距30
        padingLeftRightRect += rectWidth + Rpx * 30;
      }
      //矩形颜色设置
      context.setFillStyle('#ffffff');
      //调用绘制圆角矩形
      CanvasUtil.drawRoundedRect(context, padingLeftRightRect, currentLineHeight, rectWidth, rectHeight, rectRadius, true);
      //矩形上变背景颜色生成
      context.setFillStyle('#f7f7f7');
      //调用绘制圆角矩形
      CanvasUtil.drawRoundedRect(context, padingLeftRightRect, currentLineHeight, rectWidth, topRectHeight, rectRadius, true);

      //币种字体颜色
      context.setFillStyle('#333333');
      context.font = `${(Rpx * 34).toFixed(0)}px PingFangSC-Regular`;
      //币种文本绘制
      context.fillText(item.chName, padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34);
      //币种英文绘制
      context.fillText(item.abridge, padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
      //绘制币种图案
      context.drawImage(`/currencyImg/${item.iconName}`, padingLeftRightRect + Rpx * 226, currentLineHeight + Rpx * 35, Rpx * 64, Rpx * 64);

      //价格字体颜色
      context.setFillStyle('#666666');
      context.font = `${(Rpx * 26).toFixed(0)}px PingFangSC-Regular`;
      context.fillText('钞买价', padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 70, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);

      context.fillText('汇买价', padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 110, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);

      context.fillText('钞卖价', padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 150, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);

      context.fillText('汇卖价', padingLeftRightRect + Rpx * 26, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 190, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
      //价格值字体颜色
      context.setFillStyle('#333333');
      //钞买价
      context.fillText(item.cashPrice, padingLeftRightRect + Rpx * 204, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 70, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
      // 汇买价
      context.fillText(item.purchasePrice, padingLeftRightRect + Rpx * 204, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 110, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
      //钞卖价
      context.fillText(item.banknotePrice, padingLeftRightRect + Rpx * 204, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 150, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);
      //汇卖价
      context.fillText(item.sellingPrice, padingLeftRightRect + Rpx * 204, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 190, currentLineHeight + Rpx * 30 + Rpx * 34 * 2 + Rpx * 10);

      //操作完成后恢复上次值
      // context.restore();
    });
    //行高换行
    currentLineHeight += rectHeight + Rpx * 40;



    //字体颜色
    context.setFillStyle('#999999');
    context.setTextAlign('center');
    context.font = `${(Rpx * 28).toFixed(0)}px PingFangSC-Regular`;
    //领取提示文本 绘制
    context.fillText(tips, canvasWidth / 2, currentLineHeight);

    //行高换行
    currentLineHeight += Rpx * 30;

    //qrcode生成图片
    context.drawImage('/imgs/qrcode.png', paddingLeft, currentLineHeight, canvasWidth - paddingLeft - paddingRight, Rpx * 200);

    context.setTextAlign('left');
    //字体颜色
    context.setFillStyle('#EEC62E');
    context.font = `${(Rpx * 32).toFixed(0)}px PingFangSC-Regular`;
    //领取提示文本 绘制
    context.fillText('测试canvas', paddingLeft + Rpx * 43, currentLineHeight + Rpx * 90);

    //字体颜色
    context.setFillStyle('#999999');
    context.font = `${(Rpx * 28).toFixed(0)}px PingFangSC-Regular`;
    //领取提示文本 绘制
    context.fillText('出境游、炒汇必备神器', paddingLeft + Rpx * 43, currentLineHeight + Rpx * 130);

    //内容行高控制
    currentLineHeight += Rpx * 220;


    //设置最终canvas高度
    self.setData({
      shareCanvasItem: {
        Height: currentLineHeight
      }
    });
    //绘制完成
    context.draw();
    //调用公共组件保存图片
    util.saveImg();
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function() {},

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function() {},

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function() {},

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function() {},

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function() {},

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function(res) {}
})

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

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

推荐阅读更多精彩内容