antd-mobile 移动端使用input调用摄像头拍摄图片反显时图片旋转问题

需要实现的页面效果:

《antd-mobile 移动端使用input调用摄像头拍摄图片反显时图片旋转问题》

点击头像进行图片上传;再次点击可以修改

遇到的问题:上传图片反显到框里面 图片旋转

最终解决方案:

          <div style={
  {padding:'10px 0'}}>
                  <span className={s.fileStyle}>
                    <img src={this.state.imgSrc}  alt="" className={s.imgs} id='imgBox'/>
                    <ImagePicker
                      length={1}
                      files={this.state.files}
                      onChange={this.onChange}
                      onImageClick={(index, fs) => console.log(index, fs)}
                      selectable={true}
                      accept="image/gif,image/jpeg,image/jpg,image/png"
                      disableDelete
                    />
                  </span>
                </div>
//js代码
   onChange = (files, type, index) => {
      console.log(files, type, index);
      if (type == 'add') {
        this.setState({
          files,
        });
        var file=files[files.length - 1].file;
        const windowURL = window.URL || window.webkitURL;//实现预览
        var u = navigator.userAgent;
        var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
        var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
        if(isiOS){
          console.log('ios');
          console.log(file.size/1024+'kb')
          const isLt400K = file.size /1024 < 200;
          if(!isLt400K){
            return this.getsmallpic(file)
          }else{
            this.setState({
              imgArr:files[files.length - 1].file,
              imgSrc:files[files.length - 1].url
            })
          }
        }else if(isAndroid){
          console.log('Android');
          var that=this;
          this.rotateImg(files[files.length - 1].file).then(blob => {
            document.getElementById('imgBox').src = URL.createObjectURL(blob) // 转换后的img
            this.blobToDataURL(blob, function(dataurl) {
              console.log(file.size/1024+'kb')
              const isLt400K = file.size /1024 < 200;
              if(!isLt400K){
                return that.getsmallpic(that.dataURLtoFile(dataurl,file.name))
              }else{
                this.setState({
                  imgArr:files[files.length - 1].file
                })
              }
            });
          });
        }else{
          console.log('pc')
          console.log(file.size/1024+'kb')
          const isLt400K = file.size /1024 < 200;
          if(!isLt400K){
            return this.getsmallpic(file)
          }else{
            this.setState({
              imgArr:files[files.length - 1].file,
              imgSrc:files[files.length - 1].url
            })
          }
        }
      }
    }
  blobToDataURL(blob, callback) {
    var a = new FileReader();
    a.onload = function(e) {
      callback(e.target.result);
    }
    a.readAsDataURL(blob);
    return a;
  }


//图片翻转

   rotateImg(file) {
    return new Promise((resolve, reject) => {
      let img = new Image();
      img.src = window.URL.createObjectURL(file);
      img.onload = () => {
        util.addScript('https://cdn.jsdelivr.net/npm/exif-js', () => {
          var EXIF=window.EXIF;
          // 获取图片源数据 上面已经引入EXIF全局变量
          EXIF.getData(img, function () {
            // 获取图片orientation值
            console.log(EXIF.getAllTags(this))
            let orientation = EXIF.getTag(this, "Orientation");
            let canvas = document.createElement("canvas");
            let ctx = canvas.getContext("2d");
            switch (orientation) {
              case 3: // 旋转180°
                canvas.width = img.width;
                canvas.height = img.height;
                ctx.rotate((180 * Math.PI) / 180);
                ctx.drawImage(img, -img.width, -img.height, img.width, img.height);
                break;
              case 6: // 旋转90°
                canvas.width = img.height;
                canvas.height = img.width;
                ctx.rotate((90 * Math.PI) / 180);
                ctx.drawImage(img, 0, -img.height, img.width, img.height);
                break;
              case 8: // 旋转-90°
                canvas.width = img.height;
                canvas.height = img.width;
                ctx.rotate((-90 * Math.PI) / 180);
                ctx.drawImage(img, -img.width, 0, img.width, img.height);
                break;
              default: // 没有源信息的图片和正常的图片是不需要旋转的
                canvas.width = img.width;
                canvas.height = img.height;
                ctx.drawImage(img, 0, 0, img.width, img.height);
                break;
            }
            // 处理完返回 (这里返回都是被压缩的,根据实际情况更改正常的图片处理方式)
            canvas.toBlob(file => resolve(file), 'image/jpeg', 0.8)
          })
        });
      }
    })
  }
