当前位置: 首页 > news >正文

微信小程序-生成canvas图片并保存到手机相册

wxml页面

<button class="rightbtn bottomBtnCss"  catch:tap="canvasImg"><image src='{{imgUrl}}/images/mine/jspj-icon.png' class="restNumImg"></image><text class="btnText">生成图片</text></button>
<!-- 生成图片弹框 -->
<view class="wx-dialog_wrapper "  wx:if="{{isShowCanvas}}" ><view class="wx-dialog wx-dialogwidth80"><view class="wx-dialog_body"><view class="canvasWrap"><canvas type="2d" id='posterCanvas' style="width: 100%;height: 1000rpx;"></canvas></view><button class="rightbtn bottomBtnCss"  catch:tap="saveImg"><image src='{{imgUrl}}/images/mine/jspj-icon.png' class="restNumImg"></image><text class="btnText">保存图片</text></button></view></view>
</view>

wxss页面

.wx-dialogwidth80{width:80%;
}
#posterCanvas {margin: 0 auto;
}
.canvasWrap {
margin: 10px auto;
text-align: center;
}

js代码

const app = getApp()
Page({/*** 页面的初始数据*/data: {imgUrl: app.globalData.imgUrl,//线上图片路径totalCnt: '',isSaveCanvas: false,},/*** 生命周期函数--监听页面加载*/onLoad(options) {let totalCnt = wx.getStorageSync('totalCnt')this.setData({totalCnt: totalCnt || '0.00'})},// 重新计算restClick() {wx.navigateTo({url: '../../index'})},/*** 用户点击右上角分享*/onShareAppMessage() {},// 关闭showVipDialogClose() {this.setData({isShowCanvas: false})},canvasImg() {this.setData({isShowCanvas: true})// wx.showLoading({//   title: '海报生成中...',// })let _this = this//选取画板const query = wx.createSelectorQuery()query.select('#posterCanvas').fields({node: true,size: true}).exec(async (res) => {const canvas = res[0].node;const ctx = canvas.getContext('2d');const dpr = wx.getSystemInfoSync().pixelRatio //手机分辨率 为了使保存到相册的图片清晰canvas.width = res[0].width * dprcanvas.height = res[0].height * dprconsole.log('dpr', dpr);ctx.clearRect(0, 0, 320, 410); //清空画板ctx.fillStyle = '#fff';ctx.fillRect(0, 0, 320, 410);// 1.背景图const image = canvas.createImage();image.src = this.data.imgUrl + "/images/carbonEmissionImages/排放总量背景.png";;let bgImg = await new Promise((resolve, reject) => {image.onload = () => {resolve(image)}image.onerror = (e) => {reject(e)}});ctx.drawImage(bgImg, 0, 0, canvas.width, canvas.height);// 2.头部文字 在背景图上作画// 设置文字样式ctx.font = "700 36px sans-serif";ctx.fillStyle = "#fff";ctx.textAlign = "center" //居中是以文字设定的x轴( canvas.width/2)为中心点// 添加文字ctx.fillText("我在ESGPRO上测了企业碳排放总量", canvas.width / 2, 200);// 3.画中心圆图const image1 = canvas.createImage();image1.src = this.data.imgUrl + "/images/carbonEmissionImages/tco2背景.png";;let bgImgPo = await new Promise((resolve, reject) => {image1.onload = () => {resolve(image1)}image1.onerror = (e) => {reject(e)}});ctx.drawImage(bgImgPo, 0.5 * (canvas.width - 400), 0.5 * (canvas.height - 800), 400, 400);// 4.圆圈内文字 在背景图上作画// // 设置文字样式ctx.font = "700 36px sans-serif";ctx.fillStyle = '#00bf5b'; //文字颜色:默认黑色ctx.textAlign = "center"ctx.fillText(_this.data.totalCnt, canvas.width / 2, 0.5 * (canvas.height - 400)) //绘制文本// 设置文字样式ctx.font = "28px sans-serif";ctx.fillStyle = "#bdbdbd";ctx.textAlign = "center" //居中是以文字设定的x轴( canvas.width/2)为中心点// 添加文字ctx.fillText('tCO2', canvas.width / 2, 0.5 * (canvas.height - 300));// 5.小程序二维码let image2 = canvas.createImage();// image2.src = this.data.imgUrl + '/images/carbonEmissionImages/COimg.jpg'; // 引入本地图片image2.src = '../../images/COimg.jpg'; // 引入本地图片image2.onload = function () {ctx.drawImage(image2, 0.5 * (canvas.width - 300), 0.5 * (canvas.height + 400), 300, 300);// 6.添加文字// 设置文字样式ctx.font = "24px sans-serif";ctx.fillStyle = "#999999";ctx.textAlign = "center" //居中是以文字设定的x轴( canvas.width/2)为中心点// 添加文字ctx.fillText('微信扫码或搜索ESGPRO', canvas.width / 2, 0.5 * (canvas.height + 1100));ctx.font = "24px sans-serif";ctx.fillStyle = "#999999";ctx.textAlign = "center" //居中是以文字设定的x轴( canvas.width/2)为中心点// 添加文字ctx.fillText('即可免费使用碳排放计算器', canvas.width / 2, 0.5 * (canvas.height + 1200));}})},async saveImg() {let _this = this;const query = wx.createSelectorQuery();const canvasObj = await new Promise((resolve, reject) => {query.select('#posterCanvas').fields({node: true,size: true}).exec(async (res) => {resolve(res[0].node);})});wx.canvasToTempFilePath({canvas: canvasObj, //现在的写法success: (res) => {console.log(res);_this.setData({isShowCanvas: false});//保存图片wx.saveImageToPhotosAlbum({filePath: res.tempFilePath,success(res) {wx.hideToast();wx.showModal({title: '图片保存成功',content: '图片成功保存到相册了',showCancel: false,confirmText: '好哒',confirmColor: '#5096cd',success: function (res) {if (res.confirm) {console.log('用户点击确定');}}})},fail(err) {wx.hideToast()if (err.errMsg === "saveImageToPhotosAlbum:fail:auth denied" ||err.errMsg === "saveImageToPhotosAlbum:fail auth deny" ||err.errMsg === "saveImageToPhotosAlbum:fail authorize no response") {wx.showModal({title: '提示',content: '需要您授权保存相册',showCancel: false,success: res => {wx.openSetting({success(res) {if (settingdata.authSetting['scope.writePhotosAlbum']) {wx.showModal({title: '提示',content: '获取权限成功,再次点击即可保存',showCancel: false,})} else {wx.showModal({title: '提示',content: '获取权限失败,将无法保存到相册哦~',showCancel: false,})}},fail(err) {console.log("fail", err)},complete(res) {console.log("finish", res)}})}})} else if (err.errMsg === "saveImageToPhotosAlbum:fail cancel") {wx.showModal({title: '提示',content: '取消了保存图片,再次点击下载即可保存',showCancel: false,})} else {wx.showModal({title: '提示',content: err.errMsg,showCancel: false,})}}})},fail(err) {wx.showToast({title: '保存失败,稍后再试',duration: 2000,icon: 'none'});}}, this)},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},})

相关文章:

微信小程序-生成canvas图片并保存到手机相册

wxml页面 <button class"rightbtn bottomBtnCss" catch:tap"canvasImg"><image src{{imgUrl}}/images/mine/jspj-icon.png class"restNumImg"></image><text class"btnText">生成图片</text></but…...

设计模式8:代理模式-动态代理

上一篇&#xff1a;设计模式8&#xff1a;代理模式-静态代理 目录 如何理解“动态”这两个字&#xff1f;动态代理简单的代码实例一个InvocationHandler代理多个接口有动态代理&#xff0c;为什么还要用Cglib代理&#xff1f; 如何理解“动态”这两个字&#xff1f; “动态”…...

tcp字节传输(java)-自定义包头和数据识别

1、背景 tcp传输的时候会自动拆包&#xff0c;因此服务端接收的数据段可能跟客户端发送过来的数据段长度不一致&#xff0c;比如客户端一次发送10000个字节。但是服务端接收了两次才接收完整&#xff08;例如第一次接收6000字节&#xff0c;第二次接收4000字节&#xff09;。但…...

pyspark 系统找不到指定的路径; \Java\jdk1.8.0_172\bin\java

使用用具PyCharm 2023.2.1 1&#xff1a;pyspark 系统找不到指定的路径&#xff0c; Java not found and JAVA_HOME environment variable is not set. Install Java and set JAVA_HOME to point to the Java installation directory. 解决方法&#xff1a;配置正确环境变量…...

UE4 Physics Constraint Actor 实现钟摆效果

放入场景&#xff0c;然后将一个球体放入场景 选择小球 将小球改为Movable 选择模拟物理&#xff0c;并将小球移除平衡点 就实现了...

UE4/UE5 动画控制

工程下载​ ​​​​​​​​​​​​​https://mbd.pub/o/bread/ZJ2cm5pu 蓝图控制sequence播放/倒播动画&#xff1a; 设置开启鼠标指针&#xff0c;开启鼠标事件 在场景中进行过场动画制作 设置控制事件...

Springboot整合shiro

导入依赖 <!-- 引入springboot的web项目的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency> ​ <!-- shiro --><depende…...

阻塞/非阻塞、同步/异步(网络IO)

1.阻塞/非阻塞、同步/异步(网络IO) 【思考】典型的一次 IO 的两个阶段是什么&#xff1f; 数据就绪 和 数据读写 数据就绪 &#xff1a;根据系统 IO 操作的就绪状态 阻塞 非阻塞 数据读写 &#xff1a;根据应用程序和内核的交互方式 同步 异步 陈硕&#xff1a;在处理 IO …...

为什么大家会觉得考PMP没用?

一是在于PMP这套知识体系&#xff0c;是一套底层的项目管理逻辑框架&#xff0c;整体是比较抽象的。大家在学习工作之后&#xff0c;会有人告诉你很多职场的一些做事的规则&#xff0c;比如说对于沟通&#xff0c;有人就会告诉如何跟客户沟通跟同事相处等等&#xff0c;这其实就…...

AVR128单片机 USART通信控制发光二极管显示

一、系统方案 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 void port_init(void) { PORTA 0xFF; DDRA 0x00;//输入 PORTB 0xFF;//低电平 DDRB 0x00;//输入 PORTC 0xFF;//低电平 DDRC 0xFF;//输出 PORTE 0xFF; DDRE 0xfE;//输出 PO…...

为什么5G 要分离 CU 和DU?(4G分离RRU 和BBU)

在 Blog 一文中&#xff0c;5G--BBU RRU 如何演化到 CU DU&#xff1f;_5g rru_qq_38480311的博客-CSDN博客 解释了4G的RRU BBU 以及 5G CU DU AAU&#xff0c;主要是讲了它们分别是什么。但是没有讲清楚 为什么&#xff0c;此篇主要回答why。 4G 为什么分离基站为 RRU 和 BBU…...

Python中的数据输入

获取键盘输入 input语句 使用input()可以从键盘获取输入&#xff0c;使用一个变量来接收 print("你是谁&#xff1f;") name input() print(f"我知道了&#xff0c;你是{name}")# print("你是谁&#xff1f;") name input("你是谁&…...

cms系统稳定性压力测试出现TPS抖动和毛刺的性能bug【杭州多测师_王sir】

一、并发线程数100&#xff0c;分10个阶梯&#xff0c;60秒加载时间&#xff0c;运行1小时进行压测&#xff0c;到10分钟就出现如下 二、通过jstat -gcutil 16689 1000进行监控...

【UE】材质描边、外发光、轮廓线

原教学视频链接&#xff1a; ue4 材质描边、外发光、轮廓线_哔哩哔哩_bilibili 步骤 1. 首先新建一个材质&#xff0c;这里命名为“Mat_outLine” 在此基础上创建一个材质实例 2. 在视口中添加一个后期处理体积 设置后期处理体积为无限范围 点击添加一个数组 选择“资产引用”…...

百模大战,打响AI应用生态的新赛点

点击关注 文&#xff5c;郝鑫 黄小艺&#xff0c;编&#xff5c;刘雨琦 “宇宙中心”五道口&#xff0c;又泛起了昔日的光芒。 十字路口一角的华清嘉园里&#xff0c;各种互联网大佬们&#xff0c;王兴、程一笑、张一鸣等人的创业传说似乎还有余音&#xff0c;后脚搬进来的AI…...

【C++二叉树】进阶OJ题

【C二叉树】进阶OJ题 目录 【C二叉树】进阶OJ题1.二叉树的层序遍历II示例代码解题思路 2.二叉搜索树与双向链表示例代码解题思路 3.从前序与中序遍历序列构造二叉树示例代码解题思路 4.从中序与后序遍历序列构造二叉树示例代码解题思路 5.二叉树的前序遍历&#xff08;非递归迭…...

C++——vector:resize与reserve的区别,验证写入4GB大数据时相比原生操作的效率提升

resize和reserve的区别 reserve&#xff1a;预留空间&#xff0c;但不实例化元素对象。所以在没有添加新的对象之前&#xff0c;不能引用容器内的元素。而要通过调用push_back或者insert。 resize&#xff1a;改变容器元素的数量&#xff0c;且会实例化对象&#xff08;指定或…...

基础配置xml

# 配置端口 server.port8081# 文件上传配置 # 是否支持文件上传 spring.servlet.multipart.enabledtrue # 是否支持文件写入磁盘 spring.servlet.multipart.file-size-threshold0 # 上传文件的临时目录 spring.servlet.multipart.locationd:/opt/tmp # 最大支持上传文件大小 sp…...

win环境安装SuperMap iserver和配置许可

SuperMap iServer是我国北京超图公司研发的基于跨平台GIS内核的云GIS应用服务器产品&#xff0c;通过服务的方式&#xff0c;面向网络客户端提供与专业GIS桌面产品相同功能的GIS服务&#xff0c;能够管理、发布多源服务&#xff0c;包括REST服务、OGC服务等。 SuperMap iserve…...

【Apollo学习笔记】——规划模块TASK之PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER(一)

文章目录 TASK系列解析文章前言PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER功能介绍PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER相关配置PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER流程确定优化变量定义目标函数定义约束ProcessSetUpStatesAndBoundsOptimizeByQPCheckSpeedLimitF…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...