【uni-app】H5以及真机(android& ios解决上传图片旋转90度的问题)

又更新了下,难搞,苹果手机有些版本会旋转有些版本不会,所以还要区别下,目前只知道最新版的不会旋转,就单独处理下,目前没有打包成苹果app,所以在苹果包上有没有问题还不确定

卡了将近两天才解决完,真是头大,根据网上的方法也是卡了好久,所以又特地整理了下

h5是通过拿到旋转的值,重新用canvas画图,所以在页面需要加入canvas 元素,其中用v-if的原因,是重复上传的话之前画的不会清空掉,所以用v-if来清空。还有canvas要设置height: 100vh;width: 100vw; 才可以把上传的图片完整的画出来。然后在外一层加上overflow: hidden;就行,下面的代码片段是自己封装的组件中的片段,因为有些需要优化的就不贴出来完整的代码

    <view class="h-upload-img-content">
            <view class="h-upload-img-content-input" @click="onChangeUpload" v-if="!imgSrc">
                <text class="cross"></text>
                <!--canvas 用来解决图片旋转的-->
                <canvas canvas-id="uploadCanvas" class="upload-canvas" v-if="isCanvas"></canvas>
            </view>

            <view class="h-upload-img-content-img" v-if="imgSrc">
                <view class="h-upload-img-content-icon" @click.stop="onDelImg()"><h-icon path="icon/close" width="40" height="40" /></view>
                <h-lazy-img :src="imgSrc" mode="widthFix" preview></h-lazy-img>
            </view>
        </view>
import compressImage from '@/libs/imageUtil.js';
...
    // 选择上传文件
        onChangeUpload() {
            if (this.limt && this.limt <= this.imgList) return uni.showToast({ title: `只能上传${this.limt}个文件`, icon: 'none' });
            uni.chooseImage({
                count: this.limt || 1,
                success: res => {
                    if (res && res.tempFiles.length && res.tempFiles[0].size > 5 * 1024 * 1024) {
                        return uni.showToast({ title: '上傳圖片大小不能超過5M!', icon: 'none' });
                    }
                    this.compressImageHandler(res.tempFiles[0]);
                }
            });
        },

        // 解决有些图片会旋转的问题
        async compressImageHandler(file) {
            uni.showLoading({title: '上傳中...'});
            this.isCanvas = true; //用来清空画布
            const tempPath = await compressImage(file.path);
            this.uploadFile({ file: tempPath });
            this.isCanvas = false;
        },

        // 上传文件
        async uploadFile(file) {
            try {
                let res = await this.$api.uploadFile(file);
                uni.showToast({ title: res.msg, icon: 'none' });
                this.imgSrc = res.url;
                this.$emit('change', this.imgSrc);
            } catch (e) {
                uni.showToast({ title: e.msg, icon: 'none' });
            }
        },
注意:h5因为要拿到旋转的值,所以引用exif.js文件,这个直接在github就可以搜到,但因为img中complete这个值我拿不到,所以把js文件的974行一段条件注释掉了。
image.png

解决旋转问题的js - imageUtil.js


/**
 *  imageUtil.js
 *解决图片旋转的问题 
 * **/

import EXIF from './exif.js'


async function compressImage(path) {
    let imageInfo = await getImageInfo(path)
    let systemInfo = await getSystemInfo()

    return new Promise(function(resolve, reject) {
        // #ifdef APP-PLUS || APP-NVUE
        appCompressImage(path, imageInfo).then(res => {
            resolve(res)
        }).catch(e => {
            reject(e)
        })
        // #endif

        // #ifdef H5
        let orientation = 1;
        let img = document.createElement("img");
        img.src = path;
        img.onload = function() {
            EXIF.getData(img, function() {
                orientation = EXIF.getTag(this, 'Orientation');
                canvasImg(path, orientation, imageInfo, systemInfo).then(res => {
                    resolve(res)
                }).catch(e => {
                    reject(e)
                })

            })
        }
        img.onerror = function() {
            reject(path)
        }
        // #endif
    })
}

// app处理旋转图片
function appCompressImage(src, imageInfo) {
    return new Promise(function(resolve, reject) {
        let orientation = imageInfo.orientation;
        let rotate = 0;
        let quality = 80;
        if (plus.os.name == "iOS") {
            rotate = 0;
            quality = 25;
        } else {
            switch (orientation) {
                case 'up': //exif:1 不旋转
                    rotate = 0;
                    break;
                case 'down': //exif:3 旋转180度
                    rotate = 180;
                    break;
                case 'right': //exif:6 旋转90度
                    rotate = 90;
                    break;
                case 'left': //exif:8 旋转270度
                    rotate = 270;
                    break;
                default:
                    rotate = 0;
                    break;
            }
        }

        plus.zip.compressImage({
                src: src,
                dst: "_doc/uniapp_temp" + '/compressed/' + Math.round(new Date()) + '.png',
                format: 'png',
                quality: quality,
                width: 'auto',
                height: 'auto',
                rotate: rotate,
            },
            function(event) {
                resolve(event.target)
            },
            function(error) {
                reject(src);
            });
    })
}


