uniapp小程序使用wxml-to-canvas生成图片
开发框架:uniapp
场景:小程序保存页面为图片并上传
尝试方案:使用html-to-canvas,问题:小程序不允许操作dom,也无法获取dom标签,只能通过wx.createSelectorQuery()获取dom信息。
微信小程序官方解决方案:wxml-to-canvas。问题:只支持wxml的原生小程序canvas图片生成,相关配置也是原生小程序的配置。
解决方案:
1、打开微信小程序官方代码片段代码片段
2、在程序根目录下新建wxcomponents文件夹,将代码片段中的miniprogram_npm下的widget-ui和wxml-to-canvas两个文件夹复制进去

3、将/wxcomponents/wxml-to-canvas/index.js中的
module.exports = require("widget-ui");
//改为
module.exports = require("../widget-ui/index.js")
4、配置pages.json(这样uni-app才会打包wxcomponents)
"pages": [ { "path": "pages/share", "style": { "usingComponents": { "wxml-to-canvas": "/wxcomponents/wxml-to-canvas/index" } } }, ... ]
5、主页面 pages/share.vue
<template>
<view class="share-page">
<view class="share-page-box" id="box" v-if="show"
:style="{width: canvasWidth + 'px', height: canvasHeight + 'px' }">
<wxml-to-canvas class="widget" :width="canvasWidth" :height="canvasHeight"></wxml-to-canvas>
</view>
<view class="share-page-btn" @tap="extraImage">
<button class="btn-big" :style="getBtnStyle">保存图片</button>
</view>
</view>
</template>
<script>
const {
wxml,
style
} = require('./domData.js')
export default {
name: '',
data() {
return {
show: false, // 是否显示canvas
canvasWidth: 320, // 默认canvas宽高
canvasHeight: 480,
screenWidth: null, // 设备宽度
screenHeight: null, // 设备宽度
name: '',
pic: '',
chapter: '',
widget: null,
}
},
onLoad(options) {
console.log('options', options);
this.name = 'wxml生成canvas(liangtao)'
this.pic = 'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg'
this.chapter = ['第一段对话','第二段对话','第三段对话','第四段对话','第五段对话','第六段对话','第七段对话','第八段对话','第九段对话','第十段对话','第十一段对话','第十二段对话','第十三段对话']
// 获取设备信息
wx.getSystemInfo({
success: (res) => {
console.log("设备信息",res);
this.screenWidth = res.screenWidth
this.screenHeight = 1000//高度建议计算得出或写死。如使用res.screenHeight,文字过长时无法生成
this.canvasWidth = this.screenWidth
this.canvasHeight = this.screenHeight
this.show = true
// 数字容器宽度 动态设置
setTimeout(() => {
wx.showLoading({
title: '图片生成中...'
})
this.widget = this.selectComponent('.widget')
this.renderToCanvas()
}, 1000)
}
});
},
methods: {
// wxml 转 canvas
renderToCanvas() {
console.log('this.widget', this.widget)
const _wxml = wxml(this.name, this.pic, this.chapter)//调用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('生成失败')
})
},
// 保存图片
extraImage() {
const p2 = this.widget.canvasToTempFilePath()
let that = this
p2.then(result => {
let path = result.tempFilePath
console.log(path);
})
},
}
}
</script>
6、配置wxml页面 /pages/domData.js
const wxml = (name, pic, c1) => ` <view class="container"> <image src="` + pic + `" class="pic"/> <text class="name">${name}</text> <text class="content">` + c1[0] + `</text> <text class="content">` + c1[1] + `</text> <text class="content">` + c1[2] + `</text> <text class="content">` + c1[3] + `</text> <text class="content">` + c1[4] + `</text> <text class="content">` + c1[5] + `</text> <text class="content">` + c1[6] + `</text> <text class="content">` + c1[7] + `</text> <text class="content">` + c1[8] + `</text> <text class="content">` + c1[9] + `</text> <text class="content">` + c1[10] + `</text> <text class="content">` + c1[11] + `</text> <text class="content">` + c1[12] + `</text> </view> ` /** * @param {*} screenWidth 屏幕宽度 * @param {*} canvasWidth 画布宽度 * @param {*} canvasHeight 画布高度 * @param {*} numberWidth 数字宽度,动态设置 * @return {*} */ const style = (screenWidth, canvasWidth, canvasHeight) => { return { "container": { width: canvasWidth, height: canvasHeight, position: 'relative', overflow: 'hidden', backgroundColor: '#ffffff', }, "name": { fontSize: 20, color: '#333', marginLeft: canvasWidth * 0.08, width: canvasWidth * 0.84, height: screenWidth * 0.18, textAlign: 'center', }, "content": { fontSize: 14, color: '#333', width: canvasWidth * 0.84, height: screenWidth * 0.15, marginLeft: canvasWidth * 0.08, }, "pic": { width: canvasWidth * 0.3, height: screenWidth * 0.28, marginTop: canvasWidth * 0.1, marginLeft: canvasWidth * 0.35, marginBottom: canvasWidth * 0.05, borderRadius: screenWidth * 0.14, overflow: 'hidden', }, } } module.exports = { wxml, style }
需要说明一点,此处的wxml返回的是字符串,也就是页面实际呈现的结果,不可以在里面写wx:if,wx:for等语法。
如果需要加,在箭头函数里面直接用js写法,去判断和遍历,然后return字符串。

7、最终效果

wxml-to-canvas要注意的一些问题
1、只能画view,text,img
2、每个元素必须要设置宽高
3、默认是flex布局,可以通过flexDirection: "column"来改变排列方式

浙公网安备 33010602011771号