最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue實現(xiàn)壓縮圖片預(yù)覽并上傳功能(promise封裝)

 更新時間:2019年01月10日 14:26:47   作者:zhaohanqq  
這篇文章主要為大家詳細介紹了vue實現(xiàn)壓縮圖片預(yù)覽并上傳功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了vue實現(xiàn)壓縮圖片預(yù)覽并上傳的具體代碼,供大家參考,具體內(nèi)容如下

主要用到filereader、canvas 以及 formdata 這三個h5的api

過程大致分為三步:

用戶使用input file上傳圖片的時候,用filereader讀取用戶上傳的圖片數(shù)據(jù)(base64格式)
把圖片數(shù)據(jù)傳入img對象,然后將img繪制到canvas上,再調(diào)用canvas.toDataURL對圖片進行壓縮
獲取到壓縮后的base64格式圖片數(shù)據(jù),轉(zhuǎn)成二進制塞入formdata,再通過XmlHttpRequest提交formdata。

模板:

<template>
 <div class="image-box">
 <input type="file" accept="image/*" @change="imageHandle">
 <img ref="upImg"/>
 </div>
</template>

獲取圖片數(shù)據(jù)

methods: {
  //監(jiān)聽input file的change事件
 imageHandle(e) {
  //**這個是必不可少的,在下面的reader.onload中this就不再指vm了**
  let that = this;
  let maxSize = 100 * 1024;
  let files = e.srcElement.files;
  if (!files.length) return; //文件長度大于0
  if (!/^image\//.test(files[0].type)) return; //必須是圖片才處理
  if (!window.FileReader) return; //支持FileReader
  //創(chuàng)建filereader對象
  let reader = new FileReader();
  reader.readAsDataURL(files[0]); //將圖片轉(zhuǎn)成base64格式
  reader.onload = function() {
  let result = this.result;
  let img = new Image();
  img.src = result;
  let formdata = new FormData();
  if (this.result.length <= maxSize) {
   that.$refs.upImg.src = result; //預(yù)覽圖片
   img = null;
   //上傳圖片
   formdata.append("image", that._upload(result, files[0].name, files[0].type));
   that.$store.dispatch("uploadImage", formdata)
    .then(data => {
     if (data === 1) {
     that.$toast("上傳成功", "success");
     } else if (data === -1) {
     that.$toast("圖片為空", "error");
     } else {
     that.$toast("上傳失敗", "error");
     }
    })
    .catch(error => that.$toast("上傳失敗", "error"));
  } else {
   img.onload = function() {
   //壓縮圖片
   let data = that._compress(img);
   //圖片預(yù)覽
   that.$refs.upImg.src = data;
   //上傳圖片
   formdata.append("image", that._upload(data, files[0].name, files[0].type));
   that.$store.dispatch("uploadImage", formdata)
     .then(data => {
      if (data === 1) {
      that.$toast("上傳成功", "success");
      } else if (data === -1) {
      that.$toast("圖片為空", "error");
      } else {
      that.$toast("上傳失敗", "error");
      }
     })
     .catch(error => that.$toast("上傳失敗", "error"));
   };
  }
  };
 },

壓縮圖片

在IOS中,canvas繪制圖片是有兩個限制的:

首先是圖片的大小,如果圖片的大小超過兩百萬像素,圖片也是無法繪制到canvas上的,調(diào)用drawImage的時候不會報錯,但是你用toDataURL獲取圖片數(shù)據(jù)的時候獲取到的是空的圖片數(shù)據(jù)。

再者就是canvas的大小有限制,如果canvas的大小大于大概五百萬像素(即寬高乘積)的時候,不僅圖片畫不出來,其他什么東西也都是畫不出來的。

應(yīng)對第一種限制,處理辦法就是瓦片繪制了。瓦片繪制,也就是將圖片分割成多塊繪制到canvas上,我代碼里的做法是把圖片分割成100萬像素一塊的大小,再繪制到canvas上。

而應(yīng)對第二種限制,我的處理辦法是對圖片的寬高進行適當壓縮,我代碼里為了保險起見,設(shè)的上限是四百萬像素,如果圖片大于四百萬像素就壓縮到小于四百萬像素。四百萬像素的圖片應(yīng)該夠了,算起來寬高都有2000X2000了。

如此一來就解決了IOS上的兩種限制了。

除了上面所述的限制,還有兩個坑,一個就是canvas的toDataURL是只能壓縮jpg的,當用戶上傳的圖片是png的話,就需要轉(zhuǎn)成jpg,也就是統(tǒng)一用canvas.toDataURL(‘image/jpeg', 0.1) , 類型統(tǒng)一設(shè)成jpeg,而壓縮比就自己控制了。

另一個就是如果是png轉(zhuǎn)jpg,繪制到canvas上的時候,canvas存在透明區(qū)域的話,當轉(zhuǎn)成jpg的時候透明區(qū)域會變成黑色,因為canvas的透明像素默認為rgba(0,0,0,0),所以轉(zhuǎn)成jpg就變成rgba(0,0,0,1)了,也就是透明背景會變成了黑色。解決辦法就是繪制之前在canvas上鋪一層白色的底色。

_compress(img) {
  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");
  //瓦片
  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);
  widht /= 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, canvas.width, canvas.height);
  }
  //進行壓縮
  let ndata = canvas.toDataURL("image/jpeg", 0.3);
  tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
  return ndata;
 },