//图片压缩
  dataURLtoFile(dataurl, filename) {
      var arr = dataurl.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 File([u8arr], filename, {type:mime});
    }
    // 图片压缩
    getsmallpic(file){
      return new Promise((resolve,reject)=>{
        //对图片进行压缩
        const reader = new FileReader()
        const image = new Image()
        image.onload = (imageEvent) => {
          const canvas = document.createElement('canvas');
          const context = canvas.getContext('2d');
          const width = image.width * 0.5
          const height = image.height * 0.5
          canvas.width = width;
          canvas.height = height;
          context.clearRect(0, 0, width, height);
          context.drawImage(image, 0, 0, width, height);
          const dataUrl = canvas.toDataURL(file.type);
          const blobData = this.dataURLtoFile(dataUrl,file.name);
          if(blobData){
            if(blobData.size /1024 < 400){
              Object.assign(blobData,{uid:blobData.lastModified});
              const windowURL = window.URL || window.webkitURL;//实现预览
              resolve(blobData)
              this.setState({
                imgSrc:windowURL.createObjectURL(blobData)
              })
              this.setState({
                imgArr:blobData
              })
            }else{
              this.getsmallpic(blobData)
            }

          }else{
            reject()
          }

        }
        reader.onload = (e => { image.src = e.target.result; });
        reader.readAsDataURL(file);
      })
    }




//css片段

.fileStyle{
  position: relative;
  display: block;
  width: 160px;
  height: 160px;
  border-radius: 50%;
  text-align: center;
  background: #f5f5f5;
  margin: 0 auto;
  border: 1px solid #0486FE;
  overflow: hidden;
}
.imgs {
  width: 160px !important;
  height: 160px !important;
  border-radius: 50%;
  position: relative;
}
.fileStyle input {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 9;
  width: 160px;
  height: 160px;
  opacity: 0;
}
:global(.am-image-picker .am-image-picker-list .am-flexbox){
  width: 165px !important;
  height: 165px !important;
  border-radius: 50%;
  position: absolute;
  top:0;
  left: 0;
  background-color: transparent!important;
}
:global(.am-image-picker-list){
  padding: 0 0 0 0!important;
  margin-bottom: 0!important;
}
:global(.am-image-picker-upload-btn){
  border-radius: 50% !important;
  border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item .am-image-picker-item-content){
  border-radius: 50% !important;
  border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item){
  opacity: 0!important;
}

 

解题历程:

1.原始问题:刚开始使用input type类型为file上传文件 获取图片路径反显到img里面;遇到了几部手机会出现图片反显翻转的问题

<img src={this.state.imgSrc}  alt="" className={s.imgs} id='imgBox'/>
                    <input
                      accept="image/png, image/jpeg,image/jpg"
                      type = "file"
                      id = "faceHuman"
                      className={s.input}
                      onChange={this.humanChange.bind(this)}
                    />



//js方法
    humanChange(e){
      const windowURL = window.URL || window.webkitURL;//实现预览
      const file = document.getElementById('faceHuman').files[0];
       console.log(file.size/1024+'kb')
       const isLt400K = file.size /1024 < 200;
       if(!isLt400K){
         return this.getsmallpic(file)  //压缩图片的方法
       }else{
         this.setState({
           imgSrc:windowURL.createObjectURL(file)
         })
        this.setState({
           imgArr:file
         })
       }
    }

//图片压缩的方法
    dataURLtoFile(dataurl, filename) {
        var arr = dataurl.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 File([u8arr], filename, {type:mime});
      }
      // 图片压缩
       getsmallpic(file){
        return new Promise((resolve,reject)=>{
            //对图片进行压缩
            const reader = new FileReader()
            const image = new Image()
            image.onload = (imageEvent) => {
              const canvas = document.createElement('canvas');
              const context = canvas.getContext('2d');
              const width = image.width * 0.5
              const height = image.height * 0.5
              canvas.width = width;
              canvas.height = height;
              context.clearRect(0, 0, width, height);
              context.drawImage(image, 0, 0, width, height);
              const dataUrl = canvas.toDataURL(file.type);
              const blobData = this.dataURLtoFile(dataUrl,file.name);
              if(blobData){
                if(blobData.size /1024 < 400){
                  Object.assign(blobData,{uid:blobData.lastModified});
                    const windowURL = window.URL || window.webkitURL;//实现预览
                  resolve(blobData)
                  this.setState({
                    imgSrc:windowURL.createObjectURL(blobData),
                    class:1
                   }) 
                   this.setState({
                    imgArr:blobData
                })
                }else{
                  this.getsmallpic(blobData)
                }
                
              }else{
                reject()
              }
              
            }
            reader.onload = (e => { image.src = e.target.result; });
            reader.readAsDataURL(file);
        })
      }

