用canvas绘制微信小程序海报页面并保存相册-适用微信原生

news2025/1/10 21:43:15

微信小程序绘制海报并保存相册

tip:代码中使用的是uni的api 如果使用原生微信小程序开发,可以把uni更换成wx使用

文章目录

  • 微信小程序绘制海报并保存相册
  • 前言
  • 一、分析需求
  • 二、准备数据
  • 三、编码开始
      • html部分
        • 解析:
      • js部分
        • 1、准备好数据后开始绘制
        • 解释:
        • 2、保存图片
        • 解析:
  • 总结


前言

本片文章主要是把我工作中实际用到,可以整合出来的功能,做一个总结和讲解。

1、如何使用canvas
2、canvas绘制后如何生成图片
3、将图片保存到相册
4、难点:如何解决canvas层级高于position定位层级问题,如何适配不同屏幕大小比例


一、分析需求

两种方案:

  1. 进入页面先绘制canvas,点击按钮后再生成图片并保存相册
  2. 进入页面先绘制canvas,并生成图片,点击按钮直接保存图片到相册

我这边使用的是第一种方式,看实际需求。(其实没多大区别)

二、准备数据

在开始绘制canvas之前首先要,分析页面中用到了哪些内容:

  1. 背景图片
  2. 二维码图片
  3. 关于海报的一些描述性文案

注意:
1、由于这些数据可能不是页面写死的内容,是根据api返回的数据,所以需要在绘制canvas之前就先准备好从api返回的数据。
2、需要考虑同步问题


三、编码开始

先看下页面图片样式
效果图

html部分

<canvas :style="{height:pageHeight,width: _width +'px'}" canvas-id="mycanvas" />
<cover-view @tap="saveImg">
	<cover-image src="btn_img.png"></cover-image>
</cover-view>

解析:

1、首先需要准备一个canvas用于绘制页面内容的载体,id是唯一标识
2、需要一个按钮用于保存图片,但是发现即使用绝对定位调整层级还是不能将按钮显示到canvas上层,所以借助于官方提供的覆盖原生组件的方法。cover-viewcover-image

js部分

这里只说代码重点部分。

页面中用到的变量可以自行修改,至于变量的初始值都可以是空字符串

1、准备好数据后开始绘制

onReady() {
	// 为了兼容不同机型页面大小,所以需要先获取到页面宽高
	this.getSysInfo()
},
getSysInfo() {
	/*获取手机宽高*/
	let that = this
	let imgUrl = this.imageUrl
	let qrcodeUrl = this.codeUrl
	uni.getSystemInfo({
		success(res) {
			console.log('屏幕宽度', res)
			that._width = res.windowWidth
			that._heigth = res.windowHeight
			// 获取图片信息生成canvas
			// 因为这里用的网络图片所以需要先获取本地网络图地址
			that.getImginfo([imgUrl, qrcodeUrl], 0);
		}
	})
},
getImginfo(urlArr, _type) {
	let that = this;
	uni.getImageInfo({
		src: urlArr[_type],
		success: function(res) {
			//res.path是网络图片的本地地址
			if (_type === 0) { //
				that.localImageUrl = res.path
				that.getImginfo(urlArr, 1)
			} else {
				//二维码
				that.localCodeUrl = res.path
				// 创建canvas图片
				that.createNewImg();
			}
		},
		fail: function(res) {
			//失败回调
			console.log('错误', _type, res)
		}
	});
},
createNewImg() {
	let that = this;
	let ctx = uni.createCanvasContext('mycanvas');
	// 绘制背景
	ctx.drawImage(this.localImageUrl, 0, 0, this._width, this._heigth - 44 - this.statusBarHeight);
	// 绘制二维码区域
	ctx.lineJoin = "round";
	ctx.lineWidth = 12;
	ctx.setFillStyle('#FFFFFF')
	ctx.setStrokeStyle('#FFFFFF')

	// 二维码区域y坐标
	const yPosition = this._heigth - 44 - this.statusBarHeight - this.remSize(98) - 100
	ctx.strokeRect(this.remSize(24), yPosition, this.remSize(326), this.remSize(98));
	ctx.fillRect(this.remSize(24), yPosition, this.remSize(326), this.remSize(98));

	// 绘制二维码
	const yPosition2 = yPosition + 4
	ctx.drawImage(this.localCodeUrl, this.remSize(28), yPosition2, this.remSize(90), this.remSize(90));

	//二维码区域文字
	let title1 = this.tips.title1;
	let title2 = this.tips.title2;
	let title3 = this.tips.title3;
	// 文字一
	ctx.setFontSize(this.remSize(14));
	ctx.setFillStyle('#333333');
	ctx.fillText(title1, this.remSize(128), yPosition + this.remSize(30));
	// 文字二三
	ctx.setFillStyle('#B8B8B8');
	ctx.setFontSize(this.remSize(12));
	ctx.fillText(title2, this.remSize(128), yPosition + this.remSize(62));
	ctx.fillText(title3, this.remSize(128), yPosition + this.remSize(85));
	// 绘制
	ctx.draw();

	//将生成好的图片保存到本地
	uni.canvasToTempFilePath({
		canvasId: 'mycanvas',
		success: (res)=> {
			that.loadImagePath = res.tempFilePath
		},
		fail: (res)=> {
			console.log(res);
		}
	});
},
// 缩放比例
let scalePage = uni.getSystemInfoSync().windowWidth / 375