上傳

完成圖片壓縮后,就可以塞進formdata里進行上傳了,先將base64數(shù)據(jù)轉(zhuǎn)成字符串,再實例化一個ArrayBuffer,然后將字符串以8位整型的格式傳入ArrayBuffer,再通過BlobBuilder或者Blob對象,將8位整型的ArrayBuffer轉(zhuǎn)成二進制對象blob,再將blob轉(zhuǎn)為File對象

_upload(data, name, type) {
  let text = window.atob(data.split(",")[1]);
  let buffer = new ArrayBuffer(text.length);
  let ubuffer = new Uint8Array(buffer);
  let pecent = 0,
  loop = null;

  for (var i = 0; i < text.length; i++) {
  ubuffer[i] = text.charCodeAt(i);
  }

  let Builder =
  window.BlobBuilder ||
  window.WebKitBlobBuilder ||
  window.MozBlobBuilder ||
  window.MSBlobBuilder;
  let blob;
  if (Builder) {
  var builder = new Builder();
  builder.append(buffer);
  blob = builder.getBlob(type);
  } else {
  blob = new window.Blob([ubuffer], { type: type });
  }
  // blob 轉(zhuǎn)file
  var fileOfBlob = new File([blob], name, { type: type });
  return fileOfBlob;
 }
 }

將圖片壓縮上傳封裝到一個js文件里

const UploadImg = {
 imageHandle(files, maxSize, imgDom) {
  let that = this;
  let formdata = new FormData();
  let reader = new FileReader();
  reader.readAsDataURL(files[0]); //將圖片轉(zhuǎn)成base64格式
  //reader.onload是異步,要用到Promise對象將值返回出去
  return new Promise((resolved, rejected) => {
   reader.onload = function () {
    let result = this.result;
    let img = new Image();
    img.src = result;
    if (this.result.length <= maxSize) {
     imgDom.src = result;
     img = null;
     formdata.append("image", that._upload(result, files[0].name, files[0].type));
     resolved(formdata);
    } else {
     img.onload = function () {
      let data = that._compress(img);
      imgDom.src = data;
      formdata.append("image", that._upload(data, files[0].name, files[0].type));
      resolved(formdata);
     };
    }
   };
  })

 },
 _compress(img) {
  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");
  //瓦片
  let tCanvas = document.createElement("canvas");
  let tctx = tCanvas.getContext("2d");
  let width = img.width;
  let height = img.height;
  //如果圖片大于四百萬像素,計算壓縮比并將大小壓至400萬以下
  let ratio;
  if ((ratio = (width * height) / 4000000) > 1) {
   ratio = Math.sqrt(ratio);
   widht /= 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, canvas.width, canvas.height);
  }
  //進行最小壓縮
  let ndata = canvas.toDataURL("image/jpeg", 0.3);
  tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
  return ndata;
 },
 _upload(data, name, type) {
  let text = window.atob(data.split(",")[1]);
  let buffer = new ArrayBuffer(text.length);
  let ubuffer = new Uint8Array(buffer);

  for (var i = 0; i < text.length; i++) {
   ubuffer[i] = text.charCodeAt(i);
  }

  let Builder =
   window.BlobBuilder ||
   window.WebKitBlobBuilder ||
   window.MozBlobBuilder ||
   window.MSBlobBuilder;
  let blob;
  if (Builder) {
   var builder = new Builder();
   builder.append(buffer);
   blob = builder.getBlob(type);
  } else {
   blob = new window.Blob([ubuffer], { type: type });
  }
  // blob 轉(zhuǎn)file
  var fileOfBlob = new File([blob], name, { type: type });
  return fileOfBlob;
 }
}

export default UploadImg

調(diào)用代碼

import UploadImg from "../../util/uploadImg";

