热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

小程序canvas绘图并保存到系统相册

开始实现之前先上个效果图tips网络图片需先配置download域名,可通过wx.getImageInfo转为临时路径;个人习惯问题,我习

开始实现之前先上个效果图

tips

  1. 网络图片需先配置download域名,可通过wx.getImageInfo转为临时路径;
  2. 个人习惯问题,我习惯使用async-await语法,所以需要引入regenerator这个库,使用方式可网上查。

一、封装通用微信api返回为Promise对象

/datas/common.js

// 封装获取微信图片信息。
export const getWxImageInfo = (imgPath) => {return new Promise((resolve, reject) => {wx.getImageInfo({src: imgPath,success: res => {resolve(res)},fail: res => {reject(res)}})})
}// 封装获取节点选择器信息
export const getSelectQurey = (queryStr) => {return new Promise(resolve => {var query = wx.createSelectorQuery();query.select(queryStr).boundingClientRect();query.exec(res => {resolve(res)})})
}// 封装把画布导出生成指定大小的图片
export const canvasToTempFilePath = (width, height, canvasId, fileType = 'jpg') => {return new Promise((resolve, reject) => {wx.canvasToTempFilePath({width,height,canvasId,fileType,success: res => {resolve(res)},fail: res => {reject(res)}})})
}// 封装保存图片到系统相册
export const saveImageToPhotosAlbum = (filePath) => {return new Promise((resolve, reject) => {wx.saveImageToPhotosAlbum({filePath,success: res => {resolve(res)},fail: res => {reject(res)}})})
}

二、视图的实现

.wxml


"icon-download" catchtap="getCanvas">点击生成图片
'shade' wx:if="{{isShowCanvas}}">'qr-code'>'qr-canvas' canvas-id="qrCanvas" id="qrCanvas">'qr-btn'>'qr-btn-save' catchtap='saveImageToPhotosAlbumFunc'>保存图片,分享到朋友圈'qr-btn-cancel' catchtap='hideCanvas'>取消

.wxss

/* 查看大图 */.shade {width: 100%;height: 100%;background-color: rgba(240, 235, 235, 0.5);position: fixed;z-index: 100;top: 0;left: 0;
}.qr-code {width: 600rpx;height: 1000rpx;background-color: #fff;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%); /* margin: 30rpx auto; */
}.qr-canvas {display: block;background-color: #fff;margin: 0 auto;width: 600rpx;height: 900rpx;
}.qr-btn {width: 600rpx;height: 100rpx;line-height: 100rpx;margin: 0 auto;font-size: 28rpx;color: #fff;display: flex;background-color: #658dc5;
}.qr-btn-save {flex: 0 0 500rpx;text-align: center;border-right: 1rpx solid #fff;
}.qr-btn-cancel {text-align: center;flex: 0 0 100rpx;
}

三、创建canvas并保存到系统相册

tips

  1. 商品图是正方形的,所以这里商品图的宽高都用canvas的宽
  2. 文字不能换行,这里只是简单的处理了一下
  3. 注意: wx.canvasToTempFilePath(Object object, Object this) 这个的使用,文档有一句话需要注意的:“把当前画布指定区域的内容导出生成指定大小的图片。在 draw() 回调里调用该方法才能保证图片导出成功。”

