uniapp生成自定义(分享)图片并保存到相册

需求描述

在这里插入图片描述
在一个页面中底部有个保存图片的功能,点击能够保存一张生成的自定义表格图片。
第一眼见到这个需求 自己会出现了两个问题

  1. 如何去处理图片中的自定义内容以及样式
  2. 如何将自定义内容转化成图片
    至于保存图片,uniapp有对应的api去实现uni.saveImageToPhotosAlbum,不做赘述

实现效果展示

请添加图片描述
下面就是生成的图片在这里插入图片描述

实现步骤

大致划分成以下几个步骤
1、需要在目标页面画出图片内容的html代码,并置于于屏幕可视区域外形成隐藏的效果(不是display:none隐藏元素)
2、需要将html转成canvas的形式,再通过toDataURL方法转成base64图片形式
3、将base64转换成临时图片路径,即可展示出,并下载

已知需要用到两个插件来帮助实现
一个是html转canvas的插件 html2canvas可通过npm下载

npm install html2canvas -D

一个是将base64图片格式转本地地址的Dcloud插件image-tools

1、画需要生成图片的元素

即就是生成图片的样式 还是需要我们自己来搞出来。可以封装成一个组件形式,这里就不贴代码,因为这不是核心逻辑,况且大家需要生成图片的样式都不一样,唯一需要注意的是,这块元素是要脱离文档流,并置于屏幕外,不让用户看到

将生成图片的代码封装成一个组件,如下 需要声明一个id 为后续转canvas做准备

<KitcalculatorTable id="pagePoster"/>

并将这块区域通过固定定位置于可视区外,这样就看不到了,不能用v-if或者v-show、display:none去隐藏,这样在后续html转canvas是失败的,无法获取到该区域元素

position: fixed;
top: -999999rpx;
background-color: #fff;
padding: 30rpx;

2将html转成canvas的形式,再转成base64图片形式

