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

相关文章

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注

Python内置函数之classmethod函数使用详解

《Python内置函数之classmethod函数使用详解》:本文主要介绍Python内置函数之classmethod函数使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 类方法定义与基本语法2. 类方法 vs 实例方法 vs 静态方法3. 核心特性与用法(1编程客

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

ModelMapper基本使用和常见场景示例详解

《ModelMapper基本使用和常见场景示例详解》ModelMapper是Java对象映射库,支持自动映射、自定义规则、集合转换及高级配置(如匹配策略、转换器),可集成SpringBoot,减少样板... 目录1. 添加依赖2. 基本用法示例:简单对象映射3. 自定义映射规则4. 集合映射5. 高级配置匹

Spring 框架之Springfox使用详解

《Spring框架之Springfox使用详解》Springfox是Spring框架的API文档工具,集成Swagger规范,自动生成文档并支持多语言/版本,模块化设计便于扩展,但存在版本兼容性、性... 目录核心功能工作原理模块化设计使用示例注意事项优缺点优点缺点总结适用场景建议总结Springfox 是

嵌入式数据库SQLite 3配置使用讲解

《嵌入式数据库SQLite3配置使用讲解》本文强调嵌入式项目中SQLite3数据库的重要性,因其零配置、轻量级、跨平台及事务处理特性,可保障数据溯源与责任明确,详细讲解安装配置、基础语法及SQLit... 目录0、惨痛教训1、SQLite3环境配置(1)、下载安装SQLite库(2)、解压下载的文件(3)、

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图