methods: {
 imageHandle(e) {
  let maxSize = 100 * 1024;
  let imgDom = this.$refs.upImg;
  let files = e.srcElement.files;
  if (!files.length) return; //文件長度大于0
  if (!/^image\//.test(files[0].type)) return; //必須是圖片才處理
  if (!window.FileReader) return; //支持FileReader

  if (this.docEntry === "" || this.lineId === "") {
  this.$toast("請?zhí)顚懲暾畔?, "error");
  return;
  }
  // let formdata = new FormData();
  UploadImg.imageHandle(files, maxSize, imgDom).then(formdata => {
  formdata.append("docEntry", this.docEntry);
  formdata.append("lineId", this.lineId);
  formdata.append("action", "ProductionListImage");
  this.$store
   .dispatch("uploadImage", formdata)
   .then(data => {
   if (data === 1) {
    this.$toast("上傳成功", "success");
   } else if (data === -1) {
    this.$toast("圖片為空", "error");
   } else {
    this.$toast("上傳失敗", "error");
   }
   })
   .catch(error => this.$toast("上傳失敗", "error"));
  });
 }
 }

參考鏈接:移動端利用H5實現(xiàn)壓縮圖片上傳功能

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue3.0+echarts實現(xiàn)立體柱圖

    vue3.0+echarts實現(xiàn)立體柱圖

    這篇文章主要為大家詳細介紹了vue3.0+echarts實現(xiàn)立體柱圖,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 詳解Vue中添加過渡效果

    詳解Vue中添加過渡效果

    本篇文章主要介紹了詳解Vue中添加過渡效果 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • Vue中獲取this.$refs為undefined的問題

    Vue中獲取this.$refs為undefined的問題

    這篇文章主要介紹了Vue中獲取this.$refs為undefined的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • vue請求函數(shù)和路由的安裝使用過程

    vue請求函數(shù)和路由的安裝使用過程

    這篇文章主要介紹了vue請求函數(shù)和路由的安裝使用過程,本文給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2024-08-08
  • Vue項目中大文件切片上傳實現(xiàn)秒傳與斷點續(xù)傳的詳細實現(xiàn)過程

    Vue項目中大文件切片上傳實現(xiàn)秒傳與斷點續(xù)傳的詳細實現(xiàn)過程

    這篇文章主要給大家介紹了關(guān)于Vue項目中大文件切片上傳實現(xiàn)秒傳與斷點續(xù)傳的詳細實現(xiàn)過程, 在開發(fā)中,如果上傳的文件過大,可以考慮分片上傳,分片就是說將文件拆分來進行上傳,將各個文件的切片傳遞給后臺,然后后臺再進行合并,需要的朋友可以參考下
    2023-08-08
  • element?el-select下拉框選擇失效解決辦法

    element?el-select下拉框選擇失效解決辦法

    el-select即選擇器用于從若干個候選項中選擇其中一個(或者多個),在傳統(tǒng)網(wǎng)頁開發(fā)中選擇器經(jīng)常被稱作下拉框、下拉列表是最常用的表單元素之一,這篇文章主要給大家介紹了關(guān)于element?el-select下拉框選擇失效解決辦法,需要的朋友可以參考下
    2023-08-08
  • vue-form表單驗證是否為空值的實例詳解

    vue-form表單驗證是否為空值的實例詳解

    今天小編就為大家分享一篇vue-form表單驗證是否為空值的實例詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • vite/Vuecli配置proxy代理解決跨域問題

    vite/Vuecli配置proxy代理解決跨域問題

    這篇文章主要介紹了vite/Vuecli配置proxy代理解決跨域問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 前端H5微信支付寶支付實現(xiàn)方法(uniapp為例)

    前端H5微信支付寶支付實現(xiàn)方法(uniapp為例)

    最近上線一個項目,手機網(wǎng)站進行調(diào)起支付寶App支付,做起來還是滿順手的,在此做個記錄,這篇文章主要給大家介紹了關(guān)于前端H5微信支付寶支付實現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下
    2024-04-04
  • Vue高效更新UI的方法詳解

    Vue高效更新UI的方法詳解

    在現(xiàn)代前端開發(fā)中,Vue.js以其高效的響應(yīng)式數(shù)據(jù)綁定和視圖更新機制著稱,而這一切的核心技術(shù)之一就是虛擬DOM和Diff算法,本文將詳細介紹虛擬DOM的概念、Diff算法的工作原理,以及Vue如何利用這些技術(shù)高效地更新UI,需要的朋友可以參考下
    2025-02-02

最新評論

乐山市| 梨树县| 阳朔县| 伊吾县| 务川| 周至县| 甘孜县| 新巴尔虎左旗| 双城市| 菏泽市| 绥阳县| 郑州市| 莱西市| 来凤县| 沽源县| 永泰县| 永新县| 永德县| 孝昌县| 新兴县| 新建县| 土默特右旗| 错那县| 马公市| 涟源市| 昭苏县| 礼泉县| 诸城市| 尼勒克县| 彰化县| 元谋县| 新巴尔虎右旗| 东宁县| 万源市| 普兰店市| 安国市| 天柱县| 邳州市| 富民县| 余姚市| 睢宁县|