苹果手机上传拍照竖图生成的图片是横向图,处理时又遇到手机加载不上图片,求助

发布于 2022-09-03 11:28:13 字数 3262 浏览 38 评论 0

需求:
1 移动端项目
2 可上传多张图片,图片前端压缩后再上传(怕直接上传图片太大影响上传速度)

问题:
ios手机上传竖图会显示成横图(处理办法:读取图片,判断exif的方向值,根据方向值前端用canvas旋转图片)

问题:
读取图片时,电脑可以onload,可是手机onload不起作用,猜想是因为图片太大?

求助,感谢!

choose.addEventListener('change', function () {
    if (!this.files.length) return;
    var files = Array.prototype.slice.call(this.files);
    if (files.length > 9) {
        alert("最多同时只可上传9张图片");
        return;
    }
    files.forEach(function (file, i) {
        if (!/\/(?:jpeg|png|gif)/i.test(file.type)) return;
        var reader = new FileReader();
        var li = document.createElement("li");
        //获取图片大小
        var size = file.size / 1024 > 1024 ? (~~(10 * file.size / 1024 / 1024)) / 10 + "MB" : ~~(file.size / 1024) +
            "KB";
        li.innerHTML =
            '<span onclick="delImg(this.parentNode)" class="del">删除</span><span class="succ">上传成功</span><span class="progress"><i></i></span>';
        postimg.appendChild(li);
        reader.onload = function () {
            var result = this.result;
            var img = new Image();
            img.src = result;
 
 
            var rotateshow;
 
            alert(111)//这里可以执行
            img.onload = function () {
                alert(222)//这里电脑可以执行,手机执行不了
                EXIF.getData(this, function () {
 
                    EXIF.getAllTags(this);
                    Orientation = EXIF.getTag(this, 'Orientation');
                    console.log('dir:' + Orientation)
 
                    switch (Orientation) {
                    case 6:
                        //需要顺时针(向左)90度旋转
                        rotateshow = rotateImg(this, 'left');
                        break;
                    case 8:
                        //需要逆时针(向右)90度旋转
                        rotateshow = rotateImg(this, 'right');
                        break;
                    case 3:
                        //需要180度旋转
                        rotateImg(this, 'right'); //转两次 
                        rotateshow = rotateImg(this, 'right');
                        break;
                    default:
                        rotateshow = result;
                        break;
                    }
                });
                li.style.backgroundImage = "url(" + rotateshow + ")";
            }
 
            //li.style.backgroundImage = "url(" + result + ")";
            li.setAttribute('type', file.type)
 
            if (compresssign) {
                //如果图片大小小于500kb,则直接上传
                if (result.length <= maxsize) {
                    img = null;
                    //upload(result, file.type, $(li));
                    return;
                }
                //图片加载完毕之后进行压缩,然后上传
                if (img.complete) {
                    callback();
                } else {
                    img.onload = callback;
                }
 
                function callback() {
                    var data = compress(img);
                    //upload(data, file.type, $(li));
                    img = null;
                }
            } else {
                img = null;
                return;
            }
        };
        reader.readAsDataURL(file);
 
 
    })
});

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情绪操控生活 2022-09-10 11:28:13

最后用的办法是,把图片写入页面,用CSS让用户看不到这个图片,在js里图片onload就可以了

埋情葬爱 2022-09-10 11:28:13

背景

今天看到《jQuery基础》的高级Ajax里有段代码,似乎跟你前几天在网易前端群里发的提问有关系,我就查了下,你看看是否有用。
对于部分浏览器是会将图片缓存的(见《Learning jQuery 4th edition》275页)。考虑到你的调试的时候不会每次都清除缓存,所以有可能是因为这个原因,img元素的load事件在第一次加载后就触发不了。

资料

这是so上的相似问题,跳到第二个回答看下,以及其中提到的参考链接

分析

当判断img资源是否加载完成时,不能完全依赖loaderror事件,因为有些浏览器存在图片缓存的问题,所以可通过判断img标签对应的DOM对象的completenaturalWidthwidth属性来确定。
相关的三个HTMLImageElement类型实例的属性可以参考这里,如果不能翻墙的话看这里,MDN因为缺少相关页面就不ref了。
naturalWidth因为是IE9+才支持,所以兼容的话还要考虑width属性(未明确设置CSS样式或者HTML特性),图片未成功加载时两个属性的返回值都是0(其实width不是,看后面)。

尝试

可以只用complete,判断加载完成

if(img.complete) {
 // 图片已缓存时的处理代码
} else { // 图片未缓存时的处理代码
  img.onload = callback;
}

如果还要判断加载成功/失败的情况,要多检测naturalWidthwidth

var propWidth = typeof img.naturalWidth ? 'width' : 'naturalWidth';
if(img.complete){ //已缓存
  if(!!img[propWidth]){
    //加载成功
  } else {
    //加载错误
  }
} else { //未缓存
  img.onload = callback1;
  img.onerror = callback2;
}

注意: 这里的width属性是个坑,并不可信,我通过建立简易服务器用IE8chrome canary测试,如果图片加载完成,但是失败了,width返回的分别是是2820
不过,你的代码是在苹果的机器上跑,应该不存在不支持naturalWidth的情况。

结论

if(img.complete){ //因为`img`加载是异步的,这段代码是同步跑的, 加载完成就说明已缓存
  if(img.naturalWidth){
    // 加载成功
  } else {
    // 加载失败
  }
} else { // 加载未完成所以未缓存
  img.onload = successCB;
  img.onerror = errorCB;
}

希望还有帮助。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文