反显到不同的手机上会出现不同的翻转情况;各种百度之后;找到了一个exif的插件;在方法上进行了修改

 2.第一次解决方法:(使用exif插件翻转处理图片)

<img src={this.state.imgSrc}  alt="" className={s.imgs} id='imgBox'/>
                    <input
                      accept="image/png, image/jpeg,image/jpg"
                      type = "file"
                      id = "faceHuman"
                      className={s.input}
                      onChange={this.humanChange.bind(this)}
                    />



//js方法
    humanChange(e){
      const windowURL = window.URL || window.webkitURL;//实现预览
      const file = document.getElementById('faceHuman').files[0];
      this.rotateImg(file).then(blob => {
        document.getElementById('imgBox').src = URL.createObjectURL(blob) // 转换后的img
      })
      this.setState({
        imgArr:file
      })
    }

//图片旋转的方法&压缩
   rotateImg(file) {
    return new Promise((resolve, reject) => {
      let img = new Image();
      img.src = window.URL.createObjectURL(file);
      img.onload = () => {
        util.addScript('https://cdn.jsdelivr.net/npm/exif-js', () => {
          var EXIF=window.EXIF;
          // 获取图片源数据 上面已经引入EXIF全局变量
          EXIF.getData(img, function () {
            // 获取图片orientation值
            console.log(EXIF.getAllTags(this))
            let orientation = EXIF.getTag(this, "Orientation");
            let canvas = document.createElement("canvas");
            let ctx = canvas.getContext("2d");
            switch (orientation) {
              case 3: // 旋转180°
                canvas.width = img.width;
                canvas.height = img.height;
                ctx.rotate((180 * Math.PI) / 180);
                ctx.drawImage(img, -img.width, -img.height, img.width, img.height);
                break;
              case 6: // 旋转90°
                canvas.width = img.height;
                canvas.height = img.width;
                ctx.rotate((90 * Math.PI) / 180);
                ctx.drawImage(img, 0, -img.height, img.width, img.height);
                break;
              case 8: // 旋转-90°
                canvas.width = img.height;
                canvas.height = img.width;
                ctx.rotate((-90 * Math.PI) / 180);
                ctx.drawImage(img, -img.width, 0, img.width, img.height);
                break;
              default: // 没有源信息的图片和正常的图片是不需要旋转的
                canvas.width = img.width;
                canvas.height = img.height;
                ctx.drawImage(img, 0, 0, img.width, img.height);
                break;
            }
            // 处理完返回 (这里返回都是被压缩的,根据实际情况更改正常的图片处理方式)
            canvas.toBlob(file => resolve(file), 'image/jpeg', 0.8)
          })
        });
      }
    })
  }

结论:公司里除了一部苹果11的手机之外都展示正常 but 领导手机型号很巧的和这位同学型号一致 so~ 继续找方法

 

3.第二次解决方案:由于这个移动端基于ant-mobile框架写的 所以我决定使用一下这个里面的上传图片的组件

ImagePicker (由于组件上这个方法和实际使用中有点差别 所以原有的组件上进行了样式修改)
<div style={
  {padding:'10px 0'}}>
                  <span className={s.fileStyle}>
                    <img src={this.state.imgSrc}  alt="" className={s.imgs} id='imgBox'/>
                    <ImagePicker
                      length={1}
                      files={this.state.files}
                      onChange={this.onChange}
                      onImageClick={(index, fs) => console.log(index, fs)}
                      selectable={true}
                      accept="image/gif,image/jpeg,image/jpg,image/png"
                      disableDelete
                    />
                  </span>
                </div>

//js代码
    onChange = (files, type, index) => {
      console.log(files, type, index);
      if (type == 'add') {
          this.setState({
            files,
          });
          this.rotateImg(files[files.length - 1].file).then(blob => {
            document.getElementById('imgBox').src = URL.createObjectURL(blob) // 转换后的img
          })
          this.setState({
            imgArr:files[files.length - 1].file
          })
        }
     }
//css代码
/*修改选择弹框的样式*/
:global(.am-image-picker .am-image-picker-list .am-flexbox){
  width: 165px !important;
  height: 165px !important;
  border-radius: 50%;
  position: absolute;
  top:0;
  left: 0;
  background-color: transparent!important;
}
:global(.am-image-picker-list){
  padding: 0 0 0 0!important;
  margin-bottom: 0!important;
}
:global(.am-image-picker-upload-btn){
  border-radius: 50% !important;
  border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item .am-image-picker-item-content){
  border-radius: 50% !important;
  border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item){
  opacity: 0!important;
}

