解决ios下input添加的图片方向不正确

2,100 阅读2分钟

问题

ios13.4以下的系统版本调用相机拍照或者上传相机拍照的照片,会有图片翻转的问题。 为了解决这个问题需要做下面两个步骤:

  • 判断系统版本是否为13.4以下
  • 如果为13.4以下的话就需要进行校正

图片处理代码

这里的图片处理包括压缩大图片,翻转等操作。 将下面代码放到一个changeImg.js文件下。

import EXIF from "exif-js";

const isIos = () => !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);

const getIosVerStr = () => {
    let userAgent = navigator.userAgent;
    let reg = /CPU iPhone OS (.*?) like Mac OS/i;
    let verStr = userAgent.match(reg)[1];
    return verStr.replace(/_/g, '.');
}

const isVerLessThan = (ver, compareVer) => {
    let verArr = ver.split('.');
    let compareVerArr = compareVer.split('.');
    let minLength = Math.max(compareVerArr.length, verArr.length);
    for (let i = 0; i < minLength; i++) {
        if (verArr[i] < compareVerArr[i]) {
            return true;
        }
    }
    return false;
}

const createBlob = (image, width, height) => {
    const canvas = document.createElement("canvas");
    const context = canvas.getContext("2d");
    canvas.width = width;
    canvas.height = height;
    context.drawImage(image, 0, 0, width, height);
    return convertCanvasToBlob(canvas);
}

const convertCanvasToBlob = (canvas) => {
    let format = "image/jpeg";
    let base64 = canvas.toDataURL(format);
    let code = window.atob(base64.split(",")[1]);
    let aBuffer = new window.ArrayBuffer(code.length);
    let uBuffer = new window.Uint8Array(aBuffer);
    for (let i = 0; i < code.length; i++) {
        uBuffer[i] = code.charCodeAt(i);
    }
    let Builder = window.WebKitBlobBuilder || window.MozBlobBuilder;
    if (Builder) {
        let builder = new Builder();
        builder.append(uBuffer);
        return builder.getBlob(format);
    } else {
        return new window.Blob([uBuffer], {
            type: format
        });
    }
}

const change = (data, ori, quality) => {
    return new Promise(resolve => {
        let image = new Image();
        image.src = data;
        image.onload = () => {
            let degree = 0;
            let drawWidth = image.naturalWidth;
            let drawHeight = image.naturalHeight;
            let width = 0;
            let height = 0;
            //以下改变一下图片大小
            let maxSide = Math.max(drawWidth, drawHeight);
            if (maxSide > 500) {
                let minSide = Math.min(drawWidth, drawHeight);
                minSide = (minSide / maxSide) * 500;
                maxSide = 500;
                if (drawWidth > drawHeight) {
                    drawWidth = maxSide;
                    drawHeight = minSide;
                } else {
                    drawWidth = minSide;
                    drawHeight = maxSide;
                }
            }
            let canvas = document.createElement("canvas");
            canvas.width = width = drawWidth;
            canvas.height = height = drawHeight;
            let context = canvas.getContext("2d");
            if (isIos()) {
                let iosVer = getIosVerStr();
                console.log(iosVer, isVerLessThan(iosVer, '13.4'));
                if (isVerLessThan(iosVer, '13.4')) {
                    //判断图片方向,重置canvas大小,确定旋转角度,iphone默认的是home键在右方的横屏拍摄方式
                    switch (ori) {
                        //iphone横屏拍摄,此时home键在左侧
                        case 3:
                            degree = 180;
                            drawWidth = -width;
                            drawHeight = -height;
                            break;
                            //iphone竖屏拍摄,此时home键在下方(正常拿手机的方向)
                        case 6:
                            canvas.width = height;
                            canvas.height = width;
                            degree = 90;
                            drawWidth = width;
                            drawHeight = -height;
                            break;
                            //iphone竖屏拍摄,此时home键在上方
                        case 8:
                            canvas.width = height;
                            canvas.height = width;
                            degree = 270;
                            drawWidth = -width;
                            drawHeight = height;
                            break;
                    }
                }
            }
            //使用canvas旋转校正
            context.rotate((degree * Math.PI) / 180);
            context.drawImage(image, 0, 0, drawWidth, drawHeight);
            let selectImg = canvas.toDataURL("image/png", quality);
            let selectImgObj = new Image();
            selectImgObj.src = selectImg;
            selectImgObj.onload = () => {
                let canvasData = createBlob(
                    selectImgObj,
                    canvas.width,
                    canvas.height
                );
                resolve({
                    imgWidth: canvas.width,
                    imgHeight: canvas.height,
                    selectImg,
                    canvasData
                });
            };
        };
    });
}

const changeImg = (file) => {
    return new Promise(resolve => {
        let quality = 1;
        const size = file.size / 1024;
        if (size >= 600) {
            quality = 600 / size;
        }
        let reader = new FileReader();
        reader.readAsDataURL(file);

        reader.onload = ({
            currentTarget
        }) => {
            EXIF.getData(file, function () {
                let orientation = EXIF.getTag(this, "Orientation");
                change(currentTarget.result, orientation, quality).then(res => {
                    resolve(res);
                });
            });
        };
    });
}

export default changeImg;

使用

vue template

          <input @change="handler($event)" />

vue script

        handler(event) {
            const { target } = event;
            if (target && target.files && target.files.length > 0) {
                const file = target.files[0];
                changeImg(file).then(res => {
									console.log(res)
                });
            } else {
                console.log("请上传图片");
            }
        }