這篇文章帶給大家的內容是關於php佇列的實作程式碼介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
身為前端工作人員,相信大家在開發系統的時候,經常有遇到需要這麼一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個問題的時候,都會虎軀一震,以為會是個棘手的問題,當你讀完這篇文章的時候,你會發現都是你瞎操作了,真相就是這麼簡單,下面進入正題:
#圖片檔案上傳
現在很多項目實現在系統內保存圖片,大多數只是在系統資料庫內保存對應圖片的url,而實際的圖片資源會放在阿里等圖片伺服器上,當然,也有一些項目會選擇在自己的資料庫中保存圖片base64格式的字串,下面講一些這兩種方法的具體實現,實現以一個vue實例來說明:
首先,我們先要從使用者那裡取得圖片資源,這個時候,我們需要用到html的<input>標籤,type值為file,指定input標籤為檔案類型的表單輸入,並將其accept屬性設為"image/*",指定只接受圖片資源的文件;
<input>
接下來,我們就要取得使用者選擇的文件,當使用者選擇完文件的時候,就會觸發input標籤的change事件,我們可以透過監聽該事件,並取得事件對象event,來取得圖片檔案:
<input>
當點擊取得檔案後,我們可以透過$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 <h2>图片拼接</h2><p>需要注意的一点了,上面压缩的过程使用了瓦片绘制,可能会导致拼接过程中不紧凑而产生一条间隙,这个只需要调整一下绘制瓦片的坐标位置即可,该思想同样可以用于处理图片拼接的问题,可按照上面思路进行拼接,这里就不再举例子说明了,瓦片绘制就是图片拼接的过程;</p><h2>图片旋转</h2><p>压缩和拼接都讲完啦,在对图片进行处理,大家都有自己的见解了,或许你们还会这么说,那如果我上传图片的时候,像把那些横着排的照片,也放成竖起来,要怎么处理,竟调整图片放置的方向,该怎么处理,这就需要用到canvas的rotate方法去实现了,老方法,我们先获取图片对象,因为之前的压缩是放回一个promise对象,data参数为img的base64格式,所以我们把旋转函数的参数定义为图片来源;</p><pre class="brush:php;toolbar:false">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控制裁剪的长度,起点坐标就可以实现,着实好用!
以上是基於vue下input實現圖片上傳,壓縮,拼接以及旋轉的程式碼詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!