国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

vue實現壓縮圖片預覽并上傳功能(promise封裝)

2019-11-19 12:18:02
字體:
來源:轉載
供稿:網友

本文實例為大家分享了vue實現壓縮圖片預覽并上傳的具體代碼,供大家參考,具體內容如下

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

過程大致分為三步:

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

模板:

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

獲取圖片數據

methods: {   //監聽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   //創建filereader對象   let reader = new FileReader();   reader.readAsDataURL(files[0]); //將圖片轉成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; //預覽圖片     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);      //圖片預覽      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上的,調用drawImage的時候不會報錯,但是你用toDataURL獲取圖片數據的時候獲取到的是空的圖片數據。

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

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

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

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

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

另一個就是如果是png轉jpg,繪制到canvas上的時候,canvas存在透明區域的話,當轉成jpg的時候透明區域會變成黑色,因為canvas的透明像素默認為rgba(0,0,0,0),所以轉成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數據轉成字符串,再實例化一個ArrayBuffer,然后將字符串以8位整型的格式傳入ArrayBuffer,再通過BlobBuilder或者Blob對象,將8位整型的ArrayBuffer轉成二進制對象blob,再將blob轉為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 轉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]); //將圖片轉成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 轉file    var fileOfBlob = new File([blob], name, { type: type });    return fileOfBlob;  }}export default UploadImg

調用代碼

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("請填寫完整信息", "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實現壓縮圖片上傳功能

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 龙里县| 宁阳县| 康平县| 嘉兴市| 长沙市| 太保市| 瓦房店市| 敦煌市| 牙克石市| 全椒县| 禄丰县| 嘉鱼县| 祁门县| 凌云县| 涿州市| 新昌县| 澄迈县| 九寨沟县| 简阳市| 资源县| 九寨沟县| 嘉鱼县| 阿拉善左旗| 三台县| 诏安县| 抚松县| 仁化县| 游戏| 潢川县| 寿阳县| 罗田县| 德江县| 东乡| 徐水县| 津南区| 中超| 呼玛县| 庆城县| 乌拉特后旗| 桂阳县| 沙田区|