// 画图片
function canvasImg(path, or, imageInfo, systemInfo) {
    return new Promise(function(resolve, reject) {
        let canvasId = 'uploadCanvas'
        const ctx = uni.createCanvasContext(canvasId)
        let scale = imageInfo.width / imageInfo.height

        // 图片参数 start
        let maxdestWidth = 1100 // 2000;
        let destWidth = imageInfo.width;
        let destHeight = imageInfo.height;

        let destCompressWidth = imageInfo.width;
        let destCompressHeight = imageInfo.height;

        // 压缩图片 最大不超过5M  1200
        // 当宽大于高的时候
        if (imageInfo.width > imageInfo.height) {
            if (imageInfo.width > maxdestWidth) {
                destCompressWidth = maxdestWidth;
                destCompressHeight = Math.floor(destCompressWidth / scale);
            } else {
                destCompressWidth = imageInfo.width * 8 / 10;
                destCompressHeight = Math.floor(destCompressWidth / scale);
            }
        }
        // 当高大于宽
        else {
            if (imageInfo.height > maxdestWidth) {
                destCompressHeight = maxdestWidth;
                destCompressWidth = Math.floor(destCompressHeight * scale);
            } else {
                destCompressHeight = imageInfo.height * 0.8;
                destCompressWidth = Math.floor(destCompressHeight * scale);
            }
        }

        destWidth = destCompressHeight
        destHeight = destCompressWidth
        // 图片参数 end


        // 画布参数 start
        let maxWidth = 300;
        let canvasW = imageInfo.width;
        let canvasH = imageInfo.height;

        let width = imageInfo.width;
        let height = imageInfo.height;

        // canvas画布不能超过最大宽
        if (canvasW > maxWidth) {
            canvasW = maxWidth;
            canvasH = Math.floor(canvasW / scale);
        }

        width = canvasW
        height = canvasH
        // 画布参数 end

        // console.log('--or---', or)
               //单独处理苹果最新版本
        if (systemInfo.model == 'iPhone' && systemInfo.system.indexOf('13.4.1') > -1) {
            ctx.drawImage(path, 0, 0, canvasW, canvasH)
            destWidth = destCompressWidth
            destHeight = destCompressHeight
        } else {
            if (or == 6) { //逆时针旋转了90
                ctx.translate(width, 0)
                ctx.rotate(Math.PI / 2)
                ctx.drawImage(path, 0, 0, canvasH, canvasW)
            } else if (or == 3) { //逆时针旋转了180
                ctx.translate(width, height)
                ctx.rotate(Math.PI)
                ctx.drawImage(path, 0, 0, canvasH, canvasW)
            } else if (or == 8) { //顺时针旋转90
                ctx.translate(0, height)
                ctx.rotate(-Math.PI / 2)
                ctx.drawImage(path, 0, 0, canvasH, canvasW)
            } else {
                ctx.drawImage(path, 0, 0, canvasW, canvasH)
                // return resolve(path);

                destWidth = destCompressWidth
                destHeight = destCompressHeight
            }
        }
        // console.log('图片原始长宽', imageInfo, maxWidth, canvasW, canvasH, width, height, destWidth, destHeight);

        ctx.draw(true, setTimeout(() => {
            uni.canvasToTempFilePath({
                x: 0,
                y: 0,
                width: width, //画布宽度
                height: height,
                destWidth: destWidth,
                destHeight: destHeight,
                fileType: 'png',
                canvasId: canvasId,
                success: (res) => {
                    resolve(res.tempFilePath)
                },
                fail: (err) => {
                    resolve(path);
                }
            })
        }, 200))
    })
}

// 获取图片信息
function getImageInfo(path) {
    return new Promise(function(resolve, reject) {
        // #ifdef APP-PLUS
        plus.io.getImageInfo({
            src: path,
            success: function(image) {
                // console.log('orientation=' + image.orientation);
                resolve(image)
            },
            fail: function(err) {
                console.log("getImageInfoErr: " + JSON.stringify(err));
                reject(err)
            }
        });
        // #endif

        // #ifdef H5 || MP-WEIXIN   
        uni.getImageInfo({
            src: path,
            success: function(image) {
                // console.log('orientation=' + image.orientation);
                resolve(image)
            },
            fail: function(err) {
                console.log("getImageInfoErr: " + JSON.stringify(err));
                reject(err)
            }
        });
        // #endif
    });
}

// 获取系统信息
function getSystemInfo(path) {
    return new Promise(function(resolve, reject) {
        uni.getSystemInfo({
            success(res) {
                resolve(res)
            },
            fail(err) {
                console.log("getSystemInfoErr: " + JSON.stringify(err));
                reject(err)
            }
        });
    });
}

export default compressImage

还有要注意的点,在ios中上传的方法设置这个才上传成功

cai

题外话,原本没处理的图片地址是一个url,我以为还要把canvas之后的base64的格式转化成url才可以上传,然而其实可以直接base64上传,当时一时没转过弯,那叫一个尴尬呀。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350