微信小程序---合成海报分享到朋友圈

记录一下折腾小程序遇到的问题。小程序目前只提供了分享给朋友或者群聊,想要分享到朋友圈只能合成带小程序码的海报分享到朋友圈

本篇的小程序使用的是uni-app开发小程序,代码都是适用于uni-app的,方法和微信小程序官方差别不大,”uni.”改成”wx.”基本就可以使用。

合成带小程序码的海报分享到朋友圈,小程序码怎么获取看前文《PHP获取微信小程序码》,这篇文章要做的是所有图片素材已经有网络路径,当然路径是https协议的,并且在小程序后台已配置。

思路

    1. 合理布局,画布设置好尺寸,放在屏幕以外备用
    1. wx.downloadFile()方法下载所有需要使用的图片,得到的路径为本地临时路径
    1. canvas绘制海报;将图片合理绘制在海报上预设的位置
    1. 将canvas提取出来,获得海报本地临时路径,在弹窗中展示使用
    1. 点击按钮,wx.saveImageToPhotosAlbum(),使用海报本地临时路径下载到本地相册

准备工作

data中定义几个变量,方便下文使用:

1
2
3
4
5
6
7
8
9
product_cover: '',  // 商品图url
screenWidth: 375 , // 海报宽度
windowHeight: 665, // 海报高度
acode_path: null, // 小程序码路径
qrcode_temp: '', // 小程序码本地临时路径
goods_temp: '', // 商品图本地临时路径
popupShow: false, // 是否显示海报弹窗
maskShow: false, // 遮罩曾是否显示
tempFilePath: null // 海报本地临时路径

模板和css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- canvas绘制海报 -->
<canvas canvas-id="myCanvas" class="box-canvas" style="width:375px;" :style="{height: windowHeight + 'px'}"></canvas>

<!-- 海报弹窗模板 -->
<view class="box-mask" v-if="popupShow"></view>

<!-- 海报弹窗-->
<view class="box-poster" v-if="popupShow">
<view class="btn-close iconfont iconguanbi2" @click="cancelPoster"></view>
<view class="canvas-box">
<image :src="tempFilePath"></image>
</view>
<button class="btn-save" @click="canvasToImage">下载图片</button>
</view>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/* 把canvas直接展示,移出到屏幕可视区域以外,方便绘制,调试的时候放在屏幕上就行 */
.box-canvas{
position: fixed;
top:100000px;
}

/* 海报弹窗 */
.box-poster{
position: fixed;
top:50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 101;

.btn-close{
position: absolute;
top: -25rpx;
right: -25rpx;
width: 50rpx;
height: 50rpx;
line-height: 50rpx;
text-align: center;
font-size: 40rpx;
background: #fff;
border-radius: 50%;
color: $uni-color-primary;
box-shadow: 2rpx 2rpx 10rpx $uni-color-primary;
}

.canvas-box{
width: 460rpx;
height: 820rpx;
display: inline-block;
image{
width: 460rpx;
height: 820rpx;
}
}

.btn-save{
margin-top: 5px;
width: 460rpx;
height: 75rpx;
line-height: 75rpx;
background: #fa4547;
color: #fff;
font-size: 26rpx;
}
}

主要是把画布设置好尺寸,放在屏幕以外的地方

下载所有需要使用的图片

https://developers.weixin.qq.com/miniprogram/dev/api/network/download/wx.downloadFile.html

官方说明

wx.downloadFile()

1
2
3
4
5
6
7
8
9
10
11
12
13
DownloadTask wx.downloadFile(Object object)
下载文件资源到本地。客户端直接发起一个 HTTPS GET 请求,返回文件的本地临时路径,单次下载允许的最大文件为 50MB。使用前请注意阅读相关说明。

注意:请在服务端响应的 header 中指定合理的 Content-Type 字段,以保证客户端正确处理文件类型。

示例代码
wx.downloadFile({
url: 'https://example.com/audio/123', //仅为示例,并非真实的资源
success (res) {
// 只要服务器有响应数据,就会把响应内容写入文件并进入 success 回调,业务需要自行判断是否下载到了想要的内容

}
})

