靈兒
靈兒
  • 发布:2019-04-25 16:36
  • 更新:2020-05-21 13:47
  • 阅读:4967

【报Bug】Hello uni-app 模板中,H5平台图片选择拍照显示会旋转-90°

分类:uni-app

Hello uni-app 模板 https://uniapp.dcloud.io/h5/pcguide.html
接口---媒体---图片,在图片页面操作,点击“+”,选择拍照显示的图片会旋转-90°,选择图库显示的图片是正确的

1、型号:iPhone XR ,版本:IOS 12.2,微信版本:V 7.0.3,微信扫码进入

2、型号:Mi Note3,版本:MIUI 10.3,微信版本:V 7.0.4,微信扫码进入

2019-04-25 16:36 负责人:无 分享
已邀请:
5***@qq.com

5***@qq.com

说下场景,uniapp开发移动端h5页面,在选择手机相册图片及拍照图片时,会发生旋转90度问题。废话不多少,直接说思路。
1.判断图片是否旋转,这里的坑是chooseImage返回的是临时路径,而uniapp并没有提供h5中的保存临时文件的api,所以这里用的是ajax请求 返回的临时路径(Blob Url格式的),请求回来的blob二进制数据可以让我们得到图片的大小已经方向等图片属性
2.对旋转图片进行处理 (旋转 压缩) ,这里网上很多网友使用的是exif-js,但我是在网上找了别人的方法,发现也好使,代码会在最后统一粘贴
这一步遇到的坑是,由于最后图片处理后需要上传服务端(OSS),所以我提前把处理旋转得到的base64转成了临时文件的url,但发现转换的url 本地浏览器能打开,但手机上无法显示。只能把这一步转换放在了最后上传处

var imagePathArr = e.tempFilePaths  
var promiseArr = []  
                            var resArr = []  
                            for (let i = 0; i < imagePathArr.length; i++) {  

                                let promise = new Promise(function(resolve, reject) {  
                                    var obj = {  
                                        index: i  
                                    }  
                                    var url = imagePathArr[i];  

                                    var xhr = new XMLHttpRequest();  
                                    xhr.open('GET', url, true);  
                                    xhr.responseType = "blob";  
                                    xhr.onload = function() {  
                                        if (this.status == 200) {  
                                            var blob = this.response;  
                                            var imgSize = blob.size / 1024  
                                            // alert(imgSize)  
                                            const reader = new FileReader();  
                                            reader.readAsDataURL(blob);  
                                            /* eslint-disable func-names */  
                                            // 箭头函数会改变this,所以这里不能用肩头函数  
                                            reader.onloadend = function(res) {  
                                                // this.result就是转化后的结果  
                                                var img_base64 = res.target.result;  
                                                if (imgSize > _self.$config.imageSize) { // 需要压缩处理  
                                                    _self.photoCompress(img_base64, {  
                                                        quality: 0.5  
                                                    }, function(tempBase64) {  
                                                        _self.getOrientation(blob, function(orientation) {  
                                                            // @param {string} img 图片的base64  
                                                            // @param {int} dir exif获取的方向信息  
                                                            // @param {function} next 回调方法,返回校正方向后的base64  
                                                            if (orientation == 3 || orientation == 6 || orientation == 8) { // 图片发生旋转  
                                                                _self.getImgData(tempBase64, orientation, function(res1) {  
                                                                    _self.base64ByBlob(res1, function(blobObj) {  
                                                                        var url = window.URL.createObjectURL(blobObj)  
                                                                        obj.url = res1  
                                                                        resolve(obj)  
                                                                    })  
                                                                })  
                                                            } else {  
                                                                obj.url = tempBase64  
                                                                resolve(obj)  
                                                            }  
                                                        });  
                                                    })  
                                                } else {  
                                                    _self.getOrientation(blob, function(orientation) {  
                                                        // @param {string} img 图片的base64  
                                                        // @param {int} dir exif获取的方向信息  
                                                        // @param {function} next 回调方法,返回校正方向后的base64  
                                                        if (orientation == 3 || orientation == 6 || orientation == 8) { // 图片发生旋转  
                                                            _self.getImgData(img_base64, orientation, function(res1) {  

                                                                _self.base64ByBlob(res1, function(blobObj) {  
                                                                    var url = window.URL.createObjectURL(blobObj)  
                                                                    obj.url = res1  
                                                                    resolve(obj)  
                                                                })  
                                                            })  
                                                        } else {  
                                                            obj.url = url  
                                                            resolve(obj)  
                                                        }  
                                                    });  
                                                }  
                                            };  
                                        }  
                                    }  
                                    xhr.send();  
                                })  
                                promiseArr.push(promise);  
                            }  
                            Promise.all(promiseArr).then(res => {  
                                var imgArr = []  
                                for (var i = 0; i < res.length; i++) {  
                                    imgArr.push(res[i].url)  
                                    _self.imageList.push(res[i].url)  
                                }  
                                _self.$emit('add', {  
                                    currentImages: imgArr,  
                                    allImages: _self.imageList  
                                })  
                                _self.$emit('input', _self.imageList)  
                            })  

