vue 移动端上传图片

1,图片组件

<template>

  <div class="imgWrap">

    <p class="titleImgWrap">{{Imgtitle}}</p>

    <div class="imgBtn">

      <span>+</span>

      <input style ref="file" type="file" id="upload" accept="image/*" @change="upload">

    </div>

  </div>

</template>

<script>

import EXIF from "@/utils/small-exif"

export default {

  props: {

    photoEventNumber: Number,

    Imgtitle:String

  },

  data() {

    return {

      headerImage: "",

      picValue: ""

    };

  },

  mounted() {},

  watch: {

    photoEventNumber: {

      handler() {

        var userAgent = navigator.userAgent;

        var el = this.$refs.file;

      }

    }

  },

  methods: {

    upload(e) {

      let files = e.target.files || e.dataTransfer.files;

      if (!files.length) return;

      this.picValue = files[0];

      this.imgPreview(this.picValue);

    },

    imgPreview(file) {

      let self = this;

      let Orientation;

      //去获取拍照时的信息,解决拍出来的照片旋转问题

      EXIF.getData(file, function () {

        Orientation = EXIF.getTag(this, 'Orientation');

      });

      // 看支持不支持FileReader

      if (!file || !window.FileReader) return;

      if (/^image/.test(file.type)) {

        // 创建一个reader

        let reader = new FileReader();

        // 将图片2将转成 base64 格式

        reader.readAsDataURL(file);

        // 读取成功后的回调

        reader.onloadend = function() {

          let result = this.result;

          let img = new Image();

          img.src = result;

          //判断图片是否大于100K,是就直接上传,反之压缩图片

          if (this.result.length <= 100 * 1024) {

            self.headerImage = this.result;

            self.postImg();

          } else {

            img.onload = function() {

              let data = self.compress(img, Orientation);

              self.headerImage = data;

              self.postImg();

            };

          }

        };

      }

    },

    postImg() {

      //这里写接口

      var photoFile = this.convertBase64UrlToBlob(this.headerImage);

      var photo = {};

      photo.base64 = this.headerImage;

      photo.file = photoFile;

      this.$emit("photoData", photo);

    },

    /* 将以base64的图片url数据转换为Blob

    * @param urlData

    *            用url方式表示的base64图片数据

    */

    convertBase64UrlToBlob(urlData) {

      var bytes = window.atob(urlData.split(",")[1]); //去掉url的头,并转换为byte

      //处理异常,将ascii码小于0的转换为大于0

      var ab = new ArrayBuffer(bytes.length);

      var ia = new Uint8Array(ab);

      for (var i = 0; i < bytes.length; i++) {

        ia[i] = bytes.charCodeAt(i);

      }

      return new Blob([ab], {

        type: "image/png"

      });

    },

    rotateImg(img, direction, canvas) {

      //最小与最大旋转方向,图片旋转4次后回到原方向

      const min_step = 0;

      const max_step = 3;

      if (img == null) return;

      //img的高度和宽度不能在img元素隐藏后获取,否则会出错

      let height = img.height;

      let width = img.width;

      let step = 2;

      if (step == null) {

        step = min_step;

      }

      if (direction == "right") {

        step++;

        //旋转到原位置,即超过最大值

        step > max_step && (step = min_step);

      } else {

        step--;

        step < min_step && (step = max_step);

      }

      //旋转角度以弧度值为参数

      let degree = (step * 90 * Math.PI) / 180;

      let ctx = canvas.getContext("2d");

      switch (step) {

        case 0:

          canvas.width = width;

          canvas.height = height;

          ctx.drawImage(img, 0, 0);

          break;

        case 1:

          canvas.width = height;

          canvas.height = width;

          ctx.rotate(degree);

          ctx.drawImage(img, 0, -height);

          break;

        case 2:

          canvas.width = width;

          canvas.height = height;

          ctx.rotate(degree);

          ctx.drawImage(img, -width, -height);

          break;

        case 3:

          canvas.width = height;

          canvas.height = width;

          ctx.rotate(degree);

          ctx.drawImage(img, -width, 0);

          break;

      }

    },

    compress(img, Orientation) {

      let canvas = document.createElement("canvas");

      let ctx = canvas.getContext("2d");

      //瓦片canvas

      let tCanvas = document.createElement("canvas");

      let tctx = tCanvas.getContext("2d");

      let initSize = img.src.length;

      let width = img.width;

      let height = img.height;

      //如果图片大于四百万像素,计算压缩比并将大小压至400万以下

      let ratio;

      if ((ratio = (width * height) / 4000000) > 1) {

        ratio = Math.sqrt(ratio);

        width /= ratio;

        height /= ratio;

      } else {

        ratio = 1;

      }

      canvas.width = width;

      canvas.height = height;

      //        铺底色

      ctx.fillStyle = "#fff";

      ctx.fillRect(0, 0, canvas.width, canvas.height);

      //如果图片像素大于100万则使用瓦片绘制

      let count;

      if ((count = (width * height) / 1000000) > 1) {

        count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片

        //            计算每块瓦片的宽和高

        let nw = ~~(width / count);

        let nh = ~~(height / count);

        tCanvas.width = nw;

        tCanvas.height = nh;

        for (let i = 0; i < count; i++) {

          for (let j = 0; j < count; j++) {

            tctx.drawImage(

              img,

              i * nw * ratio,

              j * nh * ratio,

              nw * ratio,

              nh * ratio,

              0,

              0,

              nw,

              nh

            );

            ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);

          }

        }

      } else {

        ctx.drawImage(img, 0, 0, width, height);

      }

      //修复ios上传图片的时候 被旋转的问题

      if (Orientation != "" && Orientation != 1) {

        switch (Orientation) {

          case 6: //需要顺时针(向左)90度旋转

            this.rotateImg(img, "left", canvas);

            break;

          case 8: //需要逆时针(向右)90度旋转

            this.rotateImg(img, "right", canvas);

            break;

          case 3: //需要180度旋转

            this.rotateImg(img, "right", canvas); //转两次

            this.rotateImg(img, "right", canvas);

            break;

        }

      }

      //进行最小压缩

      let ndata = canvas.toDataURL("image/jpeg", 0.1);

      tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;

      return ndata;

    }

  }

};

