vue 图片压缩使用exif调整ios上旋转90度方向并上传

github地址

安装方式:

npm install exif-js --save

或游览器本地引入:

<script src="exif.js"></script>

读取图像的元数据:

在最近的活动中,遇到了用户上传图片时图片方向偏转的问题。针对这个问题,通过google得到exif.js可以获取照片的元数据,例如:拍照方向、相机设备型号、拍摄时间、ISO 感光度、GPS 地理位置等数据。EXIF 数据主要来自拍摄的照片,多用于移动端开发,PC 端也会用到,兼容性良好,兼容主流浏览器,IE10 以下不支持。

使用方法:

EXIF.getData(document.getElementById('imgElement'), function(){
  EXIF.getAllTags(this);
  EXIF.getTag(this, 'Orientation');
});

API:

名称    说明
EXIF.getData(img, callback)    获取图像的数据
EXIF.getTag(img, tag)    获取图像的某个数据
EXIF.getAllTags(img)    获取图像的全部数据,值以对象的方式返回
EXIF.pretty(img)    获取图像的全部数据,值以字符串的方式返回

HTML代码:

<div  @touchend="toAvatar()">
    <div id="imgPlaceholder" v-if="!show"></div>
    <img id="avatar" v-else :src="userInfo.headerStatus ? userInfo.avatar : defaultImg" :style="{borderRadius:'50%',width:'0.93rem',height:'0.93rem'}">
    <input type="file" @change="imageFileChange($event)" ref="file" accept="image/*"  multiple style="display:none">
</div>
<div class="test">
    <img :src="compressFrondImage" style="width:100%"> <!--压缩之前的图片-->
    <img :src="compressEndImage" width="200"> <!--压缩之后的图片-->
</div>

JavaScript代码:

<script>
import EXIF from 'exif-js';
import { _updateAvatar } from "../axios/index.js";
import Mint from 'mint-ui';
export default {
    name:'',
    data() {
        return {
            show:false,
            compressFrondImage:'',// 压缩之前的图片
            compressEndImage:'', // 压缩之后的图片
            defaultImg:'img/my/default.png',
            userInfo: {
                avatar:'',
                headerStatus:null
            }
        }
    },
    methods:{
        toAvatar() {
          this.$refs.file.click();
        },
        /**
         * 图片文件发生变化
         */
        imageFileChange (e) {
          this.file = e.target.files[0];
          if (!this.file) return;
          let fileSize = (this.file.size/1024/1024).toFixed(4);
          console.log('oldSize: '+fileSize+' M');
          if (this.file) {
            // FileReader
            let reader = new FileReader()
            reader.readAsDataURL(this.file)
            reader.onload = (e) => {
              // console.log(e.target)
              this.compressFrondImage = e.target.result
              this.compressImages(this.compressFrondImage)
           }
        },
        /**
         * 压缩图片
         */
        compressImages (res) {
          let defaultImage = {
            width: 210,
            height: 210,
            quality: 0.8, // 压缩图片的质量
            orientation: '' // 获取照片方向角属性,用户旋转控制
          }
          var img = new Image()
          img.src = res
          let initSize = img.src.length
          img.onload = () => {
            console.log('压缩之前宽度: ' + img.width)
            console.log('压缩之前高度: ' + img.height)
            var canvas = document.createElement('canvas')
            var ctx = canvas.getContext('2d')
            if (img.width > defaultImage.width) {
              img.height = img.height * (defaultImage.width / img.width)
              img.width = defaultImage.width
            }
            if (img.height > defaultImage.height) {
              img.width *= defaultImage.height / img.height
              img.height = defaultImage.height
            }
            canvas.width = img.width
            canvas.height = img.height
            ctx.clearRect(0, 0, canvas.width, canvas.height)
            EXIF.getData(this.file, () => { // IMG_FILE为图像数据
              // 是否是iPhone手机,iPhone 拍照之后的压缩是逆时针旋转90,针对iphone做一下处理
              if (navigator.userAgent.match(/iphone/i)) {
                defaultImage.orientation = EXIF.getTag(this.file, 'Orientation')
                // translate是平移变换,scale(-1,1)是向左翻转,rotate是顺时针旋转。
                // defaultImage.orientation = 6   // 测试iPhone手机
                // alert('Orientation:' + defaultImage.orientation) // 拍照方向
                switch (Number(defaultImage.orientation)) {
                  case 2:
                    ctx.translate(img.width, 0)
                    ctx.scale(-1, 1)
                    ctx.drawImage(img, 0, 0, img.width, img.height)
                    break
                  case 3:
                    ctx.rotate(180 * Math.PI / 180)
                    ctx.drawImage(img, -img.width, -img.height, img.width, img.height)
                    break
                  case 4:
                    ctx.translate(img.width, 0)
                    ctx.scale(-1, 1)
                    ctx.rotate(180 * Math.PI / 180)
                    ctx.drawImage(img, -img.width, -img.height, img.width, img.height)
                    break
                  case 5:
                    ctx.translate(img.width, 0)
                    ctx.scale(-1, 1)
                    ctx.rotate(90 * Math.PI / 180)
                    ctx.drawImage(img, 0, -img.width, img.height, img.width)
                    break
                  case 6:
                    canvas.width = img.height
                    canvas.height = img.width
                    ctx.rotate(90 * Math.PI / 180)
                    ctx.drawImage(img, 0, 0, img.width, -img.height)
                    break
                  case 7:
                    ctx.translate(img.width, 0)
                    ctx.scale(-1, 1)
                    ctx.rotate(270 * Math.PI / 180)
                    ctx.drawImage(img, -img.height, 0, img.height, img.width)
                    break
                  case 8:
                    ctx.rotate(270 * Math.PI / 180)
                    ctx.drawImage(img, -img.height, 0, img.height, img.width)
                    break
                  default:
                    ctx.drawImage(img, 0, 0, img.width, img.height)
                }
              } else {
                ctx.drawImage(img, 0, 0, img.width, img.height)
              }
              var imgUrl = canvas.toDataURL('image/jpeg', defaultImage.quality)
              // 压缩之后的base64 图片地址
              this.compressEndImage = imgUrl
              // TODO 上传图片文件
              this.uploadImage()
            })
          }
        },
        /**
         * 上传图片
         */
        uploadImage: function () {
            //创建FormData对象
            let data = new FormData();
            let newFile = this.base64ToFileObject(this.compressEndImage);
            console.log('newSize: '+(newFile.size/1024/1024).toFixed(4)+' M');
            //为FormData对象添加数据
            data.append('head', newFile);
            // this.fileData = data;
            this.submit(data);
        },
        async submit(fileData) {
          let _self = this;
          const res = await _updateAvatar(fileData,{user:'loading'});
          if (res.status === 200) {
            // console.log(res);
            if (res.data.code === 1) {
              _self.getUserInfo();
              Mint.Toast({
                message: '修改成功',
                position: 'center',
                duration: 1200
              });
            }
          }
        },
        base64ToFileObject(base64) {
            base64=base64.split(',')[1];
            base64=window.atob(base64);
            var ia = new Uint8Array(base64.length);
            for (var i = 0; i < base64.length; i++) {
              ia[i] = base64.charCodeAt(i);
            };
            var blob=new Blob([ia], {type:"image/jpeg"});
            var newFile = new File([blob],"abc.jpeg");
            return newFile;
        },
      },
    }
}
</script>

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值