结论:使用组件测试之后,得出结论:安卓手机直接使用这个组件会翻转;最后决定写个判断 如果是安卓手机 使用exif插件进行图片处理反显;如果是苹果手机原来得组件赋值。

4.第三次解决方案:(翻转完成后 可以适配)

             <div style={
  {padding:'10px 0'}}>
                  <span className={s.fileStyle}>
                    <img src={this.state.imgSrc}  alt="" className={s.imgs} id='imgBox'/>
                    <ImagePicker
                      length={1}
                      files={this.state.files}
                      onChange={this.onChange}
                      onImageClick={(index, fs) => console.log(index, fs)}
                      selectable={true}
                      accept="image/gif,image/jpeg,image/jpg,image/png"
                      disableDelete
                    />
                  </span>
                </div>
//js代码
   onChange = (files, type, index) => {
      console.log(files, type, index);
      if (type == 'add') {
        this.setState({
          files,
        });
        var u = navigator.userAgent;
        var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
        var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
        if(isiOS){
          console.log('ios')
          this.setState({
            imgArr:files[files.length - 1].file,
            imgSrc:files[files.length - 1].url
          })
        }else if(isAndroid){
          console.log('Android')
          this.rotateImg(files[files.length - 1].file).then(blob => {
            document.getElementById('imgBox').src = URL.createObjectURL(blob) // 转换后的img
          })
          this.setState({
            imgArr:files[files.length - 1].file
          })
        }else{
          console.log('pc')
          this.setState({
            imgArr:files[files.length - 1].file,
            imgSrc:files[files.length - 1].url
          })
        }
      }
    }


//图片翻转&压缩

   rotateImg(file) {
    return new Promise((resolve, reject) => {
      let img = new Image();
      img.src = window.URL.createObjectURL(file);
      img.onload = () => {
        util.addScript('https://cdn.jsdelivr.net/npm/exif-js', () => {
          var EXIF=window.EXIF;
          // 获取图片源数据 上面已经引入EXIF全局变量
          EXIF.getData(img, function () {
            // 获取图片orientation值
            console.log(EXIF.getAllTags(this))
            let orientation = EXIF.getTag(this, "Orientation");
            let canvas = document.createElement("canvas");
            let ctx = canvas.getContext("2d");
            switch (orientation) {
              case 3: // 旋转180°
                canvas.width = img.width;
                canvas.height = img.height;
                ctx.rotate((180 * Math.PI) / 180);
                ctx.drawImage(img, -img.width, -img.height, img.width, img.height);
                break;
              case 6: // 旋转90°
                canvas.width = img.height;
                canvas.height = img.width;
                ctx.rotate((90 * Math.PI) / 180);
                ctx.drawImage(img, 0, -img.height, img.width, img.height);
                break;
              case 8: // 旋转-90°
                canvas.width = img.height;
                canvas.height = img.width;
                ctx.rotate((-90 * Math.PI) / 180);
                ctx.drawImage(img, -img.width, 0, img.width, img.height);
                break;
              default: // 没有源信息的图片和正常的图片是不需要旋转的
                canvas.width = img.width;
                canvas.height = img.height;
                ctx.drawImage(img, 0, 0, img.width, img.height);
                break;
            }
            // 处理完返回 (这里返回都是被压缩的,根据实际情况更改正常的图片处理方式)
            canvas.toBlob(file => resolve(file), 'image/jpeg', 0.8)
          })
        });
      }
    })
  }


//css片段

.fileStyle{
  position: relative;
  display: block;
  width: 160px;
  height: 160px;
  border-radius: 50%;
  text-align: center;
  background: #f5f5f5;
  margin: 0 auto;
  border: 1px solid #0486FE;
  overflow: hidden;
}
.imgs {
  width: 160px !important;
  height: 160px !important;
  border-radius: 50%;
  position: relative;
}
.fileStyle input {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 9;
  width: 160px;
  height: 160px;
  opacity: 0;
}
:global(.am-image-picker .am-image-picker-list .am-flexbox){
  width: 165px !important;
  height: 165px !important;
  border-radius: 50%;
  position: absolute;
  top:0;
  left: 0;
  background-color: transparent!important;
}
:global(.am-image-picker-list){
  padding: 0 0 0 0!important;
  margin-bottom: 0!important;
}
:global(.am-image-picker-upload-btn){
  border-radius: 50% !important;
  border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item .am-image-picker-item-content){
  border-radius: 50% !important;
  border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item){
  opacity: 0!important;
}

结论:图片上传到后台没有压缩 之后进行图片压缩处理

之后解决方法为最上面的解决方案

完美解决~

    原文作者:small_fox_dtt
    原文地址: https://blog.csdn.net/small_fox_dtt/article/details/106785966
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