<template><view class="html2Canvas" id="pagePoster"><view class="table"><view class="kitCalculatorName">{{ pageData.kitCalculatorName }}</view><KitcalculatorTable :tableData="tableData" :isSumData="true" /><view class="average-data"><view style="margin-right: 50rpx">件套平均价格:{{ pageData.averagePriceOneDesc }}</view><view v-if="visiblePrice2">平均价格2:{{ pageData.averagePriceTwoDesc }}</view></view></view><view class="bottom-logo"><img class="code" :src="codeImage" /><view><view class="">报盘计算器,长按识别二维码使用</view><img class="logo" :src="logoImage" /></view></view></view><view class="muji-button" style="margin: 0 24rpx" @click="canvasImage.generateImageSave">保存图片</view><view class="muji-button" @click="canvasImage.generateImageShare">分享</view>
</template>
<script lang="renderjs" module="canvasImage">
import html2canvas from 'html2canvas'
export default {mounted() {},methods: {generateImageSave(){this.generateImage('save')},generateImageShare(){this.generateImage('share')},// 生成图片需要调用的方法generateImage(methodType) {this.$ownerInstance.callMethod('openLoading', '正在生成图片~')setTimeout(() => {const dom = document.getElementById('pagePoster') // 需要生成图片内容的 dom 节点html2canvas(dom, {width: dom.clientWidth, //dom 原始宽度height: dom.clientHeight,scrollY: 0, // html2canvas默认绘制视图内的页面,需要把scrollY,scrollX设置为0scrollX: 0,useCORS: true, //支持跨域// scale: 2, // 设置生成图片的像素比例,默认是1,如果生成的图片模糊的话可以开启该配置项}).then((canvas) => {// 生成成功// html2canvas 生成成功的图片链接需要转成 base64位的urlthis.$ownerInstance.callMethod('receiveRenderData',canvas.toDataURL('image/png'))}).catch(err=>{this.$ownerInstance.callMethod('_errAlert',`【生成图片失败,请重试】${err}`)})}, 300)},}
}
</script>
<script>
import { pathToBase64,base64ToPath} from 'image-tools';
export default {props: {pageData: {type: Object,default: () => {return {};},},},data() {return {temUrl: '', //生成的临时路径图片codeImage: '', // 件套二维码图片logoImage: '', // logo图片};},created() {// 处理静态图片 转为base64this.actionImage();},methods: {// 处理已知静态图片 转base64格式actionImage() {this.turnBase64Image(require('@/static/logo/down-code.png'), 'codeImage');this.turnBase64Image(require('@/static/logo/muji-logo.png'), 'logoImage');},// 将图片转为base 64 位urlturnBase64Image(img, key) {uni.getImageInfo({src: img,success: (image) => {pathToBase64(image.path).then((base64) => {this[key] = base64;}).catch((error) => {console.log('转换失败:', error);});},fail: (err) => {console.log('将本地图片转为base 64报错:', err);},});},/* 将base64 位的图片路径转换为 临时路径 */loadBase64Url(imageStr) {const that = this;base64ToPath(imageStr).then((path) => {this.temUrl = path;this.closeLoading()this.saveImg()}).catch((error) => {console.error('临时路径转换出错了:', error);});},// 获取生成的base64 图片路径receiveRenderData(val) {const url = val.replace(/[\r\n]/g, ''); // 去除base64位中的空格this.loadBase64Url(url);},// 报错alert_errAlert(content) {uni.showModal({title: '提示',content: content,});},saveImg() {uni.saveImageToPhotosAlbum({filePath: this.temUrl,success: function () {uni.showToast('保存图片成功');}});},},
};
</script>

需要注意的两点是,这里要新建一个script节点,将语言改成renderjs的形式 在这之内做html转canvas的操作
再就是需要把生成图片中的已知静态图片 如下载二维码、企业logo转换成base64的形式

保存图片

最后就是点击保存后,调用canvasImage下的generateImage去生成图片,拿到base64格式图片通过image-tools的base64ToPath方法去转成临时路径再下载就ok了

题外话

这里涉及到renderjs的通讯知识,还是有点坑的
比如在renderjs模块调用script的方法是可以直接

this.$ownerInstance.callMethod('script内方法名',需要带的参数)

目前只了解可以在dom去调用renderjs方法,在script内貌似不能直接用。大家就要根据需求去灵活使用这个东西

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/143822.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小样本目标检测(Few-Shot Object Detection)综述

背景 前言:我的未来研究方向就是这个,所以会更新一系列的文章,就关于FSOD,如果有相同研究方向的同学欢迎沟通交流,我目前研一,希望能在研一发文,目前也有一些想法,但是具体能不能实现还要在做的过程中慢慢评估和实现.写文的主要目的还是记录,避免重复劳动,我想用尽量简洁的语言…

【移远QuecPython】EC800M物联网开发板的MQTT协议腾讯云数据上报

【移远QuecPython】EC800M物联网开发板的MQTT协议腾讯云数据上报 文章目录 导入库初始化设置MQTT注册回调订阅发布功能开启服务发送消息函数打包调用测试效果附录&#xff1a;列表的赋值类型和py打包列表赋值BUG复现代码改进优化总结 py打包 导入库 from TenCentYun import TX…

Clickhouse学习笔记(15)—— Clickhouse备份

手动备份 参考官网&#xff1a;Backup and Restore | ClickHouse Docs 简单来说&#xff0c;就是我们可以通过ALTER TABLE ... FREEZE PARTITION ...命令为表分区创建一个本地副本&#xff0c;然后这个副本硬链接到/var/lib/clickhouse/shadow/文件夹&#xff0c;因此其不会耗…

Unity性能优化分析篇

性能优化是游戏项目开发中一个重要环节。游戏帧率过低&#xff0c;手机发烫&#xff0c; 包体太大&#xff0c;低端机上跑不起来等, 这些都需要来做优化&#xff0c;不管过去&#xff0c;现在&#xff0c;未来&#xff0c;性能优化都是永恒的话题。 而性能优化首先要掌握的是性…

BIO、NIO、AIO三者的区别及其应用场景(结合生活例子,简单易懂)

再解释三者之前我们需要先了解几个概念&#xff1a; 阻塞、非阻塞&#xff1a;是相较于线程来说的&#xff0c;如果是阻塞则线程无法往下执行&#xff0c;不阻塞&#xff0c;则线程可以继续往下 执行。同步、异步&#xff1a;是相较于IO来说的&#xff0c;同步需要等待IO操作完…

Outlook邮件视图设置怎么修复

故障现象 Outlook邮箱显示不对 故障截图 故障原因 邮箱视图设置不对 解决方案 1、在Outlook上方工具栏找到视图按钮&#xff0c;以此选择视图→视图设置→列&#xff0c;打开选择的列 2、在视图→邮件预览里面&#xff0c;选择1行&#xff0c;在阅读格式选择靠右&#xff…

AI创作系统ChatGPT网站源码+支持最新GPT-Turbo模型+支持DALL-E3文生图/AI绘画源码

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

Nodejs操作缓存数据库-Redis

Hi I’m Shendi Nodejs专栏 Nodejs操作缓存数据库-Redis 在服务端开发中&#xff0c;缓存数据库也是不可或缺的&#xff0c;可以提高程序并发以及方便后续扩展&#xff0c;而目前最常用的莫过于Redis了 安装依赖 和之前的mysql一样&#xff0c;redis的依赖最常用的就是redis …

自学SLAM(8)《第四讲:相机模型与非线性优化》作业

前言 小编研究生的研究方向是视觉SLAM&#xff0c;目前在自学&#xff0c;本篇文章为初学高翔老师课的第四次作业。 文章目录 前言1.图像去畸变2.双目视差的使用3.矩阵微分4.高斯牛顿法的曲线拟合实验 1.图像去畸变 现实⽣活中的图像总存在畸变。原则上来说&#xff0c;针孔透…

51单片机应用从零开始(三)

51单片机应用从零开始&#xff08;一&#xff09;-CSDN博客 51单片机应用从零开始&#xff08;二&#xff09;-CSDN博客 详解 KEIL C51 软件的使用建立工程-CSDN博客 详解 KEIL C51 软件的使用设置工程编绎与连接程序-CSDN博客 目录 1. 用单片机控制第一个灯亮 2. 认识单片…

leetcode:476. 数字的补数

一、题目 476. 数字的补数 - 力扣&#xff08;LeetCode&#xff09; 函数原型&#xff1a; int findComplement(int num) 二、思路 将num的每一位取出来&#xff0c;取反后&#xff0c;乘以2的位次方&#xff0c;最终所有结果相加即可得到结果。 如何取出num的每一位&#xff1…

<MySQL> 查询数据进阶操作 -- 联合查询

目录 一、什么是笛卡尔积&#xff1f; 二、什么是联合查询&#xff1f; 三、内连接 3.1 简介 3.2 语法 3.3 更多的表 3.4 操作演示 四、外连接 4.1 简介 4.2 语法 4.3 操作演示 五、自连接 5.1 简介 5.2 自连接非必要不使用 六、子查询(嵌套查询) 6.1 简介 6.…

电源电压范 围宽、功耗小、抗干扰能力强的国产芯片GS069适用于电动工具等产品中,采用SOP8的封装形式封装

GS069电动工具直流调速电路是CMOS专用集成电路&#xff0c;具有电源电压范 围宽、功耗小、抗干扰能力强等特点。通过外接电阻网络&#xff0c;改变与之相接 的VMOS 管的输出&#xff0c;达到控制电动工具转速的作用。该电路输出幅值宽&#xff0c; 频率变化小&#xff0c;占空比…

自己动手实现一个深度学习算法——六、与学习相关的技巧

文章目录 1.参数的更新1&#xff09;SGD2&#xff09;Momentum3&#xff09;AdaGrad4&#xff09;Adam5&#xff09;最优化方法的比较6&#xff09;基于MNIST数据集的更新方法的比较 2.权重的初始值1&#xff09;权重初始值不能为02&#xff09;隐藏层的激活值的分布3&#xff…

04-学成在线之系统管理服务模块之查询数据字典表中的内容,前后端联调测试

前后端联调 配置前端环境 实际开发中先由后端工程师将接口设计好并编写接口文档并交给前端工程师&#xff0c;前后端的工程师就开始并行开发 前端开发人员先自己mock数据即使用假数据进行开发,当后端代码完成后前端工程师尝试请求后端接口获取数据然后渲染到页面 第一步: 首…

计算机网络之物理层

物理层 1. 物理层的基本概念 2.物理层下面的传输媒体 传输媒体可分为两类&#xff0c;一类是导引型传输媒体&#xff0c;另一类是非导引型传输媒体。 3.传输方式 3.1 串行传输和并行传输 串行传输&#xff1a;串行传输是指数据是一个比特依次发送的&#xff0c;因此在发送端…

C/C++轻量级并发TCP服务器框架Zinx-框架开发002: 定义通道抽象类

文章目录 2 类图设计3 时序图数据输入处理&#xff1a;输出数据处理总流程 4 主要实现的功能4.1 kernel类&#xff1a;基于epoll调度所有通道4.2 通道抽象类&#xff1a;4.3 标准输入通道子类4.4 标准输出通道子类4.5 kernel和通道类的调用 5 代码设计5.1 框架头文件5.2 框架实…

wx.canvasToTempFilePath生成图片保存到相册

微信小程序保存当前画布指定区域的内容导出生成指定大小的图片&#xff0c;记录一下 api&#xff1a;wx.canvasToTempFilePath 效果&#xff1a; 代码&#xff1a;wxml <canvas style"width: {{screenWidth}}px; height: {{canvasHeight}}px;" canvas-id"my…

2023.11.15 每日一题(AI自生成应用)【C++】【Python】【Java】【Go】 动态路径分析

目录 一、题目 二、解决方法 三、改进 一、题目 背景&#xff1a; 在一个城市中&#xff0c;有数个交通节点&#xff0c;每个节点间有双向道路相连。每条道路具有一个初始权重&#xff0c;代表通行该路段的成本&#xff08;例如时间、费用等&#xff09;。随着时间的变化&am…

CentOS修改root用户密码

一、适用场景 1、太久没有登录CentOS系统&#xff0c;忘记管理密码。 2、曾经备份的虚拟化OVA或OVF模板&#xff0c;使用模板部署新系统后&#xff0c;忘记root密码。 3、被恶意攻击修改root密码后的紧急修复。 二、实验环境 1、VMware虚拟化的ESXI6.7下&#xff0c;通过曾经…