</script>

<style scoped>

* {

  margin: 0;

  padding: 0;

}

.imgWrap {

  display: flex;

  align-items: center;

  padding: 20px 0;

}

p.titleImgWrap {

  font-size: 0.37333rem;

  color: #333a44;

  padding: 0.26667rem 0.4rem;

}

.imgBtn {

  position: relative;

  width: 60px;

  height: 60px;

  background: rgba(242, 246, 252, 1);

  text-align: center;

  line-height: 60px;

}

.show {

  width: 200px;

  height: 200px;

  overflow: hidden;

  position: relative;

  border: 1px solid #d5d5d5;

}

.picture {

  width: 100%;

  height: 100%;

  overflow: hidden;

  background-position: center center;

  background-repeat: no-repeat;

  background-size: cover;

}

input {

  position: absolute;

  left: 0;

  top: 0;

  width: 100%;

  height: 100%;

  opacity: 0;

}

</style>



2,使用父组件

html:

<div @click="uploadPhoto">

        <uploaderImg :photoEventNumber="photoEventNumber" @photoData="getData" :Imgtitle="Imgtitle"></uploaderImg>

      </div>

      <div class="showImgs" v-if="imgBase64 && imgBase64.length > 0">

        <p v-for="(item,index) in imgBase64" :key="index">

          <img :src="BASE_IMG_URL+item" @click="preview(index)">

          <span @click="delImg(index)">删除</span>

        </p>

      </div>

      <van-image-preview v-model="show" :images="imgList" showIndex :startPosition="startPosition"></van-image-preview>

    </van-cell-group>

js:

