zoukankan      html  css  js  c++  java
  • 移动端部分安卓手机(三星,小米)竖拍上传图片预览的时候发生旋转问题

    移动端web 页面通过 input type= file 拍照的时候,部分手机图片出现量旋转了90度的问题,出现问题的机型为小米和三星,手机竖着拍的时候出现这种旋转的问题,横拍出来的照片是正常的,结合网上的解决办法总结如下:

    主要是用 Orientation 这个参数

    这个参数并不是所有的图片都有,不过通过手机拍出来的图片都是带有这个参数的,

    旋转角度 参数值
    0 1
    顺时针90 6
    逆时针90 8
    180 3

    参数为1 的时候显示正常,有问题的机型是竖拍的时候参数为6,(在实测中发现iPhone 6s ios 9系统上发现也是竖排参数为6,但是该手机的预览结果是正常的,这个原因暂时没有深究还)

    想要拿到 Orientation 这个参数,可以通过exif.js 库来获取,github地址为:https://github.com/exif-js/exif-js

    由于项目是vue 所以就使用 yarn add exif-js --save 来安装

    exif.js获取Orientation的代码为:

    EXIF.getData(file, function() { var Orientation = EXIF.getTag(this, 'Orientation'); });

    该项目要求上传的图片能实现预览压缩,因此使用fileReader.readAsDataURL(file)来实现,

    旋转用的是canvas 的rotate()方法实现的,(将上传的图片先用canvas绘制下来,绘制的过程中将需要旋转的转过来,然后在转化成base64来预览,以及传参给后端)

    ctx.rotate(angle),

    rotate方法的参数为旋转弧度,需要将角度转化为弧度:degress * Math.PI / 180,

    压缩:手机拍出来的照片太大,而且使用 base64 编码的照片会比原照片大,那么上传的时候进行压缩就非常有必要的。现在的手机像素这么高,拍出来的照片宽高都有几千像素,用 canvas 来渲染这照片的速度会相对比较慢。

    因此第一步需要先对上传照片的宽高做限制,判断宽度或高度是否超出哪个范围,则等比压缩其宽高。

    var ratio = width / height;
    if(imgWidth > imgHeight && imgWidth > xx){
    imgWidth = xx;
    imgHeight = Math.ceil(xx / ratio);
    }else if(imgWidth < imgHeight && imgHeight > yy){
    imgWidth = Math.ceil(yy * ratio);
    imgHeight = yy;
    }

    解下来就是通过 canvas.toDataURL() 方法来压缩照片质量

    canvas.toDataURL("image/jpeg", 1);

    toDataURL() 方法返回一个包含图片展示的 data URI 。使用两个参数,第一个参数为图片格式,默认为 image/png。第二个参数为压缩质量,在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。

    附上VUE项目中的完整代码为:

    <template>
      <div class="photo">
        <h1>发现身边的投资机会</h1>
        <div class="photo-input">
          <input class="photo-file" type="file" name="upload" accept="image/*"  mutiple="mutiple" @change="fileImg">
          <div class="photo-button">
            <img class="photo-logo" src="../../assets/photo-w.png" alt="">
            <span>拍照识财</span>
          </div>
        </div>
        <div v-if="text">图片上传中...</div>
        <!--<img :src="imgBase64" alt="" id="preview">-->
      </div>
    </template>
    
    <script>
    import axios from 'axios'
    import { EXIF } from 'exif-js'
    
    export default {
      name: 'photo',
      mounted(){
    
      },
      data () {
        return {
          imgBase64: '',
          text:false
        }
      },
      created () {
        localStorage.clear()
        window.aa = ''
        window.localStorage.clear()
        // localStorage.clear()
      },
      methods: {
        fileImg (e) {
          let that = this
          // localStorage.setItem('imgbase', reader.result)
          console.log(e.target.files[0])
          let Orientation
          let file = e.target.files[0]
    
    
          // this.imgPreview(e.target.files[0])
          if(file){
            EXIF.getData(file, function(){
              // var a = EXIF.pretty(this)
              // alert(a[14])
              Orientation = EXIF.getTag(this, "Orientation")
              // alert(Orientation)
            });
          }
    
    
    
          let reader = new FileReader()
    
          let img = new Image()
    
          reader.readAsDataURL(e.target.files[0])
    
          let canvas = document.createElement('canvas')
          let ctx = canvas.getContext('2d')
    
          reader.onload = (ev) => {
            // alert("图片转base64:"+reader.result)
            // this.imgBase64 = reader.result
            img.src = ev.target.result
            img.onload = function () {
              var imgWidth = this.width
              var imgHeight = this.height
    
              console.log(this.width)
              console.log(this.height)
              // alert(this.width)
              // alert(this.height)
              let ratio = imgWidth / imgHeight
              if (imgWidth > imgHeight && imgWidth > 600) {
                imgWidth = 400
                imgHeight = Math.ceil(400 / ratio)
              } else if (imgWidth < imgHeight && imgHeight > 900) {
                imgWidth = Math.ceil(200 * ratio)
                imgHeight = 200
              }
    
    
              canvas.width = imgWidth
              canvas.height = imgHeight
    
              if (Orientation && Orientation != 1) {
                switch (Orientation) {
                  case 6:
                    canvas.width = imgHeight
                    canvas.height = imgWidth
                    ctx.rotate(Math.PI / 2)
                    ctx.drawImage(this, 0, -imgHeight, imgWidth, imgHeight);
                    break;
                  case 3:
                    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);
              }
              this.imgBase64 = canvas.toDataURL("image/jpeg", 0.9)
              // console.log(this.imgBase64)
              window.aa = this.imgBase64
              // console.log(window.aa)
              var len = this.imgBase64.length
              var size = len - (len / 8) * 2
              console.log(size)
              // alert(size)
              that.$router.push('/result/industry')
    
              // reader.onload = (ev) => {
              //   // alert("图片转base64:"+reader.result)
              //   this.imgBase64 = reader.result
              //   try {
              //     // localStorage.setItem('imgBase64', reader.result)
              //     window.aa = reader.result
              //   } catch (error) {
              //     // console.log("存储localstorage失败"+error)
              //
              //   }
    
              // try {
              //   // localStorage.setItem('imgBase64', reader.result)
              //   // window.aa = reader.result
              // } catch (error) {
              //   console.log("存储localstorage失败"+error)
              // }
              // alert('base64全局存储完成')
              // this.$router.push('/result/industry')
              // alert('push完成')
            }
          }
    
        },
        imgPreview(file){
          // let _this = this
          let Orientation
          console.log(file)
          //去获取拍照时的信息,解决拍出来的照片旋转问题
          EXIF.getData(file, function(){
            var a = EXIF.pretty(this)
            // alert(a[14])
            // alert(a[Orientation])
            console.log(a)
            Orientation = EXIF.getTag(this, "Orientation")
            // alert(EXIF.getTag(this, "Orientation"))
            alert(Orientation)
    
          });
          console.log(Orientation)
    
    
        }
      }
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    .photo{
      background: #fff;
      padding:20px;
    }
    .photo h1{
      display: block;
      font-size:20px;
      padding:10px 0;
    }
    .photo-input{
      display: block;
      position: relative;
      height:80px;
      margin:50px 0;
    }
    .photo-file{
      display:block;
      100%;
      height:50px;
      position: absolute;
      z-index:2;
      opacity: 0;
    }
    .photo-button{
      display: flex;
      position: absolute;
      top: 0;
      background: #4CAF50;
       80%;
      border-radius: 50px;
      height: 50px;
      left: 10%;
      align-items: center;
      justify-content: center;
    }
    .photo-button img{
      display: block;
      34px;
    }
    .photo-button span{
      display: block;
      font-size:16px;
      color:#fff;
      padding:0 8px;
    }
    </style>
    

      

    参考链接为:https://www.imweb.io/topic/59559c01ad7fa941029740aa

  • 相关阅读:
    javascript实现数据结构:串--堆分配存储表示
    javascript实现数据结构:串--定长顺序存储表示以及kmp算法实现
    javascript实现数据结构与算法系列:队列 -- 链队列和循环队列实现及示例
    javascript实现数据结构与算法系列:栈 -- 顺序存储表示和链式表示及示例
    线性链表的例子:一元多项式
    javascript实现数据结构与算法系列:功能完整的线性链表
    javascript实现数据结构与算法系列:循环链表与双向链表
    javascript实现数据结构与算法系列:线性表的静态单链表存储结构
    javascript实现数据结构:线性表--线性链表(链式存储结构)
    javascript实现数据结构:线性表--简单示例及线性表的顺序表示和实现
  • 原文地址:https://www.cnblogs.com/keleyz/p/10310391.html
Copyright © 2011-2022 走看看