关键源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
* 缓存图片
* @param {Object} target 目标
* @param {Object} img_url 图片网络链接
*/
cacheFile(target, img_url, func=null) {
let _this = this;
wx.downloadFile({
url: img_url,
success: function(res2) {
if (target == 'qrcode') {
console.log('二维码:' + res2.tempFilePath)
//缓存二维码
_this.qrcode_temp = res2.tempFilePath;
} else if (target == 'portrait') {
console.log('头像:' + res2.tempFilePath)
//缓存二维码
_this.portrait_temp = res2.tempFilePath;
} else if (target == 'goods') {
console.log('商品封面:' + res2.tempFilePath)
//缓存二维码
_this.goods_temp = res2.tempFilePath;
}
if (func) {
func()
}
}
})
},
/**
* 缓存图片
* @param {Object} target 目标
* @param {Object} img_url 图片网络链接
* @param {Object} func 回调函数
*/
cacheFile(target, img_url, func=null) {
let _this = this;
wx.downloadFile({
url: img_url,
success: function(res2) {
if (target == 'qrcode') {
console.log('二维码:' + res2.tempFilePath)
_this.qrcode_temp = res2.tempFilePath;
} else if (target == 'portrait') {
console.log('头像:' + res2.tempFilePath)
_this.portrait_temp = res2.tempFilePath;
} else if (target == 'goods') {
console.log('商品封面:' + res2.tempFilePath)
_this.goods_temp = res2.tempFilePath;
}
if (func) {
func()
}
}
})
}

canvas绘制海

https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.createOffscreenCanvas.html

canvasToTempFilePath()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
wx.canvasToTempFilePath(Object object, Object this)
把当前画布指定区域的内容导出生成指定大小的图片。在 draw() 回调里调用该方法才能保证图片导出成功。

示例代码
wx.canvasToTempFilePath({
x: 100,
y: 200,
width: 50,
height: 50,
destWidth: 100,
destHeight: 100,
canvasId: 'myCanvas',
success(res) {
console.log(res.tempFilePath)
}

关键源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
* 绘制海报
*/
drawImage() {
//绘制canvas图片
var _this = this

var bgPath = '/static/image/banner_index.png'
var portraitPath = _this.portrait_temp
var goodsPath = _this.goods_temp
var qrPath = _this.qrcode_temp
var hostNickname = 'test'

var scale = _this.scale
var windowWidth = _this.screenWidth
var windowHeight = _this.windowHeight

var product_price = _this.detail.product_price;
var product_name = _this.detail.product_name;

// // 绘制头像
// ctx.save()
// ctx.beginPath()
// ctx.arc(25, 25, 25, 0, 2 * Math.PI)
// ctx.clip()
// ctx.drawImage(portraitPath, 0, 0, 50, 50)
// ctx.restore()

const ctx = wx.createCanvasContext('myCanvas')
ctx.setFillStyle('#ffffff');
ctx.fillRect(0,0,windowWidth,windowHeight);

// 绘制商品图
ctx.drawImage(goodsPath, 0, 300 * scale, 375 * scale, 375 * scale, 15 * scale, 45 * scale, 345 * scale, 345 * scale);

// 绘制
ctx.setFillStyle('#333333');
ctx.setFontSize(18 * scale)
ctx.fillText(product_name, 15 * scale, 445 * scale)

ctx.setFillStyle('red');
ctx.setFontSize(22 * scale)
ctx.fillText('¥'+product_price, 15 * scale, 565 * scale)

ctx.setFillStyle('#9a9a9a');
ctx.setFontSize(12 * scale)
ctx.fillText('扫描或长按小程序码', 250 * scale, 620 * scale)

// 绘制二维码
ctx.drawImage(qrPath, 260 * scale, 520 * scale, 80 * scale, 80 * scale)

ctx.draw(true, function(){
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: _this.windowWidth,
height: _this.windowWidth ,
destWidth: _this.windowWidth * 4,
destHeight: _this.windowWidth * 4,
canvasId: 'myCanvas',
success: function(res) {
_this.tempFilePath = res.tempFilePath;
},
fail: function(err) {
uni.hideLoading();
console.log('失败')
console.log(err)
}
})
});

return;
},

wx.canvasToTempFilePath()必须在ctx.draw()执行完之后才能调用。

获得海报本地临时路径后,可以直接在image标签中使用,弹窗展示海报预览图。

点击保存海报到本地

wx.saveImageToPhotosAlbum()

1
2
3
4
5
6
7
8
9
wx.saveImageToPhotosAlbum(Object object)
基础库 1.2.0 开始支持,低版本需做兼容处理。
调用前需要 用户授权 scope.writePhotosAlbum
保存图片到系统相册。

示例代码
wx.saveImageToPhotosAlbum({
success(res) { }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 保存为文件
*/
canvasToImage(){
var _this = this
uni.showLoading({
title: '正在保存...'
});
setTimeout(function(){
wx.saveImageToPhotosAlbum({
filePath: _this.tempFilePath,
})
uni.hideLoading();
_this.popupShow = false;
}, 1000);
},

成品如下:

WechatIMG131