remSize(num) {
	return num * scalePage
},

解释:

1、uni.createCanvasContext创建canvas上下文,用于操作绘制具体图片和文字
2、ctx.drawImage用于绘制图片
3、ctx.setFillStyle用于绘制填充色
4、ctx.setStrokeStyle用于绘制边框颜色
5、因为canvas不能绘制圆角实心矩形,所以取巧的方式,就是用圆角矩形和实心矩形覆盖的方式,效果见上图。
6、ctx.strokeRect绘制矩形空心
7、ctx.fillRect绘制矩形实心
6、ctx.setFontSize ctx.setFillStyle ctx.fillText 绘制文字大小,颜色,位置
7、ctx.draw() 把所有的上下文内容,绘制到canvas上面
特别说明:

  1. remSize方法,根据设计稿去设置图片大小和文案的位置比例,我这边是根据375像素的宽度计算比例。
  2. 这些api具体使用方法,可以参考官方文档,这里就不一一列举了。

2、保存图片

//点击保存到相册
saveImg() {
	uni.saveImageToPhotosAlbum({
		filePath: this.loadImagePath,
		success(res) {
			uni.showToast({
				title: '已保存到相册',
				icon: 'success',
				duration: 3000
			})
		}
	})
},

解析:

1、因为保存按钮是固定定位,并且按钮并非canvas绘制内容,所以保存图片的时候并不会有按钮。
2、需要注意的是,保存相册是需要相册保存权限的,这个可以看文档自己去设置。

总结

上面的说的覆盖问题,还可以是先使用canvas把直接生成图片,然后在页面上直接显示生成好的图片。
如有问题,欢迎指正修改。

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

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

相关文章

王道操作系统笔记(三)———— 处理机调度

文章目录一、调度的概念1.1 调度的基本概念1.2 调度的层次1.3 补充&#xff1a;七状态模型二、调度的时机、切换与过程2.1 进程调度的时机2.2 狭义进程调度、进程切换、广义进程调度2.3 进程切换的过程2.4 补充&#xff1a;闲逛进程三、进程的调度方式四、调度算法的评价指标五…

【通信原理(含matlab程序)】实验四 升余弦滚降基带传输

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; 本人持续分享更多关于电子通信专业内容以及嵌入式和单片机的知识&#xff0c;如果大家喜欢&#xff0c;别忘点个赞加个关注哦&#xff0c;让我们一起共同进步~ &#x…

【Novel AI】使用绘画AI构建unity游戏资源

请勿在商业用途中使用下面的示例图中的任何资源&#xff01; 1. 设想&#xff1a; 首先根据自己的设想&#xff0c;创造一些角色原型&#xff0c;角色特点等等 这里我根据网络上找的一些参考&#xff0c;我大概想要的是比较特别的一个警察的猫人形的动物角色&#xff1b; 2…

网络编程(TCP+UDP)(1)

咱们的一个TCP服务器&#xff0c;是否可以让一个UDP客户端连接上呢&#xff1f; 1)TCP和UDP&#xff0c;他们无论是API代码&#xff0c;还是协议底层的工作过程&#xff0c;都是差异巨大的&#xff0c;不是单纯的把流转化成数据包就可以的&#xff1b; 2)描述一次通信&#xff…

武器系统中的自主性(国防部指令3000.09)

批准:负责政策的国防部副部长办公室2023年1月25日可以公开发布。可在指令司网站https://www.esd.whs.mil/DD/查阅。国防部指令3000.09&#xff0c;“武器系统中的自主性”&#xff0c;2012年11月21日国防部副部长凯瑟琳希克斯(Kathleen H. Hicks)目的:本指令:•建立开发和使用武…

教育数字化转型 看低代码怎么构建实现

数字经济和数字社会的发展&#xff0c;推动教育培养目标和内容的发展与变革。经过教育信息化1.0和2.0的建设&#xff0c;我国数字技术与教育经历了起步、应用、融合、创新四个阶段&#xff0c;目前正处于融合与创新并存的时期。教育数字化教育数字化转型是教育信息化的特殊阶段…

C 程序设计教程(20)—— 数组和指针(三):数组与指针的关系

C 程序设计教程&#xff08;20&#xff09;—— 数组和指针&#xff08;三&#xff09;&#xff1a;数组与指针的关系 该专栏主要介绍 C 语言的基本语法&#xff0c;作为《程序设计语言》课程的课件与参考资料&#xff0c;用于《程序设计语言》课程的教学&#xff0c;供入门级用…

RESTful应用

