HTML5實現input:file上傳壓縮,等比壓縮圖片、base64和檔案互相轉換
阿新 • • 發佈:2019-01-01
本文例項為大家分享了Vue2.0實現呼叫攝像頭進行拍照功能的具體程式碼,以及圖片上傳功能引用exif.js,供大家參考,具體內容如下
外掛:
1.jquery.min.js
2.exif.js
效果目標:實現等比例壓縮上傳
上程式碼
HTML
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <title></title> <!--引入vue--> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17-beta.0/vue.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/1.5.1/vue-resource.js"></script> <style type="text/css"> .bgred{ background-color: red; color: #fff !important; } .nav-title p:nth-child(2) a { display: block; width: 100%; height: 100%; } .container { margin-top: 28px; } .uploading{ width: 100%; height: 250px; } </style> </head> <body> <!--mvvm--> <div id="app" v-cloak> <input @change="fileChange($event)" type="file" name="" id="" /> <p class="uploading" v-bind:style="{backgroundImage:'url(' + (keyurl==0?'https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1539833335&di=dc200e9e69f45b981705cee79d86cf69&src=http://s16.sinaimg.cn/mw690/003gRgrCzy73OGZAV434f&690':keyurl) + ')'}" v-bind:class="{active:keyurl!=0}"> 點選上傳封面 </p> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.3.0/exif.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/layer/2.3/layer.js"></script> <script src="index.js" type="text/javascript" charset="utf-8"></script> </body> </html>
JS
//model var data = { keyurl:'', key:'', qiniutoken:'', //修改詳情 accept: ['image/gif', 'image/jpeg', 'image/png', 'image/bmp'], width:'', height:'' } //ViewModel var app = new Vue({ el: "#app", data: data, created: function() { //獲取資料 //獲取七牛token this.qiniutk(); }, methods: { //獲取qiniu qiniutk:function(){ this.$http.get('qiniutokenUrl').then(function(r){ var token = r.data.data; this.qiniutoken = token; }); }, //使用者上傳 fileChange:function(el){ let file = el.target.files[0]; let type = file.type;//檔案型別 let size = file.size;//檔案大小 if (this.accept.indexOf(type)==-1) { layer.msg("請選擇我的支援的圖片格式"); return false; }; if (size>3145728){ layer.msg("請選擇3M以內的圖片"); return false; }; if (!file.size) return;//判斷是否有檔案數量 if (!file) return; // 未上傳 var orientation; // 圖片上傳的角度,解決 /** * 利用exif.js解決ios手機上傳豎拍照片旋轉90度問題 * 詳見 http://code.ciaoca.com/javascript/exif-js/ */ EXIF.getData(file, function () { // 獲取照片方向角屬性,使用者旋轉控制 orientation = EXIF.getTag(this, 'Orientation'); }); var reader = new FileReader(); // 讀取檔案 var self = this; reader.onload = function () { self.getImgData(this.result, orientation, function (result) { var img = new Image(); img.src = result; // 如果圖片大小小於200kb,則直接上傳 if (result.length <= 200) { self.fileList(file); //呼叫上傳介面函式:無需壓縮 img = null; return; }; // 圖片載入完畢之後進行壓縮,然後上傳 if (img.complete) { callback(); } else { img.onload = callback; }; function callback () { var data = self.compress(img);//這個就是base64的資料了 //self.keyurl = data;//渲染原始影象 //console.log(img.width +'----'+img.height);//這裡就是上傳圖片的寬和高了 var file = self.dataURLtoFile(data,'1.png');//將base64轉換為檔案 self.fileList(file);//呼叫上傳介面函式:壓縮版本 img = null; } }); }; reader.readAsDataURL(file); //this.fileList(file);//獲取files檔案組傳入處理:未壓縮版本 }, dataURLtoFile:function(dataurl, filename){//將base64轉換為檔案 var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/), bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], filename, {type:mime}); }, compress:function(img) { // 用於壓縮圖片的canvas var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); // 瓦片canvas var tCanvas = document.createElement('canvas'); var tctx = tCanvas.getContext('2d'); let initSize = img.src.length // 獲取父元素寬高 let parentWh = $('.creater_class .files'); let wid = parentWh.width(); let hei = parentWh.height(); //console.log("父親:"+wid+'...'+hei) //console.log("原始圖片:"+img.width+'...'+img.height) // 等比壓縮圖片 this.AutoSize(img, wid, hei); var width = this.width; var height = this.height; //console.log("變小圖片:"+width+'...'+height) // 如果圖片大於四百萬畫素,計算壓縮比並將大小壓至400萬以下 var 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 = '#000'; ctx.fillRect(0, 0, canvas.width, canvas.height); // 如果圖片畫素大於100萬則使用瓦片繪製 var count; if ((count = width * height / 1000000) > 1) { count = ~~(Math.sqrt(count) + 1); // 計算要分成多少塊瓦片 // 計算每塊瓦片的寬和高 var nw = ~~(width / count); var 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); } // 進行最小壓縮0.1 var ndata = canvas.toDataURL('image/jpeg', 0.5); // console.log('壓縮前:' + initSize) // console.log('壓縮後:' + ndata.length) // console.log('壓縮率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%") tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0; return ndata; }, AutoSize:function(image, maxWidth, maxHeight) {// 等比壓縮圖片 // 當圖片比圖片框小時不做任何改變 if (image.width < maxWidth && image.height < maxHeight) { //原圖片寬高比例 大於 圖片框寬高比例 this.width = image.width; this.height = image.height; } else { //原圖片寬高比例 大於 圖片框寬高比例,則以框的寬為標準縮放,反之以框的高為標準縮放 if (maxWidth / maxHeight <= image.width / image.height) { this.width = maxWidth; //以框的寬度為標準 this.height = maxWidth * (image.height / image.width); } else { this.width = maxHeight * (image.width / image.height); this.height = maxHeight; //以框的高度為標準 } } }, getImgData:function(img, dir, next) { var image = new Image(); image.onload = function () { var degree = 0; var drawWidth; var drawHeight; var width; var height; drawWidth = this.naturalWidth; drawHeight = this.naturalHeight; // 以下改變一下圖片大小 var maxSide = Math.max(drawWidth, drawHeight); if (maxSide > 1024) { var minSide = Math.min(drawWidth, drawHeight); minSide = minSide / maxSide * 1024; maxSide = 1024; if (drawWidth > drawHeight) { drawWidth = maxSide; drawHeight = minSide; } else { drawWidth = minSide; drawHeight = maxSide; } } var canvas = document.createElement('canvas'); canvas.width = width = drawWidth; canvas.height = height = drawHeight; var context = canvas.getContext('2d'); // 判斷圖片方向,重置canvas大小,確定旋轉角度,iphone預設的是home鍵在右方的橫屏拍攝方式 switch (dir) { // iphone橫屏拍攝,此時home鍵在左側 case 3: degree = 180 drawWidth = -width drawHeight = -height break // iphone豎屏拍攝,此時home鍵在下方(正常拿手機的方向) case 6: canvas.width = height canvas.height = width degree = 90 drawWidth = width drawHeight = -height break // iphone豎屏拍攝,此時home鍵在上方 case 8: canvas.width = height canvas.height = width degree = 270 drawWidth = -width drawHeight = height break } // 使用canvas旋轉校正 context.rotate(degree * Math.PI / 180) context.drawImage(this, 0, 0, drawWidth, drawHeight) // 返回校正圖片 next(canvas.toDataURL('image/jpeg', 0.8)) } image.src = img }, fileList:function(files){ // 呼叫七牛的單圖片上傳介面,獲取返回的key this.imageUpload(files); }, imageUpload:function(fileDom){ var imageData = new FormData(); imageData.append('file',fileDom); imageData.append('token',this.qiniutoken); this.$http.post('qiniuUrl',imageData).then((result)=>{ //this.keyurl = 'http://paz4semup.bkt.clouddn.com/' + result.data.key;//渲染上傳的影象 this.key = result.data.key; }); } } });