微信小程序-生成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() {},})

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

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

相关文章

算法笔记——路径问题

在引入介绍如何写一个算法的时候&#xff0c;我们先引入一个题作为例子 1137. 第 N 个泰波那契数 - 力扣&#xff08;LeetCode&#xff09; 作为刚开始学习算法的我们&#xff0c;看到这个题目的时候&#xff0c;应该想好以下的问题&#xff1a; 1.状态表示 我们要用什么来表…

Windows7安装SSH客户端的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

SQL sever中库管理

目录 一、创建数据库 1.1库界面方式 1.2SQL命令方式 二、修改数据库 2.1库界面方式 2.2SQL命令方式 三、删除数据库 3.1库界面方式 3.2SQL命令方式 四、附加和分离数据库 4.1附加和分离数据库概述 4.2作用 4.3附加和分离数据库方法 4.4示例 一、创建数据库 1.1库…

第 3 章 栈和队列 (循环队列)

1. 背景说明 和顺序栈相类似&#xff0c;在队列的顺序存储结构中&#xff0c;除了用一组地址连续的存储单元依次存放从队列头到队列尾的元素之外&#xff0c; 尚需附设两个指针 front 和 rear 分别指示队列头元素及队列尾元素的位置。约定&#xff1a;初始化建空队列时&#x…

力扣:81. 搜索旋转排序数组 II(Python3)

题目&#xff1a; 已知存在一个按非降序排列的整数数组 nums &#xff0c;数组中的值不必互不相同。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转 &#xff0c;使数组变为 [nums[k], nums[k1], .…

XmlDocument.SelectNodes 不起作用

今天采用Xpath读取Xml节点&#xff0c;怎么都读不出。 问题分析&#xff1a; 错误代码如下&#xff1a; XmlDocument xmlD new XmlDocument();xmlD.PreserveWhitespace true;xmlD.LoadXml(xStr);xmlD.SelectNodes("job-scheduling-data/schedule/job");经排查 do…

Python学习笔记——从面试题出发学习Python

Python学习笔记——从面试题出发学习Python Python学习笔记——从面试题出发学习Python1. 可变数据类型与不可变数据类型&#xff0c;深拷贝与浅拷贝&#xff0c;函数参数的传递机制1.1 变量与对象1.2 可变数据类型与不可变数据类型1.3 深拷贝与浅拷贝1.4 函数参数的传递机制1.…

element-plus的周选择器 一周从周一开始

1、代码 1&#xff09;、template中 <el-date-picker v-model"value1" type"week" format"[Week] ww" placeholder"巡访周" change"change"value-format"YYYY-MM-DD" /> 2&#xff09;、方法中 import…

Matlab(画图初阶)

目录 1.plot()函数 2. hold(添加新绘图是否保留旧绘图) 3. Plot Style 3.1 线型 3.2 标记 3.3 颜色 ​编辑 4. legend() 5.X 、Y and Title&#xff1f; 6. Text()和annotation() 7.line(创建基本线条) 7.1 基本语法 7.2 指定线条属性 7.3 更改线条属性 8.图像属性 8.1 …

c++入门一

参考&#xff1a;https://www.learncpp.com/cpp-tutorial/ When you finish, you will not only know how to program in C, you will know how NOT to program in C, which is arguably as important. Tired or unhappy programmers make mistakes, and debugging code tends…

软考高级架构师——6、软件架构设计

像学写文章一样&#xff0c;在学会字、词、句之后&#xff0c;就应上升到段落&#xff0c;就应追求文章的“布局谋 篇”&#xff0c;这就是架构。通俗地讲&#xff0c;软件架构设计就是软件系统的“布局谋篇”。 人们在软件工程实践中&#xff0c;逐步认识到了软件架构的重要性…

HarmonyOS Codelab 优秀样例——购物应用,体验一次开发多端部署魅力

一. 样例介绍 本篇Codelab基于自适应布局和响应式布局&#xff0c;实现购物应用在手机、折叠屏、平板不同屏幕尺寸设备上按不同设计显示。通过三层工程结构组织代码&#xff0c;实现一次开发&#xff0c;多端部署 。 手机运行效果如图所示&#xff1a; 折叠屏运行效果图&#x…

C语言:大小端字节序存储

一、大小端字节序存储介绍 大端字节序存储模式&#xff1a;把一个数据低位字节处的数据存放在高地址处&#xff0c;数据高位字节处的数据存放在低地址处 小端字节序存储模式&#xff1a;把一个数据低位字节处的数据存放在低地址处&#xff0c;数据高位字节处的数据存放在高地址…

MATLAB中isequal函数转化为C语言

背景 有项目算法使用matlab中isequal函数进行运算&#xff0c;这里需要将转化为C语言&#xff0c;从而模拟算法运行&#xff0c;将算法移植到qt。 MATLAB中isequal简单介绍 语法 tf isequal(A,B) tf isequal(A1,A2,...,An) 说明 如果 A 和 B 等效&#xff0c;则 tf is…

C++ 信号处理

信号是由操作系统传给进程的中断&#xff0c;会提早终止一个程序。在 UNIX、LINUX、Mac OS X 或 Windows 系统上&#xff0c;可以通过按 CtrlC 产生中断。 有些信号不能被程序捕获&#xff0c;但是下表所列信号可以在程序中捕获&#xff0c;并可以基于信号采取适当的动作。这些…

【Python】PySpark 数据计算 ⑤ ( RDD#sortBy方法 - 排序 RDD 中的元素 )

文章目录 一、RDD#sortBy 方法1、RDD#sortBy 语法简介2、RDD#sortBy 传入的函数参数分析 二、代码示例 - RDD#sortBy 示例1、需求分析2、代码示例3、执行结果 一、RDD#sortBy 方法 1、RDD#sortBy 语法简介 RDD#sortBy 方法 用于 按照 指定的 键 对 RDD 中的元素进行排序 , 该方…

用 ChatGPT 写代码太省时间了

几个月前&#xff0c;我们聊过陶哲轩使用 ChatGPT 辅助解决数学问题。当时&#xff0c;他觉得虽然测试结果不太令人满意&#xff0c;但也并没有对 ChatGPT 持完全否定的态度。他觉得&#xff0c;像 ChatGPT 这类大型语言模型在数学中可以用来做一些半成品的语义搜索工作&#x…

(超简单)将图片转换为ASCII字符图像

将一张图片转换为ASCII字符图像 原图&#xff1a; 效果图&#xff1a; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileWriter; import java.io.IOException;public class ImageToASCII {/*** 将图片转换为A…

保姆级教程之SABO-VMD-SVM的西储大学轴承诊断

之前写过一篇优化核极限学习机的轴承诊断&#xff0c;今天再出一期基于SVM的轴承诊断。 依旧是包含了从数据处理&#xff0c;到减法优化器SABO算法优化VMD参数&#xff0c;再到支持向量机的故障诊断&#xff0c;实现故障诊断的全流程&#xff0c;其他类型的故障诊断均可参考此流…

阿里云对象存储oss-文件上传过程详解(两种方式)

阿里云对象存储oss-文件上传过程详解{两种方式} 方式一(最新代码,时间:2023/8/27)(1)如何配置系统变量(2)完整代码 方式二(跟黑马最新教程同代码)(1)在复制下来的代码中(2)完整代码 方式一(最新代码,时间:2023/8/27) 问题:需要配置系统变量才能够使用 (1)如何配置系统变量 以wi…