AJAX技术 浏览器是多进程的&#xff0c;简单的说就是&#xff0c;浏览器每打开一个标签页&#xff0c;就相当于创建了一个独立的浏览器进程。但是js是基于单线程的&#xff0c;而这个线程就是浏览器的js引擎&#xff0c;浏览器无论在什么时候都只且只有一个线程在运行JavaScri…

sonic-ios-bridge(sib)性能监控之系统性能及应用性能

sib下载地址&#xff1a;Releases SonicCloudOrg/sonic-ios-bridge GitHub 可以看到最新版本为V1.3.7。下载到本地并解压后即可使用。 性能监控使用帮助&#xff1a;sib perfmon -h sib perfmon -f -j&#xff1a;以json格式化显示性能数据。 一、查看系统整体性能数据 查看…

10. POP3收取邮件

1. POP3协议 POP3&#xff0c;全名为“Post Office Protocol - Version 3”&#xff0c;即“邮局协议版本3”。是TCP/IP协议族中的一员&#xff0c;由RFC1939 定义。本协议主要用于支持使用客户端远程管理在服务器上的电子邮件。提供了SSL加密的POP3协议被称为POP3S。 POP 协议…

Kernel: sysctl: hung_task_panic、hung_task_check_count、hung_task_timeout_secs

文章目录 mutex 锁相关的一个例子这个和磁盘相关的一个例子hung_task_panic:hung_task_check_count:hung_task_timeout_secs:实例hung_task_warnings:相关的编译配置mutex 锁相关的一个例子 systemd-shutdown 卡在device-shutdown时调用的mutex-lock操作。 这个和磁盘相关的…

Android ANR触发机制及日志分析

1.ANR Application Not Responding&#xff0c;即应用程序未响应。Android系统要求一些事件在一定时间范围内完成&#xff0c;如果超过预定时间未得到有效响应或响应时间过长&#xff0c;就会造成ANR。 Android中有4种ANR发生场景&#xff1a; ①点击事件(按键和触摸事件&am…

PDF在线合并网页版有哪些?这几款你一定没用过

PDF在线合并网页版有哪些&#xff1f;很多人在工作中都需要给其他人发送一些重要文件&#xff0c;如果文件数量比较多的时候&#xff0c;就会出现耗时有耗力的情况&#xff0c;所以我们就需要想一个办法来解决问题&#xff0c;那就是将多个PDF文件进行合并&#xff0c;我们需要…

MATLAB算法实战应用案例精讲-【数模应用】概率生成模型(Generative Model)

前言 知识储备 表征学习 背后的核心思想representation learning ,不是试图直接对高维样本空间建模,而是使用一些低维潜在空间来描述训练集中的每个观察,然后学习一个映射函数,该函数可以在潜在空间中取一个点,将其映射到原始域中的一个点。换句话说,潜在空间中的每个…

[LeetCode 1664]生成平衡数组的方案数

题目描述 题目链接&#xff1a;[LeetCode 1664]生成平衡数组的方案数 给你一个整数数组 nums 。你需要选择 恰好 一个下标&#xff08;下标从 0 开始&#xff09;并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。 比方说&#xff0c;如果 nums [6,1,…

群晖(docker图形化界面)使用 SpeedTest 测速

群晖(docker图形化界面)使用 SpeedTest 测速 博主博客 https://blog.uso6.comhttps://blog.csdn.net/dxk539687357 本文主要介绍在群晖中安装 speedtest 进行网络测速。 一、安装 docker 在套件中心搜索并且安装 docker。 二、下载容器 在 注册表 中搜索 adolfintel/speedte…

UART、RS232、RS485和RS422

1.UART UART是通用异步收发传输器&#xff08;Universal Asynchronous Receiver/Transmitter)&#xff0c;是一种通用的串行、异步通信总线&#xff0c;是设备间进行异步通信的关键模块。UART负责处理数据总线和串行口之间的串/并、并/串转换&#xff0c;并规定了帧格式&#…

PPT制作心得

1.插入形状&#xff1a; 这里有三个部分可以设置&#xff1a; 填充可以设置用什么颜色来填充 轮廓可以设置边框的颜色 (样式是设置 填充轮廓&#xff0c;也就是说有一些默认的填充轮廓组合&#xff09; 还有里面的文字的大小&#xff0c;字体&#xff0c;颜色 2.如何画水平…

深度解析2023世界人工智能大会

1、2020年世界人工智能大会&#xff0c;此次大会的主要目的是什么&#xff1f; 我们现在的社会是一个科技快速发展的国家&#xff0c;因为我们已经不会再为了温饱的问题而操心&#xff0c;而是越来越追求自己的精神享受。然而科技在这一方面也是发展非常迅速的&#xff0c;我们…

请求头 x-ca-key、x-ca-nonce、x-ca-signature 加密分析第一篇

本篇博客为大家开始着手分析 请求头 x-ca-key、x-ca-nonce、x-ca-signature 加密相关内容 目标站点在本文进行隐藏&#xff0c;如有需要&#xff0c;可直接联系 一般你能搜到这篇博客&#xff0c;代表你采集的站点使用类似加密。 请求头解密目录x-ca-key、x-ca-nonce、x-ca-sig…