uniapp实现小程序打开相册或拍照上传图片附赠兼容H5方法

news/2024/7/20 1:07:10 标签: 小程序, uni-app

文章目录

  • 前言
  • 一、支持相册选择和拍照
  • 二、删除图片
  • 三、效果图
  • 存在问题


前言

小程序上传图片,或者拍照上传图片,并附带兼容H5上传图片方法,压缩图片。


一、支持相册选择和拍照

支持选择相册和拍照,可以使用uniapp提供的api,当然也可以自己去封装自己想要的样式,我这里直接是使用了uni的方法。uni.chooseImage配置sourceType: ['album', 'camera']

openSelectImage() {
	let tempList = []
	uni.chooseImage({
		sizeType: ['compressed'],
		sourceType: ['album', 'camera'],
		success: (res) => {
			if (res.tempFilePaths?.length > 0) {
				tempList = res.tempFilePaths
				// #ifdef MP
				this.recursionCompressMP(tempList, (e) => {
					console.log('压缩后结果-----', e)
				})
				// #endif
				// #ifdef H5
				this.recursionCompressH5(tempList, (e) => {
					console.log('压缩后结果-----', e)
				})
				// #endif
			}
		},
		fail: (err) => {
			console.log("err: ------", err);
		}
	})
}
// 微信
async recursionCompressMP(urlList, callback) {
	let imgCompressList = []
	let imageSize = 0
	for (let itemUrl of urlList) {
		const result = await this.jumpImageCompress(itemUrl)
		if (result?.size < 150000) {
			this.tempImageList.push(itemUrl)
			continue
		}
		await this.getUserImageCompress(itemUrl, callback, result?.size)
	}
},

压缩图片主要用canvas提供的api
1、uni.createCanvasContext 创建 canvas 绘图上下文。
2、CanvasContext.drawImage 绘制图像到画布。
3、CanvasContext.draw将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中。
4、当canvas绘制完成后,将canvas导出成为图片,把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径。uni.canvasToTempFilePath

//微信压缩图片
getUserImageCompress(itemUrl, callback, size){
	let that = this;
	return new Promise ((resolve, reject)=>{
		uni.getImageInfo({
			src: itemUrl,
			success: (res) => {
				//获取设备像素比,不获取最后图片展示有问题
				uni.getSystemInfo({
					success: function(info) {
						let ratio = 2;
						let canvasWidth = res.width //图片原始长宽
						let canvasHeight = res.height
						let compressWidth = res.width
						let quality = 0.1
						compressWidth = res.width - 120
						canvasHeight = res.height - 120
						while (canvasWidth > compressWidth || canvasHeight > canvasHeight) { // 保证宽高在400以内
							canvasWidth = Math.trunc(res.width / ratio)
							canvasHeight = Math.trunc(res.height / ratio)
							ratio++;
						}
						that.canvasWidth = canvasWidth
						that.canvasHeight = canvasHeight
						let ctx = uni.createCanvasContext('mycanvas')
						ctx.drawImage(res.path, 0, 0, canvasWidth, canvasHeight)
						ctx.draw(false, setTimeout(() => {
							uni.canvasToTempFilePath({
								canvasId: 'mycanvas',
								destWidth: canvasWidth,
								destHeight: canvasHeight,
								fileType: 'jpg',
								quality: quality,
								success: function(res1) {
									callback && callback(res1.tempFilePath) //拿到图片压缩后的临时路径
									uni.getFileInfo({
										filePath: res1.tempFilePath,
										success: (ress) => {
											console.log('压缩之后----',ress) //返回图片尺寸
											callback && callback(res1.tempFilePath)
											console.log('添加数据----', that.tempImageList)
											
											resolve(res1.tempFilePath)
											that.tempImageList.push(res1.tempFilePath)
										}
									})
								},
								fail: function(res) {
									console.log('canvas错误---',res.errMsg)
								}
							})
						}, 100)) //留一定的时间绘制canvas
					}
				})
			},
			fail: (e) => {
				console.log('错误----', e)
			}
		})
	})
},

利用返回的图片大小去控制压缩的比例,重复执行压缩函数。

//返回图片大小
jumpImageCompress (itemUrl) {	
	return new Promise((resolve, reject)=>{
		uni.getFileInfo({
			filePath: itemUrl,
			success: (res) => {
				console.log('压缩之前图片大小----',res) //返回图片尺寸
				resolve(res)
			},
			fail: (err) =>{
				reject(err)
			}
		})
	})
},
//h5
recursionCompressH5(url, callback) {
if (typeof url === 'string') {
		this.getUserImageCompressH5(url,callback)
	} else if (typeof url === 'object') {
		for (let itemImg of url) {
			this.getUserImageCompressH5(itemImg,callback)
		}
	}
},

Tips:因为H5端 Canvas 内绘制的图像需要支持跨域访问才能成功。所以h5端uni.canvasToTempFilePath会返回为空,所以需要使用toBlob转为文件,再利用createObjectURL转为url,这样就可以获取到图片信息。控制压缩比例。

