uniapp使用wxml-to-canvas开发小程序保存canvas图片

2024-01-10 23:44

本文主要是介绍uniapp使用wxml-to-canvas开发小程序保存canvas图片,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

微信小程序官方解决方案:wxml-to-canvas

使用wxml-to-canvas要知道一些前提条件
1、只能画view,text,image
2、每个元素必须要设置宽高
3、默认是flex布局,可以通过flexDirection: "column"来改变排列方式
4、文字 必须放在text中,放在view中无法显示,且text不支持字体加粗
5、如果你要设置背景颜色,请使用backgroundColor,而非background,border同理~
6、多个absolute元素时,因为没有z-index,template元素自上而下渲染,对应z-index依次增高
7、导出图片过大,可以通过canvasToTempFilePath({fileType, quality})配置里面的quality字段来减小
8、image只支持临时地址和网络地址,不支持base64和本地图片,可以通过writeFile 把base64转成临时地址
如下:
const fs = wx.getFileSystemManager();
let qrcodeBase64 = QRresult.data;
let qrcodeLink = `${wx.env.USER_DATA_PATH}/qrcodeLink.gif`;
fs.writeFile({filePath: qrcodeLink,data: qrcodeBase64,encoding: 'base64',success: res => {console.log(res)shopJson.qrcode = qrcodeLink;this.renderToCanvas();},fail(res) {console.error(res)}
})9、Canvas 初始化问题:为了正确绘制图像,需要确保在调用 canvas.draw() 之前完成所有绘制操作。
10、不支持实时更新:一旦 Canvas 绘制完成,它将成为静态图像,无法实时更新。如果需要实时更新数据可视化图表,可以考虑
使用其他库或组件。
11、长按保存图片问题:wxml-to-canvas 组件默认无法通过长按保存图片功能保存 Canvas 图像。你可能需要自行实现该功能,
并适配不同平台的实现方式。
12、对低版本小程序的兼容性问题:某些较旧的微信小程序版本可能无法完全支持 wxml-to-canvas 组件。在开发之前,请确保目
标用户群体的微信小程序版本。
13、性能问题:复杂的数据可视化图表可能会影响性能,尤其是在绘制大量数据时。尽量优化绘制逻辑,以避免出现卡顿或延迟。
14、与其他组件的兼容性问题:wxml-to-canvas 组件可能与其他小程序组件存在一些兼容性问题,导致样式错乱或布局问题。建
议在使用时进行充分的测试和调试。
15、跨平台问题:wxml-to-canvas 组件目前主要针对微信小程序,可能无法直接适用于其他小程序平台或移动端框架。如果需要
在其他平台上实现类似的功能,可能需要另行寻找适合的解决方案。
16、Canvas 绘图能力限制:由于 Canvas 的绘图能力有限,某些高级的数据可视化需求可能无法直接通过 wxml-to-canvas 组
件实现。在确定方案之前,建议先了解 Canvas 绘图的限制和特性。
17、样式定制问题:某些样式属性或效果可能难以通过 wxml-to-canvas 组件实现,例如阴影、渐变色等。需要根据具体需求考虑
是否能够满足所需的样式效果。
18、开发者工具与真机表现差异:在进行调试和预览时,开发者工具上的表现可能与真机上存在一些差异。建议进行真机测试,以
确保数据可视化图表在不同设备上正常显示。等等...其他未知问题...

一、安装

npm install --save wxml-to-canvas

二、在程序根目录下新建 wxcomponents 文件夹,将node_modules下的 widget-ui 和 wxml-to-canvas 两个文件夹复制进去。

注意:这里有的安装后生成的node_modules还不一样,可直接复制dist里面的即可(如下图)

 三、将/wxcomponents/wxml-to-canvas/index.js中的

module.exports = require("widget-ui");
//改为
module.exports = require("../widget-ui/index.js")

 四、配置pages.json (这样uni-app才会打包wxcomponents)

  • 1. 在需要用到的页面配置
"pages": [{"path": "pages/xxx","style": {"usingComponents": {"wxml-to-canvas": "/wxcomponents/wxml-to-canvas/index"}}},
...
]
  • 2. 或者在globalStyle里面全局配置
"globalStyle": {"navigationBarTextStyle": "black","navigationBarTitleText": "uni-app","navigationBarBackgroundColor": "#F8F8F8","backgroundColor": "#F8F8F8","usingComponents": {"wxml-to-canvas": "/wxcomponents/wxml-to-canvas/index"}
},

五、重点来了,如何使用?

  •  页面配置