data(){

return{

imgBase64: [],

      Imgtitle: "销售合同",

      imgList: [],

      photo: "",

      BASE_IMG_URL: BASE_URL_IMG,

      startPosition: 0,

      applicationStepsNeedData: {

        type: 3

      },

      applicationId: "",

      photoEventNumber: 1,

}}

methods:{

//上传图片

    uploadPhoto() {

      this.photoEventNumber = ++this.photoEventNumber;

    },

    getData(datas) {

      this.photo = datas.file;

      this.$toast("上传中...");

      uploadImg(this.photo)

        .then(res => {

          if (res.code == 200) {

            this.imgBase64.push(res.msg);

          }

        })

        .catch(err => {

          this.$toast("上传失败,请重试");

          console.log(err);

        });

    },

    //预览图片

    preview(i) {

      this.startPosition = i;

      this.show = true;

      this.imgList = [];

      this.imgBase64.map(item => {

        this.imgList.push(this.BASE_IMG_URL + item);

      });

      // console.log(this.imgList);

    },

    //删除图片

    delImg(index) {

      this.imgBase64.splice(index, 1);

    },

}



exft.js

var EXIF = {};

var TiffTags = EXIF.TiffTags = {

    0x0112: "Orientation"

};

function imageHasData(img) {

    return !!(img.exifdata);

}

function getImageData(img, callback) {

    function handleBinaryFile(binFile) {

        var data = findEXIFinJPEG(binFile);

        img.exifdata = data || {};

        if (callback) {

            callback.call(img);

        }

    }

    if (window.FileReader && (img instanceof window.Blob || img instanceof window.File)) {

        var fileReader = new FileReader();

        fileReader.onload = function (e) {

            handleBinaryFile(e.target.result);

        };

        fileReader.readAsArrayBuffer(img);

    }

}

function findEXIFinJPEG(file) {

    var dataView = new DataView(file);

    if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) {

        return false; // not a valid jpeg

    }

    var offset = 2,

        length = file.byteLength,

        marker;

    while (offset < length) {

        if (dataView.getUint8(offset) != 0xFF) {

            return false; // not a valid marker, something is wrong

        }

        marker = dataView.getUint8(offset + 1);

        if (marker == 225) {

            return readEXIFData(dataView, offset + 4, dataView.getUint16(offset + 2) - 2);

        } else {

            offset += 2 + dataView.getUint16(offset + 2);

        }

    }

}

function readTags(file, tiffStart, dirStart, strings, bigEnd) {

    var entries = file.getUint16(dirStart, !bigEnd),

        tags = {},

        entryOffset, tag,

        i;

    for (i = 0; i < entries; i++) {

        entryOffset = dirStart + i * 12 + 2;

        tag = strings[file.getUint16(entryOffset, !bigEnd)];

        tags[tag] = readTagValue(file, entryOffset, tiffStart, dirStart, bigEnd);

    }

    return tags;

}

