摘要:背景作為一名前端工作人員,相信大家在開發系統的時候,經常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個問題的時候,都會虎軀一震,以為會是一個棘手的問題,當你讀完這篇文章的時候,你會發現都是你瞎操作了,真相就是這么簡單
背景
作為一名前端工作人員,相信大家在開發系統的時候,經常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個問題的時候,都會虎軀一震,以為會是一個棘手的問題,當你讀完這篇文章的時候,你會發現都是你瞎操作了,真相就是這么簡單,下面進入正題:
圖片文件上傳現在很多項目實現在系統內保存圖片,大多數只是在系統數據庫內保存對應圖片的url,而實際的圖片資源會放在阿里等圖片服務器上,當然,也有一些項目會選擇在自己的數據庫中保存圖片base64格式的字符串,下面講一些這兩種方法的具體實現,實現以一個vue實例來說明:
首先,我們先要從用戶那里獲取圖片資源,這個時候,我們需要用到html的標簽,type值為file,指定input標簽為文件類型的表單輸入,并將其 accept屬性設置為"image/*",指定只接受圖片資源的文件;
接下來,我們就要獲取用戶選擇的文件,當用戶選擇完文件的時候,就會觸發input標簽的change事件,我們可以通過監聽該事件,并獲取事件對象event,來獲取圖片文件:
當點擊獲取文件后,我們可以通過$event對象,獲取$event.target.files[0]來獲取圖片資源文件對象,至于為什么要加索引值,是因為文件上傳input表單是支持多文件上傳的,只需要在input標簽上增加multiple屬性;我們可以看看下圖文件對象的一些屬性:
觀察后發現,文件對象中存在一個size屬性,表明圖片的大小,我們可以通過驗證該屬性的值是否為空,來達到檢驗文件是否已經被我們獲取到指定操作;
fileChange(el, index) { if (!el.target.files[0].size) return; }
至此,我們已經獲取到我們想要的文件對象,接下來,我們實現圖片壓縮功能,命名為compress函數:
圖片壓縮首先,我們要對我們的圖片資源進行壓縮,第一步肯定是獲取圖片資源吶,獲取后對其簡單的校驗;
compress(event) { var file = event.target.files; var reader = new FileReader(), imgFile = file[0]; if (imgFile.type.indexOf("image") == 0) { reader.readAsDataURL(imgFile); } else { this.$Message.infor("文件類型僅為圖片") } }
這里可能有些人對FileReader對象不了解,FileReader 對象允許Web應用程序異步讀取存儲在用戶計算機上的文件(或原始數據緩沖區)的內容,使用 File 或 Blob 對象指定要讀取的文件或數據,這里我們主要是用于監聽onload來判斷是否讀取完成,讀取完成時,我們把讀取的結果賦值給我們新創建的Image對象,作為后面壓縮的對象;這是時候,我們會發現,我們讀取后的結果其實是一個base64格式的字符串
(很長..,我就意思意思)
此時,我們會發現,base64的字符串在這里就出現了,它可以作為一個值復制給標簽的src屬性,同樣可以達到渲染圖片的目標,因此也有人選擇保存該格式的圖片;但是著并非主流的方式,同時也會造成我們數據庫過于冗余;
compress(event) { var file = event.target.files; var reader = new FileReader(), imgFile = file[0]; if (imgFile.type.indexOf("image") == 0) { reader.readAsDataURL(imgFile); } else { this.$Message.infor("文件類型僅為圖片") } let img = new Image(); reader.onload = function (e) { img.src = e.target.result; }; }
圖片進行壓縮,我們主要是利用canvas是實現該功能,通過canvas.getContext("2d").drawImage()方法重新繪制圖片,并利用canvas.toDataURL(type, encoderOptions)方法返回一個包含圖片展示的 dataURI,type為圖片格式,encoderOptions為圖片的清晰度,0到1遞增,這個壓縮的過程不難理解,思路就是獲取圖片的高寬,計算其像素大小,并與以一個自己設定的界限值進行比較,來看一下我們大小是否需要壓縮,如例子中的ratio表示圖片寬高的壓縮比例 ,我們是可以實現不改寬高來修改圖片的文件大小,通過drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)重新繪制圖片,他可以傳進九個參數,分別代表著繪制到上下文的元素,源圖像的矩形選擇框的左上角 X 坐標,源圖像的矩形選擇框的左上角 Y 坐標,源圖像的矩形選擇框的寬度,源圖像的矩形選擇框的高度,目標畫布的左上角在目標canvas上 X 軸的位置,目標畫布的左上角在目標canvas上 Y 軸的位置,在目標畫布上繪制圖像的寬度,在目標畫布上繪制圖像的高度;
整個函數實現如下:
compress(event) { var file = event.target.files; var reader = new FileReader(), imgFile = file[0]; if (imgFile.type.indexOf("image") == 0) { reader.readAsDataURL(imgFile); } else { this.$Message.infor("文件類型僅為圖片") } let img = new Image(); reader.onload = function (e) { img.src = e.target.result; }; var imgP = new Promise((resolve, reject) => { img.onload = () => { var canvas = document.createElement("canvas"); var ctx = canvas.getContext("2d"); // 瓦片canvas var tCanvas = document.createElement("canvas"); var tctx = tCanvas.getContext("2d"); var initSize = img.src.length; var width = img.width; var height = img.height; //圖片像素大于400萬像素,計算壓縮到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 = "#fff"; ctx.fillRect(0, 0, canvas.width, canvas.height); //如果圖片太大則使用瓦片繪制 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 (var i = 0; i < count; i++) { for (var 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) } //進行最小壓縮 var ndata = canvas.toDataURL("image/jpeg", 0.3); tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0; resolve(ndata) } }) return Promise.all([imgP]) }圖片拼接
需要注意的一點了,上面壓縮的過程使用了瓦片繪制,可能會導致拼接過程中不緊湊而產生一條間隙,這個只需要調整一下繪制瓦片的坐標位置即可,該思想同樣可以用于處理圖片拼接的問題,可按照上面思路進行拼接,這里就不再舉例子說明了,瓦片繪制就是圖片拼接的過程;
圖片旋轉壓縮和拼接都講完啦,在對圖片進行處理,大家都有自己的見解了,或許你們還會這么說,那如果我上傳圖片的時候,像把那些橫著排的照片,也放成豎起來,要怎么處理,竟調整圖片放置的方向,該怎么處理,這就需要用到canvas的rotate方法去實現了,老方法,我們先獲取圖片對象,因為之前的壓縮是放回一個promise對象,data參數為img的base64格式,所以我們把旋轉函數的參數定義為圖片來源;
rotate(imgData) { var img = new Image(); img.src = imgData; var imgR = new Promise((resolve, reject) => { img.onload = ()=>{ console.log(img.width) console.log(img.naturalWidth) } }) },
這里需要注意的是,每次我們新建一個image對象,想要獲取其一些響應的屬性值,一定要在onload方法中,確保圖片已經加載完畢,上面的console中輸出了兩個值,width和naturalWidth,在某中條件下,他們會是相等的,比如我們上面,也會存在不一致的時候,因為naturalWidth返回的依然是圖片的真實尺寸,而width返回的是給img標簽規定的尺寸,所以我們需要獲取的是naturalWidth;
rotate(imgData) { var img = new Image(); img.src = imgData; var imgR = new Promise((resolve, reject) => { img.onload = () => { let degree = 0, drawHeight, drawWidth; drawHeight = img.naturalHeight; drawWidth = img.naturalWidth; let maxSide = Math.max(drawWidth, drawHeight); if (maxSide === drawWidth) {//判斷需要旋轉的角度 degree = 90; } else { degree = 360; } var canvas = document.createElement("canvas"); canvas.width = drawWidth; canvas.height = drawHeight; var context = canvas.getContext("2d"); context.translate(drawWidth/2,drawHeight/2)//這一行和下下一行的作用是修改選擇中心 context.rotate(degree*Math.PI/180);//旋轉圖片 context.translate(-drawWidth/2,-drawHeight/2)//這一行和上上一行的作用是修改選擇中心 context.drawImage(img, 0, 0, drawWidth, drawHeight); var ndata = canvas.toDataURL("image/jpeg", 1); context.width = context.height = 0; resolve(ndata) } }) return Promise.all([imgR]) }
旋轉效果如下,寬大于高的,即是橫排的圖片,就會發生旋轉;
在vue下利用canvas實現上述功能后,發現了canvas在圖片處理這塊的強大功能,對于前端上傳圖片性能的優化會有很大的幫助;經過上述的時間,發現要實現用戶的上傳圖片前的裁剪功能,以及可以利用canvas來實現,主要是利用drawImage控制裁剪的長度,起點坐標就可以實現,著實好用!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/53331.html
摘要:背景作為一名前端工作人員,相信大家在開發系統的時候,經常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個問題的時候,都會虎軀一震,以為會是一個棘手的問題,當你讀完這篇文章的時候,你會發現都是你瞎操作了,真相就是這么簡單 背景 作為一名前端工作人員,相信大家在開發系統的時候,經常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個問題的時候,都會虎...
摘要:背景作為一名前端工作人員,相信大家在開發系統的時候,經常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個問題的時候,都會虎軀一震,以為會是一個棘手的問題,當你讀完這篇文章的時候,你會發現都是你瞎操作了,真相就是這么簡單 背景 作為一名前端工作人員,相信大家在開發系統的時候,經常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個問題的時候,都會虎...
摘要:上傳的文件經過就可以實現預覽圖片了,這方面不清楚的可以查看進階系列文件上傳下載旋轉旋轉需要用到的方法。 前言 在手機上通過網頁 input 標簽拍照上傳圖片,有一些手機會出現圖片旋轉了90度d的問題,包括 iPhone 和個別三星手機。這些手機豎著拍的時候才會出現這種問題,橫拍出來的照片就正常顯示。因此,可以通過獲取手機拍照角度來對照片進行旋轉,從而解決這個問題。 Orientatio...
摘要:引入阿里云的上傳圖片文件調用后臺接口獲取阿里云上傳下載通行證初始化權限去掉對的校驗選擇文件傳到上的名字調用上傳方法上傳文件進度調用后臺添加文件的接口上傳成功上傳失敗彈出上傳失敗的消息如果傳到阿里云的圖片要展示出來要在的圖片路徑后面 引入阿里云oss的js 上傳圖片/文件 mounted () { this.initConfig() // 調用后臺接口獲取阿里云上傳下載通行證 } ...
閱讀 1748·2023-04-25 16:28
閱讀 684·2021-11-23 09:51
閱讀 1467·2019-08-30 15:54
閱讀 1149·2019-08-30 15:53
閱讀 2816·2019-08-30 15:53
閱讀 3413·2019-08-30 15:43
閱讀 3250·2019-08-30 11:18
閱讀 3261·2019-08-26 10:25