//将以base64的图片url数据转换为Blob  
            convertBase64UrlToBlob(urlData) {  
                var arr = urlData.split(','),  
                    mime = arr[0].match(/:(.*?);/)[1],  
                    bstr = atob(arr[1]),  
                    n = bstr.length,  
                    u8arr = new Uint8Array(n);  
                while (n--) {  
                    u8arr[n] = bstr.charCodeAt(n);  
                }  
                return new Blob([u8arr], {  
                    type: mime  
                });  
            },  
            /*  
                压缩图片 三个参数  
                path:图片地址 base64  
                obj:一个是文件压缩的后宽度,宽度越小,字节越小  
                callback:回调函数  
            */  
            photoCompress(path, obj, callback) {  
                var img = new Image();  
                img.src = path;  
                img.onload = function() {  
                    var that = this;  
                    // 默认按比例压缩  
                    var w = that.width,  
                        h = that.height,  
                        scale = w / h;  
                    w = obj.width || w;  
                    h = obj.height || (w / scale);  
                    var quality = 0.7; // 默认图片质量为0.7  
                    //生成canvas  
                    var canvas = document.createElement('canvas');  
                    var ctx = canvas.getContext('2d');  
                    // 创建属性节点  
                    var anw = document.createAttribute("width");  
                    anw.nodeValue = w;  
                    var anh = document.createAttribute("height");  
                    anh.nodeValue = h;  
                    canvas.setAttributeNode(anw);  
                    canvas.setAttributeNode(anh);  
                    ctx.drawImage(that, 0, 0, w, h);  
                    // 图像质量  
                    if (obj.quality && obj.quality <= 1 && obj.quality > 0) {  
                        quality = obj.quality;  
                    }  
                    // quality值越小,所绘制出的图像越模糊  
                    var base64 = canvas.toDataURL('image/jpeg', quality);  
                    // 回调函数返回base64的值  
                    callback(base64);  
                }  
            },  
            // base64转blob  
            base64ByBlob(base64, callback) {  
                var arr = base64.split(','),  
                    mime = arr[0].match(/:(.*?);/)[1],  
                    bstr = atob(arr[1]),  
                    n = bstr.length,  
                    u8arr = new Uint8Array(n);  
                while (n--) {  
                    u8arr[n] = bstr.charCodeAt(n);  
                }  
                console.log(new Blob([u8arr], {  
                    type: mime  
                }))  
                callback(new Blob([u8arr], {  
                    type: mime  
                }))  
            },  
            // 获取图片当前方向  
            getOrientation(file, callback) {  
                var reader = new FileReader();  

                reader.onload = function(event) {  
                    var view = new DataView(event.target.result);  

                    if (view.getUint16(0, false) != 0xFFD8) return callback(-2);  

                    var length = view.byteLength,  
                        offset = 2;  

                    while (offset < length) {  
                        var marker = view.getUint16(offset, false);  
                        offset += 2;  

                        if (marker == 0xFFE1) {  
                            if (view.getUint32(offset += 2, false) != 0x45786966) {  
                                return callback(-1);  
                            }  
                            var little = view.getUint16(offset += 6, false) == 0x4949;  
                            offset += view.getUint32(offset + 4, little);  
                            var tags = view.getUint16(offset, little);  
                            offset += 2;  

                            for (var i = 0; i < tags; i++)  
                                if (view.getUint16(offset + (i * 12), little) == 0x0112)  
                                    return callback(view.getUint16(offset + (i * 12) + 8, little));  
                        } else if ((marker & 0xFF00) != 0xFF00) break;  
                        else offset += view.getUint16(offset, false);  
                    }  
                    return callback(-1);  
                };  

                reader.readAsArrayBuffer(file.slice(0, 64 * 1024));  
            },  
            // @param {string} img 图片的base64  
            // @param {int} dir exif获取的方向信息  
            // @param {function} next 回调方法,返回校正方向后的base64  
            getImgData(img, dir, next) {  
                var image = new Image();  
                image.onload = function() {  
                    var degree = 0,  
                        drawWidth, drawHeight, width, height;  
                    drawWidth = this.naturalWidth;  
                    drawHeight = this.naturalHeight;  
                    //以下改变一下图片大小  
                    var maxSide = Math.max(drawWidth, drawHeight);  
                    if (maxSide > 1024) {  
                        var minSide = Math.min(drawWidth, drawHeight);  
                        minSide = minSide / maxSide * 1024;  
                        maxSide = 1024;  
                        if (drawWidth > drawHeight) {  
                            drawWidth = maxSide;  
                            drawHeight = minSide;  
                        } else {  
                            drawWidth = minSide;  
                            drawHeight = maxSide;  
                        }  
                    }  
                    var canvas = document.createElement('canvas');  
                    canvas.width = width = drawWidth;  
                    canvas.height = height = drawHeight;  
                    var context = canvas.getContext('2d');  
                    //判断图片方向,重置canvas大小,确定旋转角度,iphone默认的是home键在右方的横屏拍摄方式  
                    switch (dir) {  
                        //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(this, 0, 0, drawWidth, drawHeight);  
                    //返回校正图片  
                    next(canvas.toDataURL("image/png"));  
                }  
                image.src = img;  
            }  

这个功能也是刚写完,可能有些地方还有问题,大的方向上是正确的。希望能帮助大家

2***@qq.com

2***@qq.com - ddd

同问题。。

2***@qq.com

2***@qq.com - ddd

解决了吗

  • 靈兒 (作者)

    木有。

    2019-04-28 13:51

fffsfgds

fffsfgds

请问 这个问题解决了么

口区

口区 -

同样的问题

fffsfgds

fffsfgds

这个问题已经解决 稍后会总结一下 然后公布出来 急需的可私聊我 q 二四零3799一八六

5***@qq.com

5***@qq.com

这个是生成画布的时候造成的,需要更改下生成方式吧。。

z***@126.com

z***@126.com

请问解决了吗

5***@qq.com

5***@qq.com

https://www.jianshu.com/p/8afd55beca5a

s***@163.com

s***@163.com

同问题。。

5***@qq.com

5***@qq.com

最后上传图片时,进行判断,base64格式的话,先转成Blob URL格式,在进行阿里云oss上传

var filePath = tempFilePaths[_i]  
// 判断是否需要base64转换  
var reg = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s]*?)\s*$/i;  
if(reg.test(filePath)){  
    _this.base64ByBlob(filePath, function(blobObj) {  
    filePath = window.URL.createObjectURL(blobObj)  
   })  
}
yyer

yyer

如何解决这个问题

花开美时

花开美时 - F2E小助理

这个问题都没有官方出来说明一下?选择确实碰到好多机型都会出现使用uni.chooseImage选择照片之后自动逆时针旋转90度

  • 风残落叶

    一样,app端还有小程序都不知道怎么处理

    2020-07-02 11:21

该问题目前已经被锁定, 无法添加新回复