H5+vue上传图片,也能单独使用

html

 <input
            type="file"

            class="file-inp"

            accept="image/*"

            @change="changeImage($event)"

          />


 <div
      class="img-view-wrapper"
      @touchmove.prevent
      @click="hideImgView"
      v-show="showBigImg"
    >
      <div class="img-view-inner">
        <div class="swiper-container">
          <div class="swiper-wrapper">
            <div class="swiper-slide" v-for="(item, i) in imageUrls" :key="i">
              <img :src="item" alt="" />
            </div>
          </div>
        </div>
      </div>
      <div class="swiper-pagination"></div>
    </div>

js


import Swiper from "swiper/dist/js/swiper.min";
import "@/assets/styles/swiper.css";
import EXIF from "exif-js";
import { compressImg, dataURLtoBlob } from "@/utils/imageManage";

data(){
      imageUrls: [],
      imagePlaceUrl: "",
      imgIsLoading: false,
      showBigImg: false,
      mySwiper: null,
}

  methods: {
     showBigImgClick(i) {
      this.initSwiper(i + 1);
      this.mySwiper.slideTo(i + 1);
      this.showBigImg = true;
    },
    hideImgView() {
      this.showBigImg = false;
    },
     initSwiper(index) {
      this.mySwiper = new Swiper(".swiper-container", {
        observer: true, // 修改swiper自己或子元素时,自动初始化swiper
        observeParents: true, // 修改swiper的父元素时,自动初始化swiper
        loop: true, // 循环模式选项
        width: window.innerWidth,
        initialSlide: index,
        pagination: {
          el: ".swiper-pagination",
          type: "fraction",
        },
      });
    },

    // 下面是H5原生
    //上传开始
    uploadStart() {
      this.imgIsLoading = true;
      this.imageUrls.push(this.imagePlaceUrl);
    },
    //上传图片
    uploadEvid(data) {
      Indicator.show("上传中...");
      let headers = {
        device: "h5",
        sharesource: 3,
        "Content-Type": "application/x-www-form-urlencoded",
      };
      upload.uploadEvid(data, headers)
        .then((res) => {
          console.log(res);
          Indicator.close();
          if (res.code == 1) {
            this.imgIsLoading = false;
            this.imageUrls.pop();
            this.imageUrls.push(res.data);
            // console.log(this.imageUrls);
          } else {
            Toast("凭证上传失败,请稍候重试[" + res.code + "]");
            this.uploadFailed();
          }
        })
        .catch((err) => {
          Indicator.close();
          this.uploadFailed();
        });
    },
    //上传失败
    uploadFailed() {
      this.imgIsLoading = false;
      this.imageUrls.pop();
    },
    changeImage(e) {
      // console.log(e);
      let file = e.target.files[0],
        imageData = new FormData(),
        self = this;
      // console.log(imageData);
      if (!file) {
        return;
      }
      //获取图片的 Orientation
      let orientation = 0;
      EXIF.getData(file, function () {
        EXIF.getAllTags(this);
        orientation = EXIF.getTag(this, "Orientation");
      });

      this.uploadStart();
      let reader = new FileReader();
      let quality = 0.3;
      reader.onload = function (e) {
        let img = new Image();
        let result = e.target.result;
        img.addEventListener("load", callback, false);
        img.src = result;
        function callback(e) {
          let newData = compressImg(img, { orientation, quality }); //压图
          let blob = dataURLtoBlob(newData); //转为Blob对象
          // console.log(file);
          // console.log(newData);
          // console.log(blob);
          // console.log(imageData);
          imageData.append("imagefile", blob, file.name);
          // console.log(imageData);
          img = null;
          self.uploadEvid(imageData);
        }
      };
      reader.readAsDataURL(file);
    },

}

imageManage.js

//修复ios拍照上传后图片旋转
//code from https://github.com/stomita/ios-imagefile-megapixel/blob/master/src/megapix-image.js line 115
//Orientation value is from EXIF tag
//Orientation 值需要借用 exif-js https://github.com/exif-js/exif-js/
//thank author
function transformCoordinate(canvas, ctx, width, height, orientation) {
    switch (orientation) {
        case 5:
        case 6:
        case 7:
        case 8:
            canvas.width = height;
            canvas.height = width;
            break;
        default:
            canvas.width = width;
            canvas.height = height;
    }

    switch (orientation) {
        case 2:
            // horizontal flip
            ctx.translate(width, 0);
            ctx.scale(-1, 1);
            break;
        case 3:
            // 180 rotate left
            ctx.translate(width, height);
            ctx.rotate(Math.PI);
            break;
        case 4:
            // vertical flip
            ctx.translate(0, height);
            ctx.scale(1, -1);
            break;
        case 5:
            // vertical flip + 90 rotate right
            ctx.rotate(0.5 * Math.PI);
            ctx.scale(1, -1);
            break;
        case 6:
            // 90 rotate right
            ctx.rotate(0.5 * Math.PI);
            ctx.translate(0, -height);
            break;
        case 7:
            // horizontal flip + 90 rotate right
            ctx.rotate(0.5 * Math.PI);
            ctx.translate(width, -height);
            ctx.scale(-1, 1);
            break;
        case 8:
            // 90 rotate left
            ctx.rotate(-0.5 * Math.PI);
            ctx.translate(-width, 0);
            break;
        default:
            break;
    }
}

