uniapp h5上传图片对图片进行压缩旋转处理

之前写过一个关于vue的上传图的旋转处理。可以直接点击查看:使用vue进行移动端上传图

 

场景:uniapp开发的h5项目,需要内嵌在app中运行,在项目首页有一块是自定义上传日历背景图,并且需要进行裁剪。
最开始直接使用的插件市场的插件,但是由于webview的原因,该项目内嵌app后在ios上出现了无法解决的bug。故弃用了插件,并且由于需求调整目前只进行图片的上传旋转处理。(下面着重旋转的处理)

思路:

1、参考vue的处理方法,需要exif.js 获取到图片meta信息中的旋转角度,故首先需要引入exif.js,(本人直接从bootcdn上搜索下载的exif.min.js )(使用import引入本地文件的方式尝试了下没有成功,放弃了。由于项目本身需要存在了引入第三方的js方法所以exifjs是通过动态添加js的方式全局引入的)

2、通过uni.chooseImage 获取到图片的临时路径,并且将blob临时路径转化为 file文件用于exif获取图片的旋转值

3、根据获取到旋转值(有:1 3 6 8),如下:

                            //如果方向角不为1,都需要进行旋转
							switch (Orientation) {
								case 6: //需要顺时针(向右)90度旋转
									console.log('(向右)90度旋转');
									break;
								case 8: //需要逆时针(向左)90度旋转
									console.log('向左)90度旋转');
									break;

								case 3: //需要180度旋转 转两次
									console.log('需要180度旋转');
									break;
								default:
									break;
							}

4、根据网上搜索的处理图片旋转方法或者从往期vue的上传图博客中提到的,对图片进行旋转处理,最终拿到base64的图片信息然后对图片进行上传。(1.直接上传base64 ;2.将base64转化为blob文件后再传后台)

 

 

具体代码如下:

1、
choiceImg(){
var that = this;
			let maxWidth = 500; //压缩图片最大宽度
			let Orientation = 1;
			uni.chooseImage({
				count: 1, // 能够选择的图片数量
				sizeType: ['original', 'compressed'], // original: 原图, compressed: 压缩图, 默认二者都有
				sourceType: ['album'], // album: 从相册选择   camera: 相机拍照
				success: res => {
					let imgArr = res.tempFilePaths; // 所选择图片的临时路径数组
					//BlobUrl转blob数据
					
					uni.showToast({
						icon: "none",
						title: "图片处理中..."
					})
					//blob数据转file
					this.objectURLToBlob(imgArr[0], function(blob) {
						let files = new window.File([blob], 'file.name', { type: 'file.type' });
						console.log('获取图片文件', files);
						EXIF.getData(files, async function() {
							let or = EXIF.getTag(this, 'Orientation'); //这个Orientation 就是我们判断需不需要旋转的值了,有1、3、6、8
							console.log(or);
							Orientation = or;
							var img = null;
							var canvas = null;
							await that.comprossImage(imgArr[0], maxWidth, function(e) {
								img = e.img;
								canvas = e.canvas;
							});
							let baseStr = '';
							//如果方向角不为1,都需要进行旋转
							switch (Orientation) {
								case 6: //需要顺时针(向右)90度旋转
									console.log('(向右)90度旋转');
									baseStr = that.rotateImg(img, 'right', canvas);
									break;
								case 8: //需要逆时针(向左)90度旋转
									console.log('向左)90度旋转');
									baseStr = rotateImg(img, 'left', canvas);
									break;

								case 3: //需要180度旋转 转两次
									console.log('需要180度旋转');
									baseStr = that.rotateImg(img, 'right', canvas, 2);
									break;
								default:
									baseStr = that.rotateImg(img, '', canvas);
									break;
							}
						});
					});
				}
			});
}
2、1中使用到的将blob转化为file方法 和图片的压缩方法
objectURLToBlob(url, callback) {
			var http = new XMLHttpRequest();
			http.open('GET', url, true);
			http.responseType = 'blob';
			http.onload = function(e) {
				if (this.status == 200 || this.status === 0) {
					callback(this.response);
				}
			};
			http.send();
		},
		async comprossImage(imgSrc, maxWidth, func) {
			if (!imgSrc) return 0;
			return new Promise((resolve, reject) => {
				uni.getImageInfo({
					src: imgSrc,
					success(res) {
						let img = new Image();
						img.src = res.path;
						console.log(img);

						let canvas = document.createElement('canvas');

						let obj = new Object();
						obj.img = img;
						obj.canvas = canvas;
						resolve(func(obj));
					}
				});
			});
		},
3、图片的旋转处理
rotateImg(img, direction, canvas, times = 1) {
			console.log('开始旋转');
			//最小与最大旋转方向,图片旋转4次后回到原方向
			var min_step = 0;
			var max_step = 3;
			if (img == null) return;

			//img的高度和宽度不能在img元素隐藏后获取,否则会出错
			var height = img.height;
			var width = img.width;
			let maxWidth = 500;
			let canvasWidth = width; //图片原始长宽
			let canvasHeight = height;
			let base = canvasWidth / canvasHeight;
			console.log(maxWidth);
			if (canvasWidth > maxWidth) {
				canvasWidth = maxWidth;
				canvasHeight = Math.floor(canvasWidth / base);
			}
			width = canvasWidth;
			height = canvasHeight;
			var step = 0;

			if (step == null) {
				step = min_step;
			}

			if (direction == 'right') {
				step += times;
				//旋转到原位置,即超过最大值
				step > max_step && (step = min_step);
			} else if (direction == 'left') {
				step -= times;
				step < min_step && (step = max_step);
			} else {
				//不旋转
				step = 0;
			}

			//旋转角度以弧度值为参数
			var degree = (step * 90 * Math.PI) / 180;
			var ctx = canvas.getContext('2d');
			// console.log(degree)
			// console.log(step)
			switch (step) {
				case 1:
					console.log('右旋转 90度');
					canvas.width = height;
					canvas.height = width;
					ctx.rotate(degree);
					ctx.drawImage(img, 0, -height, width, height);
					break;
				case 2:
					//console.log('旋转 180度')
					canvas.width = width;
					canvas.height = height;
					ctx.rotate(degree);
					ctx.drawImage(img, -width, -height, width, height);
					break;
				case 3:
					console.log('左旋转 90度');
					canvas.width = height;
					canvas.height = width;
					ctx.rotate(degree);
					ctx.drawImage(img, -width, 0, width, height);
					break;
				default:
					//不旋转
					canvas.width = width;
					canvas.height = height;
					ctx.drawImage(img, 0, 0, width, height);
					break;
			}

			let baseStr = canvas.toDataURL('image/jpeg', 1);
			// console.log(baseStr)
			// return baseStr;
			// replace("data:image/jpeg;base64,", "")
            // 将base64转化为blob文件进行图片上传,(考虑到转化后再上传耗费时间暂时没有使用,如果需要base64ToPath 方法可百度或者私信我)
			// base64ToPath(baseStr).then(tempPath => {
			// 	this.uploadBgImg(tempPath)
			// });
            // 自定义上传请求
			this.uploadBaseImg(baseStr);
		},

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章