<!-- 测试页面,可复制使用 -->
<template><view class="wrap"><!-- 保存canvas测试 --><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-box msg-box" v-else :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }">{{ msg }}</view><view class="share-page-btn" @tap="extraImage"><button class="btn-big" :style="getBtnStyle">保存图片</button></view></view></view>
</template><script>
import { wxml, style } from './DomData';
export default {data() {return {show: false, // 是否显示canvascanvasWidth: 320, // 默认canvas宽高canvasHeight: 480,screenWidth: null, // 设备宽度screenHeight: null, // 设备高度// name: '',// pic: '',// chapter1: '',// chapter2: '',widget: null,msg: '加载中,请稍等...', // 提示语listData:[{type:'1',title:'标题一',auther: '张三  2024-01-10',imgsrc:'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg',text:'本报讯(记者 杜晨薇)上海正在建设东方枢纽项目,浦东国际机场与沪通铁路将实现连通,枢纽周边临空产业、重点项目布局正在规划设计中。为落实上海市政府与中国东方航空集团有限公司(以下简称“中国东航”)合作协议要求,充分利用东方枢纽建设发展机遇期进一步深化合作发展,昨天下午,浦东新区政府与中国东航签署深化合作战略协议。'},{type: '2',title: '标题二',auther: '张三  2024-01-10',imgsrc: 'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg',text: '本报讯(记者 杜晨薇)上海正在建设东方枢纽项目,浦东国际机场与沪通铁路将实现连通,枢纽周边临空产业、重点项目布局正在规划设计中。为落实上海市政府与中国东方航空集团有限公司(以下简称“中国东航”)合作协议要求,充分利用东方枢纽建设发展机遇期进一步深化合作发展,昨天下午,浦东新区政府与中国东航签署深化合作战略协议。'},{type: '3',title: '标题三',auther: '张三  2024-01-10',imgsrc: 'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg',text: '本报讯(记者 杜晨薇)上海正在建设东方枢纽项目,浦东国际机场与沪通铁路将实现连通,枢纽周边临空产业、重点项目布局正在规划设计中。为落实上海市政府与中国东方航空集团有限公司(以下简称“中国东航”)合作协议要求,充分利用东方枢纽建设发展机遇期进一步深化合作发展,昨天下午,浦东新区政府与中国东航签署深化合作战略协议。'},{type: '4',title: '标题四',auther: '张三  2024-01-10',imgsrc: 'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg',text: '本报讯(记者 杜晨薇)上海正在建设东方枢纽项目,浦东国际机场与沪通铁路将实现连通,枢纽周边临空产业、重点项目布局正在规划设计中。为落实上海市政府与中国东方航空集团有限公司(以下简称“中国东航”)合作协议要求,充分利用东方枢纽建设发展机遇期进一步深化合作发展,昨天下午,浦东新区政府与中国东航签署深化合作战略协议。'},{type: '5',title: '标题五',auther: '张三  2024-01-10',imgsrc: 'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg',text: '本报讯(记者 杜晨薇)上海正在建设东方枢纽项目,浦东国际机场与沪通铁路将实现连通,枢纽周边临空产业、重点项目布局正在规划设计中。为落实上海市政府与中国东方航空集团有限公司(以下简称“中国东航”)合作协议要求,充分利用东方枢纽建设发展机遇期进一步深化合作发展,昨天下午,浦东新区政府与中国东航签署深化合作战略协议。'},]}},methods: {// wxml 转 canvasrenderToCanvas() {console.log('canvasStyle.widget', this.widget)const _wxml = wxml(this.listData);console.log('this.widget', _wxml)const _style = style(this.screenWidth, this.canvasWidth, this.canvasHeight) //this.canvasHeightconst p1 = this.widget.renderToCanvas({ wxml: _wxml, style: _style })console.log('renderToCanvas', p1)p1.then((res) => {console.log('海报生成成功', res);wx.hideLoading()}).catch((err) => {console.log('生成失败', err)})},// 保存到朋友圈extraImage() {if (!this.show) {wx.showToast({ title: '海报生成失败,无法分享到朋友圈', icon: 'none' })return}wx.showLoading({ title: '海报生成中...' })const p2 = this.widget.canvasToTempFilePath({ fileType:'jpg', quality :0.5})let that = this;p2.then(result => {let path = result.tempFilePathwx.getSetting({success: res => {wx.hideLoading()// 非初始化且未授权的情况,需要再次弹窗提示授权if (res.authSetting['scope.writePhotosAlbum'] != undefined && res.authSetting['scope.writePhotosAlbum'] != true) {wx.showModal({title: '是否授权相册权限',content: '需要获取相册权限,请确认授权,否则无法使用相关功能',success: res => {if (res.confirm) {wx.openSetting({success: dataAu => {if (dataAu.authSetting["scope.writePhotosAlbum"] == true) {wx.showToast({title: '授权成功',icon: 'none',duration: 1000});that.saveIMg(path);} else {wx.showToast({title: '授权失败',icon: 'success',duration: 1000});}}});}}});} else {// 初始化且未授权,系统默认会弹窗提示授权// 非初始化且已授权,也会进入这里that.saveIMg(path);}}});})},// 保存到相册async saveIMg(tempFilePath) {wx.saveImageToPhotosAlbum({filePath: tempFilePath,success: async (res) => {wx.showModal({content: '图片已保存,分享给好友吧!',showCancel: false,confirmText: '好的',confirmColor: '#333',success: function (res) {wx.navigateBack({//返回delta: 1});},fail: function (res) {console.log('res', res);}});},fail: function (res) {wx.showToast({title: '您取消了授权',icon: 'none',duration: 2000})}});},},onLoad(options) {console.log('options', options);// 获取设备信息wx.getSystemInfo({success: (res) => {console.log('屏幕',res)this.screenWidth = res.screenWidth;this.canvasWidth = this.screenWidth;this.canvasHeight = this.screenWidth * 8.5;console.log('海报高度:', this.canvasHeight)this.show = true// 数字容器宽度 动态设置 setTimeout(() => {wx.showLoading({ title: '海报加载中...' })this.widget = this.selectComponent('.widget')this.renderToCanvas()}, 1000)}});},
}</script><style lang="scss">
.share-page {background: #cc0202;position: relative;overflow: hidden;// padding: 10rpx;
//   min-height: 100vh;.msg-box {display: flex;align-items: center;text-align: center;justify-content: center;}.share-page-box {margin: 0 auto;position: relative;overflow: hidden;box-shadow: 0rpx 6rpx 20rpx 6rpx rgba(0, 0, 0, 0.2);}.share-page-btn {margin: 0 10rpx 0 10rpx;img {width: 100%;height: 100%;}}
}
</style>
  • DomData.js

/**** @param {*} listData  canvas数据*/export const wxml = (listData) => `
<view class="container">${listData.map(item=>{return `<view class="contentWrap"><view ><image src="`+ item.imgsrc + `"  class="pic1"/><text class="name">`+ item.title + `</text><text class="subtitle">`+ item.auther + `</text></view><view class="bottomcss"><image src="`+ item.imgsrc + `"  class="imgbc"/><view class="tapContent1"><text class="tapname">`+ item.text+`</text></view></view></view>`}).join('')}
</view>
`
/***** @param {*} screenWidth 屏幕宽度* @param {*} canvasWidth  画布宽度* @param {*} canvasHeight  画布高度* @param {*} numberWidth  数字宽度,动态设置* @return {*} */export const style = (screenWidth, canvasWidth, canvasHeight) => {return {"container": {width: canvasWidth,minHeight: canvasHeight,position:'relative',backgroundColor: '#ffffff',justifyContent: 'center',alignItems:'center',overflow: 'hidden'},"bottomcss":{marginTop: 0,},"contentWrap":{position: 'relative',width: canvasWidth * 0.99,marginBottom: 20,marginTop: 5,marginLeft: 1,borderRadius: 20,overflow:'hidden',backgroundColor: '#333333',},"imgbc":{justifyContent: 'center',alignItems: 'center',width: canvasWidth * 0.97,height: canvasWidth,marginBottom: 4,marginLeft: 4,marginTop: 10,borderRadius: 20,overflow: 'hidden',},"tapContent1":{position:'absolute',top: 0,left: 0,},"tapname":{fontSize: 18,color: '#fff',marginLeft: 15,marginTop: 50,overflow: 'hidden',width: canvasWidth * 0.92,height: 400,textAlign: 'left',},"name":{fontSize: 20,color: '#fff',marginLeft: canvasWidth * 0.08,width: canvasWidth * 0.84,height: 30,textAlign: 'center',},"subtitle":{fontSize: 14,color: '#9E9C9C',marginLeft: canvasWidth * 0.08,width: canvasWidth * 0.84,height: 20,textAlign: 'center',},"content": {fontSize: 14,color: '#333',width: canvasWidth * 0.84,height: screenWidth * 0.15,marginLeft: canvasWidth * 0.08,},"pic1": {width: canvasWidth * 0.3,height: screenWidth * 0.3,marginTop: canvasWidth * 0.1,marginLeft: canvasWidth * 0.35,marginBottom: canvasWidth * 0.05,borderRadius: screenWidth * 0.14,overflow: 'hidden',},"pic2": {width: canvasWidth ,height: canvasWidth ,marginTop:10,},"bottom":{width: canvasWidth,height: screenWidth * 0.2,flexDirection: 'row',justifyContent: 'self-start',alignItems: 'center',backgroundColor: '#fafafa',position: 'absolute',bottom: 0,left: 0,},"qr": {width: canvasWidth * 0.14,height: screenWidth * 0.14,marginLeft: canvasWidth * 0.04,marginRight: canvasWidth * 0.04,},"msg": {fontSize: 14,color: '#a1a1a1',width: canvasWidth * 0.74,height: 14,textAlign: 'left'},}
}

 


六、生成的效果图

 


...... 全 剧 终 ......

这篇关于uniapp使用wxml-to-canvas开发小程序保存canvas图片的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/592471

相关文章

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud