美文网首页
vue 移动端上传图片

vue 移动端上传图片

作者: 华华00526 | 来源:发表于2019-05-27 18:02 被阅读0次

    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"

    相关文章

      网友评论

          本文标题:vue 移动端上传图片

          本文链接:https://www.haomeiwen.com/subject/rhhktctx.html