const app = getApp()
const regeneratorRuntime = app.globalData.regeneratorRuntimeconst
const util = require('../../utils/util.js')
import {getSelectQurey,getWxImageInfo,canvasToTempFilePath,saveImageToPhotosAlbum
} from &#39;../../datas/common.js&#39;Page({data: {isShowCanvas: false, // 是否显示canvas wxaCode: &#39;https://xxx..jpg&#39;, // 商品小程序码goodsImageUrl: &#39;https://xxx..jpg&#39;, // 商品图片 canvasTempFilePath: &#39;&#39;, // canvas导出生成图片的临时路径 },// 点击显示要生成的canvas getCanvas(e) {if (!this.data.wxaCode) {util.showToast(&#39;二维码生成失败&#39;);return;}this.setData({isShowCanvas: true}, () &#61;> {this.createCanvas();})},// 隐藏canvas hideCanvas() {this.setData({isShowCanvas: false})},// 创建canvas async createCanvas() {wx.showLoading({title: &#39;图片生成中...&#39;})const _this &#61; this// 创建节点选择器 const res &#61; await getSelectQurey(&#39;#qrCanvas&#39;);// canvas的宽高 const cvWidth &#61; res[0].width;const cvHeight &#61; res[0].height;const cvSubValue &#61; cvHeight - cvWidthconst qrWidth &#61; cvSubValue / 1.5const qrMargin &#61; (cvSubValue - qrWidth) / 2const qrX &#61; cvWidth - qrWidth - qrMargin / 2const qrY &#61; cvWidth &#43; qrMarginconst shopNameY &#61; cvWidth &#43; cvSubValue - qrWidth// 二维码网络图片转临时路径 let qrImagePath &#61; &#39;&#39;;try {const wxaCode &#61; _this.data.wxaCode;const qrImage &#61; await getWxImageInfo(wxaCode);qrImagePath &#61; qrImage.path} catch (e) {wx.hideLoading();this.hideCanvas();util.showToast(&#39;二维码生成失败&#39;);return;}// 商品网络图片转临时路径 let goodsImagePath &#61; &#39;/images/default_goods.png&#39;;const goodsImage &#61; _this.data.goodsImageUrl;if (goodsImage) {const goodsImageRes &#61; await getWxImageInfo(goodsImage);goodsImagePath &#61; goodsImageRes.path;}// 创建canvas var ctx &#61; wx.createCanvasContext(&#39;qrCanvas&#39;, _this);// 设置背景 ctx.setFillStyle(&#39;#fff&#39;);ctx.fillRect(0, 0, cvWidth, cvHeight);// 设置商品图片 商品图宽高是一样的 ctx.drawImage(goodsImagePath, 0, 0, cvWidth, cvWidth);// 设置二维码图片 ctx.drawImage(qrImagePath, qrX, qrY, qrWidth, qrWidth);// 设置店铺名称 const shopName &#61; &#39;我是店铺名称&#39;;ctx.setFillStyle(&#39;black&#39;)ctx.setFontSize(16)ctx.setTextAlign(&#39;left&#39;)ctx.fillText(shopName, 10, shopNameY, cvWidth - qrWidth);// 设置商品名称 文字不能换行&#xff0c;这里只是简单的处理了一下 const goodsName &#61; &#39;一个名字很长很长的商品就问你怕不怕&#39;;let goodsName1 &#61; &#39;&#39;;let goodsName2 &#61; &#39;&#39;;ctx.setFillStyle(&#39;black&#39;)ctx.setFontSize(14)ctx.setTextAlign(&#39;left&#39;)if (goodsName.length <&#61; 10) {ctx.fillText(goodsName, 10, shopNameY &#43; 30, cvWidth - qrWidth);} elseif (goodsName.length > 10 && goodsName.length <&#61; 22) {goodsName1 &#61; goodsName.substring(0, 10);goodsName2 &#61; goodsName.substring(10);ctx.fillText(goodsName1, 10, shopNameY &#43; 30, cvWidth - qrWidth);ctx.fillText(goodsName2, 10, shopNameY &#43; 50, cvWidth - qrWidth);} else {goodsName1 &#61; goodsName.substring(0, 10);goodsName2 &#61; goodsName.substring(10, 22) &#43; &#39;...&#39;;ctx.fillText(goodsName1, 10, shopNameY &#43; 30, cvWidth - qrWidth);ctx.fillText(goodsName2, 10, shopNameY &#43; 50, cvWidth - qrWidth);}// 设置提示 const tipText &#61; &#39;长按识别小程序&#xff0c;马上下单&#xff01;&#39;;ctx.setFillStyle(&#39;gray&#39;)ctx.setFontSize(8)ctx.setTextAlign(&#39;center&#39;)ctx.fillText(tipText, cvWidth / 2, cvHeight - 10);// 完成 ctx.draw(false, () &#61;> {wx.hideLoading();_this.canvasToTempFilePathFunc(cvWidth, cvHeight, &#39;qrCanvas&#39;)});},// 把当前画布指定区域的内容导出生成指定大小的图片 async canvasToTempFilePathFunc(cvWidth, cvHeight, qrCanvas) {try {let res &#61; await canvasToTempFilePath(cvWidth, cvHeight, qrCanvas);this.setData({canvasTempFilePath: res.tempFilePath});} catch (error) {console.log(error);util.showToast(error.errMsg);}},// 保存图片到本地 async saveImageToPhotosAlbumFunc() {try {let res &#61; await saveImageToPhotosAlbum(this.data.canvasTempFilePath);console.log(res);this.hideCanvas();util.showToast(&#39;图片保存成功&#39;);} catch (err) {console.log(err);}}
})

