移动web上传图片旋转问题 && 附带图片压缩

191 阅读2分钟

参考链接-【bug】前端上传图片被旋转

import Exif from 'exif-js';
import {getPlatform} from "./index"
class TakePicHelper {
	constructor() {
	}
	//根据图片名称后缀校验图片格式
	checkPicType(fileName) {
          if (!fileName || !fileName.length) return false;
          const TYPEREG = /\.(png)?(jpg)?(jpeg)?$/i;
          return TYPEREG.test(fileName);
	}

	//校验图片大小是否大于limiteSize
	checkPicSize(fileSize, limitSize = 10) {
		if (limitSize <= 0) return false;
		return (fileSize / Math.pow(2, 20) > limitSize);
	}

	uploadImage(imageData) {}
	
    // 判断当前手机版本是否大于指定版本
    function isCurrentVersionLargerThan(lastVersion = '') {
        const str = navigator.userAgent.toLowerCase();
        const version = str.match(/cpu iphone os (.*?) like mac os/);
        let currentVersion = '0.0.0';
        if (version && version[1]) {
            currentVersion = version[1].replace(/_/g, '.');
        }
        console.log(currentVersion);
        
        const sources = currentVersion.split('.');
        const dests = lastVersion.split('.');
        const maxL = Math.max(sources.length, dests.length);
        let result = true;
        for (let i = 0; i < maxL; i++) {
            let preValue = sources.length > i ? sources[i] : 0;
            let preNum = isNaN(Number(preValue)) ? preValue.charCodeAt() : Number(preValue);
            let lastValue = dests.length > i ? dests[i] : 0;
            let lastNum = isNaN(Number(lastValue)) ? lastValue.charCodeAt() : Number(lastValue);
            if (preNum < lastNum) {
                result = false;
                break;
            } else if (preNum > lastNum) {
                result = true;
                break;
            }
        }
        return result;
    }
	/**
	* 使用canvas压缩用户上传的图片
	* @param {File} imgFile 被压缩的图片文件
	* @param {function} cb 回调函数
	* @param {string} type 压缩出来后的类型
	* @param {number} quality 压缩比
	* @param {number} maxLength 最大可能宽/高值
	*/
	async canvasCompress(imgFile, cb, type = 'image/jpeg', quality = 0.7, maxLength = 1500) {
    		// IOS版本大于13.4.1不会涉及到旋转问题
		if (getPlatform().iOS) {
            		if(isCurrentVersionLargerThan("13.4.0")) {
                          cb(imgFile);
                          return;
                      	}
                  }
		if (typeof FileReader === "function" && !!FileReader.prototype.readAsDataURL && !!HTMLCanvasElement.prototype.toBlob) {
			let fr = new FileReader();
			const or = await this.getImageTag(imgFile, 'Orientation');
			fr.addEventListener('load', () => {
				let img = new Image()
					, canvas = document.createElement('canvas')
					, context = canvas.getContext('2d');

				img.setAttribute('crossOrigin', 'anonymous');

				img.onload = () => {
					let imgWidth = img.width
						, imgHeight = img.height;

					if (imgWidth > maxLength) {
						imgHeight = imgHeight / imgWidth * maxLength;
						// imgHeight = maxLength;
						imgWidth = maxLength;
					}

					if (imgHeight > maxLength) {
						imgWidth = imgWidth / imgHeight * maxLength;
						// imgWidth = maxLength;
						imgHeight = maxLength;
					}
					// this.getRotateImg(img,context, or);
					console.log('--->>>>>>>or = ', or);
					switch (or) {
						case 6: // 顺时针旋转90度
							canvas.height = imgWidth;
							canvas.width = imgHeight;
							this.rotateImg(img, 'right', context, imgWidth, imgHeight);
							break;
						case 8: // 逆时针旋转90度
							canvas.height = imgWidth;
							canvas.width = imgHeight;
							this.rotateImg(img, 'left', context, imgWidth, imgHeight);
							break;
						case 3: // 顺时针旋转180度
							canvas.width = imgWidth;
							canvas.height = imgHeight;
							this.rotateImg(img, 'right', context, imgWidth, imgHeight, 2);
							break;
						default:
							canvas.width = imgWidth;
							canvas.height = imgHeight;
							context.drawImage(img, 0, 0, imgWidth, imgHeight);
							break;
					}

					canvas.toBlob((blob) => {
                    				// 根据情况选择上传blob格式或者file格式
						const file = new window.File(
							[blob],
							imgFile.name,
							{ type: imgFile.type }
						);
						// cb(blob);
						cb(file);
					}, type, quality);
				};

				img.onerror = () => {
					cb(imgFile);
				};

				img.src = fr.result;
			}, false);
			fr.readAsDataURL(imgFile);
		}
		else {
			cb(imgFile);
		}
	}
	getImageTag = (file, tag) => {
		if (!file) return 0;
		return new Promise((resolve, reject) => {
			/* eslint-disable func-names */
			// 箭头函数会修改this,所以这里不能用箭头函数
			Exif.getData(file, function () {
				const o = Exif.getTag(this, tag);
				resolve(o);
			});
		});
	};

	rotateImg = (img, dir = 'right', ctx, width, height, s = 1) => {
		const MIN_STEP = 0;
		const MAX_STEP = 3;

		let step = 0;

		if (dir === 'right') {
			step += s;
			step > MAX_STEP && (step = MIN_STEP);
		} else {
			step -= s;
			step < MIN_STEP && (step = MAX_STEP);
		}

		const degree = step * 90 * Math.PI / 180;

		switch (step) {
			case 1:
				ctx.rotate(degree);
				ctx.drawImage(img, 0, -height, width, height);
				break;
			case 2:
				ctx.rotate(degree);
				ctx.drawImage(img, -width, -height, width, height);
				break;
			case 3:
				ctx.rotate(degree);
				ctx.drawImage(img, -width, 0, width, height);
				break;
			default:
				ctx.drawImage(img, 0, 0, width, height);
				break;
		}
	};
}

export default new TakePicHelper();