// h5压缩图片
getUserImageCompressH5 (imgUrl,callback) {
	let that = this;
	return new Promise((resolve, reject)=>{
		uni.getImageInfo({
			src: imgUrl,
			success(res) {
				let canvasWidth = res.width; //图片原始长宽
				let canvasHeight = res.height;
				let img = new Image();
				img.src = res.path;
				console.log(5435435353)
				let canvas = document.createElement("canvas");
				let ctx = canvas.getContext("2d");
				canvas.width = canvasWidth / 2;
				canvas.height = canvasHeight / 2;
				ctx.drawImage(img, 0, 0, canvasWidth / 2, canvasHeight / 2);
				canvas.toBlob(function(fileSrc) {
					let imgSrc = window.URL.createObjectURL(fileSrc);
					uni.getFileInfo({
						filePath: imgSrc,
						success: (resFileInfo) => {
							if (resFileInfo.size > 150000) {
								//压缩后大于1M就继续压缩
								that.recursionCompressH5(imgSrc, callback);
								return;
							} else {
								callback && callback(imgSrc)
								resolve(imgSrc)
								that.tempImageList.push(imgSrc)
							}
						},
					});
				});
			}
		});
	})
},

二、删除图片

删除功能很简单,直接使用数组方的删除方法splice就可以了。

deleteSelectImg(index) {
	this.tempImageList.splice(index, 1)
},

三、效果图

至于页面ui结构,这里就不粘贴了,可以根据自己实际需求去实现。
在这里插入图片描述


存在问题

在控制压缩比例的地方,还有一些缺陷,并没有很完美的解决压缩指定大小图片问题。
如有问题欢迎指出…


http://www.niftyadmin.cn/n/287328.html

相关文章

为什么要进行数据决策?数据决策对企业而言有何重要意义?

“大数据”几乎已成为时下最时髦的词汇&#xff0c;不夸张地说&#xff0c;当今各行各业无不对大数据充满了向往&#xff0c;希望自己在新一轮的大数据营销中抢占先机。同时&#xff0c;从大数据中引申出的数据挖掘、数据分析、数据安全等数据运用技术也成为人们热捧的焦点。 …

STC15W104 模块化编程用定时器实现灯的闪烁(定时器原理讲解二)

上一篇文章讲了原理和示例程序查找。这一篇讲怎么修改例程。 定时器0 1ms中断一次 1s翻转LED1一次 思维导图内部晶振 11.0592MHz 1T 不分频 设置定时器的工作模式 16位自动装载 计算1ms需要计时的次数 修改定时器0中断函数 使能定时器中断 开始计数 开启总中断确定内部晶振 1…

救生衣、划船背心、救生圈、U 形救生圈和投掷式浮垫等个人漂浮设备 (PFD)UL报告标准要求

个人漂浮设备 (PFD) 个人漂浮设备 (PFD) 是帮助人们在水中保持漂浮状态的装备。个人漂浮设备是一个范围较大的商品分类&#xff0c;其中包括救生衣、划船背心、救生圈、U 形救生圈和投掷式浮垫 救生衣 救生衣是一种在使用者正确穿戴时可为其提供支持的服装或设备&#xff0c;由…

代码随想录补打卡 968 监控二叉树

968 监控二叉树 代码如下 /** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */ func minCameraCover(root *TreeNode) int { res : 0 var traversal func(cur *TreeNode) int travers…

thread-最佳时间

wait-notify wait被阻塞后其是会释放锁的&#xff0c;并且需要在sychronized范围内使用 sychronized(lock){ while(!条件){ lock.wait(); } } sychronized(lock){ lock.notifyAll(); }join 模式保护性暂停 public final synchronized void join(final long millis)throws Inte…

有必要给孩子买台灯吗?分享四款高品质的护眼台灯

有必要使用护眼台灯&#xff0c;尤其是有近视现象的孩子们。 现在很多孩子小学就开始近视了&#xff0c;保护视力刻不容缓呀! 很多人不知道&#xff0c;其实劣质光线是最大的眼睛杀手 给孩子随便买便宜的台灯&#xff0c;看着一样能用&#xff0c;其实时间久了 对孩子眼睛的…

前端学习之使用JavaScript

前情回顾&#xff1a;网页布局 JavaScript 简介 avaScript诞生于1995年&#xff0c;它的出现主要是用于处理网页中的前端验证。所谓的前端验证&#xff0c;就是指检查用户输入的内容是否符合一定的规则。比如&#xff1a;用户名的长度&#xff0c;密码的长度&#xff0c;邮箱的…

【软考高级】2019年系统分析师综合知识

第 1 题 面向对象分析中&#xff0c;一个事物发生变化会影响另一个事物&#xff0c;两个事物之间属于&#xff08;1&#xff09;。 (1) A .关联关系 B .依赖关系 C .实现关系 D .泛化关系 参考答案&#xff1a;(1)B 试题解析&#xff1a; 本题考查的是 UML 图中类的关系…