h5 input type=file ios拍照相片旋转90度修正 前端图片利用canvas处理压缩 vue图片上传优化处理

直接进入正题

input type=file 是前端处理图片上传的必要途径  这里说一下

第一个需求  如果用户点击type=file的按钮 只想完成调用照相功能 而不用选取照片功能   

其实 input type=file标签上还是有很多 特殊好玩的属性的   我们列举一下

<input type="file" accept="image/*" capture="camera">
<input type="file" accept="video/*" capture="camcorder">
<input type="file" accept="audio/*" capture="microphone">
/*
accept规定可通过文件上传控件提交的文件类型;
capture表示的是系统所捕获的默认设备,camera:照相机;camcorder:摄像机;microphone:录音。
*/
       
<input type="file" accept="image/*" >
<input type="file" accept="video/*" >
<input type="file" accept="audio/*" >
/*
如果不加上capture,则只会显示相应的,例如上述三种依次是:拍照或图库,录像或图库,
录像或拍照或图库,加上capture之后不会调用图库。
其中还有一个属性multiple,支持多选,当支持多选时,multiple优先级高于capture,
所以只用写成:<input type="file" accept="image/*" multiple>就可以
*/

当我们修改默认的capture的时候 就是默认调起什么方式了    

不过我们单位的需求 是 只想选择相册 想关闭掉拍照的唤起  这里百度很多  其中 回复最多的是添加multiple属性

原理是  这个属性是要可以多张选择的 而你开启了多张选择 就会关闭掉照相了     

不过我这里测试后 发现只有安卓生效  ios 微信内置无效 还是可以调用拍照功能

2 正题 如何进行压缩  和 旋转  这里我将方法进行了抽离  下面贴出代码

a. 利用EXIF 来进行是否需要旋转的确认    

b. npm install exif-js -S  进行下载 (注意 不要下载成 exif了 很容易弄混 不过2个模块并不是一个功能)

c. 返回的内容是我写的 即result.flag是true 则需要通过Orientation去修正; false则无需处理

扫描二维码关注公众号,回复: 10625663 查看本文章
const EXIF = require('exif-js')    // 引入


// vue method里的方法


isNeedFixPhoto(file){
       return new Promise(function (resolve,reject) {
          EXIF.getData(file, function() {
            var Orientation = EXIF.getTag(this, 'Orientation');
            if(Orientation && Orientation != 1){
              //图片角度不正确
              resolve({flag:true,Orientation:Orientation})
            }else{
              //不需处理直接上传
              resolve({flag:false,Orientation:Orientation})
            }
          });
        })
      },


// 调用

 const result=await this.isNeedFixPhoto(file);

d.利用 方法 将file文件 读成base64码 

// 定义方法
file2Base64(file) {
        return new Promise(function (resolve, reject) {
          let reader = new FileReader();
          reader.readAsDataURL(file);
          reader.onload = function (ev) {
            resolve(ev.target.result);
          }
        })
      },


// 方法调用
const resultBase64=await this.file2Base64(file);

e. 结合上面2步  有了是否需要修正的判断 也有了文件的base64码 下面处理判断 

// 整体修正方法
async repairPhoto(file,num,w){
        const result=await this.isNeedFixPhoto(file);
        const resultBase64=await this.file2Base64(file);
        const Orientation = result.Orientation;
        const numb = num || 1;
        if(result.flag){  // 处理旋转
            return await this.best4Photo(resultBase64,Orientation,numb,w)
        }else{            // 不处理旋转
            return await this.best4Photo(resultBase64,1,numb,w)
        }
      },
// 压缩处理选中的方法
best4Photo(resultBase64,Orientation,num,w){
        return new Promise(function (resolve, reject) {
          let image = new Image();
          image.src = resultBase64;
          image.onload = function () {
            // var imgWidth = this.width,
            //   imgHeight = this.height; //获取图片宽高

            var imgWidth = w,
              imgHeight = w*this.height/this.width; //获取图片宽高
            var canvas = document.createElement("canvas");
            var ctx = canvas.getContext('2d');
            canvas.width = imgWidth;
            canvas.height = imgHeight;
            if(Orientation && Orientation != 1){
              switch(Orientation){
                case 6:     // 旋转90度
                  canvas.width = imgHeight;
                  canvas.height = imgWidth;
                  ctx.rotate(Math.PI / 2);
                  ctx.drawImage(this, 0, -imgHeight, imgWidth, imgHeight);
                  break;
                case 3:// 旋转180度
                  ctx.rotate(Math.PI);
                  ctx.drawImage(this, -imgWidth, -imgHeight, imgWidth, imgHeight);
                  break;
                case 8:     // 旋转-90度
                  canvas.width = imgHeight;
                  canvas.height = imgWidth;
                  ctx.rotate(3 * Math.PI / 2);
                  ctx.drawImage(this, -imgWidth, 0, imgWidth, imgHeight);
                  break;
              }
            }else{
              ctx.drawImage(this, 0, 0, imgWidth, imgHeight);
            }
            const result = canvas.toDataURL("image/jpeg",num);
            resolve(result)
          }
        })
      },

best4photo里 image.onload 是为了 当时想对图片不进行 尺寸的更改 只进行质量度的处理  但是后来总和考虑  还是利用外部参数去设定压缩后的图片尺寸  这里这个方法其实可以省略的  

主要 switch 判断了要旋转的角度 然后利用canvas 重新旋转后绘制图片 

canvas.toDataUrl 这个方法的第二个参数是用来处理 压缩质量的   可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他参数会被忽略

这样我们就完成了图片的旋转和压缩的处理   虽然看似方法很多  但最后的目的 是为了 剥离代码  方便重复利用     其实代码上还有一些可以优化的地方  这里暂不做处理了

如果你觉得我帮到你了,买个肥宅快乐水,怎么样?哈哈哈哈哈哈

发布了100 篇原创文章 · 获赞 75 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/gaoqiang1112/article/details/90603362