当前位置: 首页 > 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…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...