//压缩图片
//code from https://github.com/whxaxes/node-test/blob/master/server/upload/index_2.html line 119
//thank author
export function compressImg(img, options){
    //用于压缩图片的canvas
    let canvas = document.createElement('canvas'),
        ctx = canvas.getContext('2d');

    //用于分片绘制的canvas
    let tempCanvas = document.createElement('canvas'),
        tempCtx = tempCanvas.getContext('2d');

    let format = 'image/jpeg',   //全部转为jpeg
        width = img.width,
        height = img.height,
        imgSize = width * height;

    let orientation = 0,
        quality = 0.3;
    options = options || {};    
    orientation = options.orientation || orientation,
    quality = options.quality || quality;

    //ios 中canvas的大小有限制,如果canvas的大小大于大概五百万像素(即宽高乘积)的时候,不仅图片画不出来,其他什么东西也都是画不出来的      
    //我们这里把最大像素值设置为400万                 
    const CANVAS_MAX_SIZE = 2000 * 2000;
    let ratio = imgSize / CANVAS_MAX_SIZE; 
    if( ratio > 1){     //如果大于400万像素,就等比缩放至400万像素以下
        ratio = Math.sqrt( ratio );
        width /= ratio;
        height /= ratio;
    } else {
        ratio = 1;
    }
    
    width = Math.floor(width);
    height = Math.floor(height);
    //设置canvas的宽高以及是否需要旋转
    transformCoordinate(canvas, ctx, width, height, orientation);

    //铺一层白色底色
    //因为canvas的toDataURL只能压缩jpg
    //如果是png转jpg,绘制到canvas上的时候,canvas存在透明区域的话,当转成jpg的时候透明区域会变成黑色
    //canvas的透明像素默认为rgba(0,0,0,0),所以转成jpg就变成rgba(0,0,0,1)了,也就是透明背景会变成了黑色
    ctx.fillStyle = '#fff';
    ctx.fillRect(0, 0, width, height);

    //判断是否需要分片绘制
    //ios 中 如果图片的大小超过两百万像素,图片无法绘制到canvas上, 我们这里把最大像素值设置为100万           
    const IMG_MAX_SIZE = 1000 * 1000;
    let count = imgSize / IMG_MAX_SIZE;
    if(count > 1){
        count = Math.ceil(Math.sqrt(count));
        //console.log(width)
        //分片,用canvas的宽高除以 count, 向下取整,可能会少几像素
        let newW = Math.floor(width / count);
        let newH = Math.floor(height / count);

        tempCanvas.width = newW;
        tempCanvas.height = newH;

        //防止部分手机,绘制图像时因为小数的原因出现缝隙。
        let actualW = Math.floor(newW * ratio);
        let actualH = Math.floor(newH * ratio);
        //计算因为向下取整而遗漏的像素       
        let canvasDiffW = width - newW * count;
        let canvasDiffH = height - newH * count;

        for(let i = 0; i < count; i++){
            for( let j = 0; j < count; j++){
                tempCtx.drawImage(img, i * actualW, j * actualH, actualW, actualH, 0, 0, newW, newH);

                ctx.drawImage(tempCanvas, i * newW, j * newH, 
                    newW + (i === count - 1 ? canvasDiffW : 0), 
                    newH + (j === count - 1 ? canvasDiffH : 0));
            }
        }                
    } else {
        ctx.drawImage(img, 0, 0, width, height);
    }

    //将canvas内容转为base64,并压缩
    let newData = canvas.toDataURL(format, quality);                
    canvas = ctx = tempCanvas = tempCtx = null;

    return newData;
}

//base64转为blob
export function dataURLtoBlob(dataURI){
    let format = 'image/jpeg',
        code = window.atob(dataURI.split(',')[1]),                                               
        codeLen = code.length,
        arrayBuffer = new ArrayBuffer(codeLen),
        intArray = new Uint8Array(arrayBuffer);
    for(let i = 0; i < codeLen; i++){
        intArray[i] = code.charCodeAt(i);
    }
    try{
        return new Blob([intArray], {type: format});
    } catch(e) {
        let BlobBuilder = window.BlobBuilder || window.WebkitBlobBuilder;                            
        let bb = new BlobBuilder();
        bb.append(arrayBuffer);
        return bb.getBlob(format);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值