function readTagValue(file, entryOffset, tiffStart, dirStart, bigEnd) {

    var type = file.getUint16(entryOffset + 2, !bigEnd),

        numValues = file.getUint32(entryOffset + 4, !bigEnd),

        valueOffset = file.getUint32(entryOffset + 8, !bigEnd) + tiffStart,

        offset,

        vals, val, n,

        numerator, denominator;

    switch (type) {

        case 1: // byte, 8-bit unsigned int

        case 7: // undefined, 8-bit byte, value depending on field

            if (numValues == 1) {

                return file.getUint8(entryOffset + 8, !bigEnd);

            } else {

                offset = numValues > 4 ? valueOffset : (entryOffset + 8);

                vals = [];

                for (n = 0; n < numValues; n++) {

                    vals[n] = file.getUint8(offset + n);

                }

                return vals;

            }

            case 2: // ascii, 8-bit byte

                offset = numValues > 4 ? valueOffset : (entryOffset + 8);

                return getStringFromDB(file, offset, numValues - 1);

            case 3: // short, 16 bit int

                if (numValues == 1) {

                    return file.getUint16(entryOffset + 8, !bigEnd);

                } else {

                    offset = numValues > 2 ? valueOffset : (entryOffset + 8);

                    vals = [];

                    for (n = 0; n < numValues; n++) {

                        vals[n] = file.getUint16(offset + 2 * n, !bigEnd);

                    }

                    return vals;

                }

                case 4: // long, 32 bit int

                    if (numValues == 1) {

                        return file.getUint32(entryOffset + 8, !bigEnd);

                    } else {

                        vals = [];

                        for (n = 0; n < numValues; n++) {

                            vals[n] = file.getUint32(valueOffset + 4 * n, !bigEnd);

                        }

                        return vals;

                    }

                    case 5: // rational = two long values, first is numerator, second is denominator

                        if (numValues == 1) {

                            numerator = file.getUint32(valueOffset, !bigEnd);

                            denominator = file.getUint32(valueOffset + 4, !bigEnd);

                            val = new Number(numerator / denominator);

                            val.numerator = numerator;

                            val.denominator = denominator;

                            return val;

                        } else {

                            vals = [];

                            for (n = 0; n < numValues; n++) {

                                numerator = file.getUint32(valueOffset + 8 * n, !bigEnd);

                                denominator = file.getUint32(valueOffset + 4 + 8 * n, !bigEnd);

                                vals[n] = new Number(numerator / denominator);

                                vals[n].numerator = numerator;

                                vals[n].denominator = denominator;

                            }

                            return vals;

                        }

                        case 9: // slong, 32 bit signed int

                            if (numValues == 1) {

                                return file.getInt32(entryOffset + 8, !bigEnd);

                            } else {

                                vals = [];

                                for (n = 0; n < numValues; n++) {

                                    vals[n] = file.getInt32(valueOffset + 4 * n, !bigEnd);

                                }

                                return vals;

                            }

                            case 10: // signed rational, two slongs, first is numerator, second is denominator

                                if (numValues == 1) {

                                    return file.getInt32(valueOffset, !bigEnd) / file.getInt32(valueOffset + 4, !bigEnd);

                                } else {

                                    vals = [];

                                    for (n = 0; n < numValues; n++) {

                                        vals[n] = file.getInt32(valueOffset + 8 * n, !bigEnd) / file.getInt32(valueOffset + 4 + 8 * n, !bigEnd);

                                    }

                                    return vals;

                                }

    }

}

function getStringFromDB(buffer, start, length) {

    var outstr = "";

    for (var n = start; n < start + length; n++) {

        outstr += String.fromCharCode(buffer.getUint8(n));

    }

    return outstr;

}

function readEXIFData(file, start) {

    if (getStringFromDB(file, start, 4) != "Exif") {

        return false;

    }

    var bigEnd,

        tags, tag,

        exifData, gpsData,

        tiffOffset = start + 6;

    // test for TIFF validity and endianness

    if (file.getUint16(tiffOffset) == 0x4949) {

        bigEnd = false;

    } else if (file.getUint16(tiffOffset) == 0x4D4D) {

        bigEnd = true;

    } else {

        return false;

    }

    if (file.getUint16(tiffOffset + 2, !bigEnd) != 0x002A) {

        return false;

    }

    var firstIFDOffset = file.getUint32(tiffOffset + 4, !bigEnd);

    if (firstIFDOffset < 0x00000008) {

        return false;

    }

    tags = readTags(file, tiffOffset, tiffOffset + firstIFDOffset, TiffTags, bigEnd);

    return tags;

}

EXIF.getData = function (img, callback) {

    if ((img instanceof Image || img instanceof HTMLImageElement) && !img.complete) return false;

    if (!imageHasData(img)) {

        getImageData(img, callback);

    } else {

        if (callback) {

            callback.call(img);

        }

    }

    return true;

}

EXIF.getTag = function (img, tag) {

    if (!imageHasData(img)) return;

    return img.exifdata[tag];

}

export default EXIF

// 页面引入方式    import EXIF from "@/utils/small-exif"

猜你喜欢

转载自blog.csdn.net/weixin_33778544/article/details/90837485