写得比较简单&#xff0c;因为主要是方便自己做记录的&#xff0c;所以也没有考虑到过多的使用场景。


转:https://juejin.im/post/5d0ae2715188251ac11f70c1



推荐阅读
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 在使用 DataGridView 时,如果在当前单元格中输入内容但光标未移开,点击保存按钮后,输入的内容可能无法保存。只有当光标离开单元格后,才能成功保存数据。本文将探讨如何通过调用 DataGridView 的内置方法解决此问题。 ... [详细]
  • 毕业设计:基于机器学习与深度学习的垃圾邮件(短信)分类算法实现
    本文详细介绍了如何使用机器学习和深度学习技术对垃圾邮件和短信进行分类。内容涵盖从数据集介绍、预处理、特征提取到模型训练与评估的完整流程,并提供了具体的代码示例和实验结果。 ... [详细]
  • 本文详细探讨了网站流量统计中常用的三个关键指标:页面浏览量(PV)、独立访客数(UV)和独立IP数(IP)。通过分析这些指标的定义、计算方法及其应用场景,帮助网站运营者更好地理解用户行为,优化网站内容与用户体验。 ... [详细]
  • 数据管理权威指南:《DAMA-DMBOK2 数据管理知识体系》
    本书提供了全面的数据管理职能、术语和最佳实践方法的标准行业解释,构建了数据管理的总体框架,为数据管理的发展奠定了坚实的理论基础。适合各类数据管理专业人士和相关领域的从业人员。 ... [详细]
  • 本文介绍如何通过注册表编辑器自定义和优化Windows文件右键菜单,包括删除不需要的菜单项、添加绿色版或非安装版软件以及将特定应用程序(如Sublime Text)添加到右键菜单中。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 本文介绍如何通过创建替代插入触发器,使对视图的插入操作能够正确更新相关的基本表。涉及的表包括:飞机(Aircraft)、员工(Employee)和认证(Certification)。 ... [详细]
  • 网络运维工程师负责确保企业IT基础设施的稳定运行,保障业务连续性和数据安全。他们需要具备多种技能,包括搭建和维护网络环境、监控系统性能、处理突发事件等。本文将探讨网络运维工程师的职业前景及其平均薪酬水平。 ... [详细]
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
  • 百度服务再次遭遇技术问题,疑似DNS解析故障
    近日晚间,百度多项在线服务出现加载异常,包括移动端搜索在内的多个功能受到影响。初步迹象表明,问题可能与DNS服务器解析有关。 ... [详细]
  • MySQL索引详解与优化
    本文深入探讨了MySQL中的索引机制,包括索引的基本概念、优势与劣势、分类及其实现原理,并详细介绍了索引的使用场景和优化技巧。通过具体示例,帮助读者更好地理解和应用索引以提升数据库性能。 ... [详细]
  • 本文探讨了在通过 API 端点调用时,使用猫鼬(Mongoose)的 findOne 方法总是返回 null 的问题,并提供了详细的解决方案和建议。 ... [详细]
author-avatar
天若无雨666
这个菇凉很宅,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有