小程序通过wxml-to-canvas生成分享海报

需求:

小程序项目中,想要实现生成一张海报图,并且可以将图片保存到手机本地相册,然后用户可以分享到朋友圈或者发送给好友

小程序的canvas可以实现,但是学习成本大,排版麻烦

所以打算使用小程序官方扩展组件wxml-to-canvas

原因:

由于项目使用了uniapp开发,跟小程序扩展组件的安装逻辑冲突

正常原生小程序开发,如果要增加扩展组件wxml-to-canvas

只需要安装

1
npm install --save wxml-to-canvas

后面再增加JSON组件声明,wxml引入组件即可

执行之后,会在项目根目录下创建node_modules目录,但是这个node_modules 目录不会参与小程序编译、上传和打包,所以要通过开发者工具“工具-构建 npm”,这样就会在node_modules 的同级目录下会生成一个 miniprogram_npm 目录,里面会存放构建打包后的 npm 包,也就是小程序真正使用的 npm 包。

但是uniapp开发的小程序不一样,首先uniapp项目里会有自己的package.json文件,安装npm install之后,会在项目根目录生成一个node_modules目录,里面是所有第三方的安装包,包括uniapp的所有包,核心、编译、解析等等。

经过uniapp打包之后,生成的原生小程序项目(也就是我们最终给开发者工具使用的项目包),里面是不包含node_modules目录,也就没办法通过开发者工具“工具-构建 npm”生成miniprogram_npm 目录

所以解决方案是

下载官方wxml-to-canvas的代码片段

我们在目录里找到miniprogram_npm目录

img

将其中两个个文件

widget-ui、wxml-to-canvas拷贝下来,

放到我们的uniapp项目里wxcomponents目录下

最终形成的文件格式如下:

img

然后在全局引入wxml-to-canvas

1
2
3
"usingComponents": {
"wxml-to-canvas": "/wxcomponents/wxml-to-canvas/index",
}

另外需要修改wxml-to-canvas/index.js

1
module.exports = require("widget-ui");

改为

1
module.exports = require("../widget-ui/index");

剩下的就是按照官方api进行开发就可以了

index.vue

页面引入组件

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
<template>
<wxml-to-canvas class="widget" :width="canvasWidth" :height="canvasHeight"></wxml-to-canvas>
</template>

<script>
const { wxml, style } = require('./DomData.js')

export default {

onLoad() {
setTimeout(() => {
wx.showLoading({title: '海报生成中...'})
this.widget = this.selectComponent('.widget')
this.renderToCanvas()
}, 1000)
},
methods: {
// wxml 转 canvas
renderToCanvas () {
const _wxml = wxml('张三')
const _style = style(this.screenWidth, this.canvasWidth, this.canvasHeight)
const p1 = this.widget.renderToCanvas({ wxml: _wxml, style: _style })
p1.then((res) => {
console.log('海报生成成功');
wx.hideLoading()
}).catch((err) => {
console.log('生成失败')
})
},
}
}



</script>

DomData.js

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

/**
*
* @param {*} name 名字
*/
const wxml = (name) =>`
<view class="container">
<image src="https://atg-fs-static.oss-cn-hangzhou.aliyuncs.com/wdqActivity/drug/bg1.png" class="bg1"/>
<image src="https://atg-fs-static.oss-cn-hangzhou.aliyuncs.com/wdqActivity/drug/bg2.png" class="bg2"/>
<view class="box">
<text class="name">`+ name +`</text>
</view>
</view>
`

/**
*
*
* @param {*} screenWidth 屏幕宽度
* @param {*} canvasWidth 画布宽度
* @param {*} canvasHeight 画布高度
* @return {*}
*/
const style = (screenWidth, canvasWidth, canvasHeight) => {
return {
"container": {
width: canvasWidth,
height: canvasHeight,
position: 'relative',
overflow: 'hidden',
},
"bg1": {
position: 'absolute',
top: 0,
left: 0,
width: canvasWidth,
height: canvasHeight,
zIndex: 1,
},
"bg2": {
position: 'absolute',
top: screenWidth * 0.17,
left: screenWidth * 0.04,
width: screenWidth * 0.84,
height: screenWidth * 1.08,
zIndex: 2,
},
"box": {
position: 'absolute',
top: screenWidth * 0.17,
left: screenWidth * 0.04,
width: screenWidth * 0.84,
height: screenWidth * 1.08,
zIndex: 99,
},
"name":{
fontSize: 20,
color: '#333',
marginTop: screenWidth * 0.35,
marginLeft: screenWidth * 0.05,
},
}
}

module.exports = {
wxml,
style
}

注意

DomData.js中引入的图片链接地址必须是全英文,不能有中文

文档:

wxml-to-canvas 微信官网

wxml-to-canvas github官网

使用示例


小程序通过wxml-to-canvas生成分享海报
https://thaneyang.github.io/2021/11/小程序通过wxml-to-canvas生成分享海报.html
作者
ThaneYang
发布于
2021年11月21日
许可协议