微信小程序分享朋友圈 长海报 canvas 动态高度计算
业务场景
在微信中 小程序无法分享到朋友圈,目前大部分的解决方案都是,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公用组件
<!--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 数据代码省略... 请查看顶部源码链接
微信小程序分享朋友圈 长海报 canvas 动态高度计算的更多相关文章
- 微信小程序分享朋友圈的实现思路与解决办法
实现思路 那么既然小程序没有分享到朋友圈的api,我们怎么实现分享到朋友圈呢,下面我介绍一下实现思路. 既然没有捷径,那就走复杂一点的路线,那就是需要用户手动分享到朋友圈,问题又来了,用户手动分享的话 ...
- 微信小程序分享朋友圈
原理:canvas生成图片再保存到手机 JS onShow: function () { var that = this; //1. 请求后端API生成小程序码 // that.getQr(); // ...
- 微信小程序仿朋友圈功能开发(发布、点赞、评论等功能)
微信小程序仿朋友圈功能开发(发布.点赞.评论等功能) 1.项目分析 项目整体分为三个部分 发布 展示 详情页 graph LR 朋友圈发布 --内容发布--> 内容展示 内容展示 --点击展示卡 ...
- golang-vue实现微信小程序分享到朋友圈
最近涉及到微信小程序分享到朋友圈,不知道微信为什么不直接接口分享,咱也不敢佛,咱也不敢问,只能百度问度娘,看官方文档,网上的一些分享五花八门,每一个重点的,所以整理了一下到底怎样生成二维码分享图片才是 ...
- 微信小程序分享至朋友圈的方法
最近研究怎么实现微信小程序分享至朋友圈,对就是朋友圈. 微信小程序目前没有直接提供方法来将小程序分享至朋友圈,不过可以采用曲线救国的方式来达到目的. 方法分两步: 1.通过浏览器将希望分享的东西风向至 ...
- 微信小程序--分享功能
微信小程序--分享功能 微信小程序前段时间开放了小程序右上角的分享功能, 可以分享任意一个页面到好友或者群聊, 但是不能分享到朋友圈 这里有微信开发文档链接:点击跳转到微信分享功能API 入口方法: ...
- 关于微信小程序分享/转发功能的实现方法
实现微信小程序分享,可以有两个入口: 1. 小程序右上角菜单自带的分享 这个入口是默认关闭的,需要在当前页面中调用showShareMenu方法,开启分享 onLoad: function () { ...
- 微信小程序分享转发用法大全——自定义分享、全局分享、组合分享
官方提供的自定义分享 使用隐式页面配置函数实现的全局分享-推荐 使用隐式路由实现的全局分享-不推荐,仅供了解隐式路由 前言: 目前微信小程序只开放了页面自定义分享的API,为了能够更灵活的进行分享配置 ...
- 微信小程序把玩(四十一)canvas API
原文:微信小程序把玩(四十一)canvas API 绘图是每个移动应用必备的技术,基本上和Android,IOS,等移动开发都是相同的,创建个上下文,给你个画布再上画,官网给的小例子都比较全了自己去看 ...
随机推荐
- 如何基于EasyDSS流媒体RTMP、HLS(m3u8)、HTTP-FLV、RTSP服务器体系的全套SDK完成各种场景下的视频应用需求
需求背景 回顾EasyDSS的发展过程,基本上保持的是先局部后系统.先组件后平台的发展方式,一步一步夯实每一个细节功能点,从最基础.最兼容的音视频数据的拉流获取,到高效的.全兼容的数据推流,再到流媒体 ...
- [LeetCode] 401. Binary Watch 二进制表
A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom ...
- [LeetCode] 844. Backspace String Compare 退格字符串比较
Given two strings S and T, return if they are equal when both are typed into empty text editors. # m ...
- 什么是 Web server
前端开发人员应该对 Web 开发中的基本概念有一些了解,请简述 什么是 Web 服务器 Web 服务器能做什么 首先我们来了解什么是服务器(server) 一般来说,server 有两重意思 有时候 ...
- 【OpenCV开发】OpenCV3后IPLimage转换成MAT的问题
IplImage* img1 = cvCreateImage(cvGetSize(resizeRes), IPL_DEPTH_8U, 1);//创建目标图像 Mat test = img1; 报错 ...
- android基础---->Toast的使用
简要说明 Toast是一种没有交点,显示时间有限,不能与用户进行交互,用于显示提示信息的显示机制,我们可以把它叫做提示框.Toast不依赖 于Activity,也就是说,没有Activity,依然可以 ...
- 运行报错:'_TestResult' object has no attribute 'outputBuffer'
一.运行main函数,未生成测试报告,报错:'_TestResult' object has no attribute 'outputBuffer' 解决方式: 1.在HTMLTestReportCN ...
- Qt5 QtQuick系列----QtQuick的Secne Graph剖析(3)-- qml与OpenGl结合
我读的书愈多,就愈亲近世界,愈明了生活的意义,愈觉得生活的重要. -- 高尔基 需要先看:https://blog.csdn.net/qq_35865125/article/details/86485 ...
- Git的各种工作流
Git工作流可以理解为团队成员遵守的一种代码管理方案,在Git中有以下几种常见工作流: 集中式工作流 功能开发工作流 Gitflow工作流 Forking工作流 1)集中式工作流 这种工作方式跟svn ...
- Apache Kafka + Spark Streaming Integration
1.目标 为了构建实时应用程序,Apache Kafka - Spark Streaming Integration是最佳组合.因此,在本文中,我们将详细了解Kafka中Spark Streamin ...