Vue項(xiàng)目實(shí)現(xiàn)html5圖片上傳的示例代碼
選擇圖片 -> 預(yù)覽圖片 -> 裁剪圖片 -> 上傳圖片
我會(huì)以事例貫穿圖片接下來(lái),就詳細(xì)的介紹每個(gè)步驟具體實(shí)現(xiàn)。
圖例
1.選擇圖片
選擇圖片有什么好講的呢?不就一個(gè) input[type=file]
,然后點(diǎn)擊就可以了嗎?確實(shí)是這樣的,但是,我們想要做得更加的友好一些,比如需要過(guò)濾掉非圖片文件, 或只允許從攝像頭拍照獲取圖片等,還是需要進(jìn)行一些簡(jiǎn)單配置的。
下面就先來(lái)看看最簡(jiǎn)單的選擇文件:
<input type="file" />
上面可以查看到非圖片類型的文件,這并不是我們想要的結(jié)果,畢竟我們只想要圖片類型??梢酝ㄟ^(guò) accept
屬性來(lái)實(shí)現(xiàn),如下:
<input type="file" accept="image/*">
這樣就可以過(guò)濾掉非圖片類型了。但是圖片的類型可能也太多了, 有些可能服務(wù)器不支持,所以,如果想保守一些,只允許 jpg
和 png
類型,可以寫(xiě)成這樣:
<input type="file" accept="image/jpg, image/jpeg, image/png">
或這樣
<input type="file" accept=".jpg, .jpeg, .jpg">
OK, 過(guò)濾非圖片的需求搞定了。但是有時(shí)候 ,產(chǎn)品還要求只能從攝像頭采集圖片,比如需要上傳證件照,防止從網(wǎng)上隨便找別人的證件上傳,那capture
屬性就可以派上用場(chǎng)了:
<input type="file" accept="image/*" capture>
這時(shí)候,就不能從文件系統(tǒng)中選擇照片了,只能從攝像頭采集。到了這一步,可能覺(jué)得很完美了,但是還有個(gè)問(wèn)題,可能有些變態(tài)產(chǎn)品要求默認(rèn)打開(kāi)前置攝像頭采集圖片,比如就是想要你的自拍照片。 capture
默認(rèn)調(diào)用的是后置攝像頭。默認(rèn)啟用前置攝像頭可以設(shè)置 capture="user"
,如下:
<input type="file" accept="image/*" capture="user">
好啦,關(guān)于選擇圖片的就講么這么多了,有個(gè)注意的地方是,可能有些配置在兼容性上會(huì)有一些問(wèn)題,所以需要在不同的機(jī)型上測(cè)試一下看看效果。
下面再來(lái)談?wù)勵(lì)A(yù)覽圖片的實(shí)現(xiàn)。
2.預(yù)覽圖片
不使用圖片預(yù)覽,點(diǎn)擊上傳圖片后無(wú)法查看 例如下圖:我重新?lián)Q了圖片,圖片路徑變了,但圖片沒(méi)變
2.1添加圖片預(yù)覽代碼
圖片變了可以預(yù)覽查看
源碼1: 使用 URL.createObjectURL 預(yù)覽
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> img { width: 300px; height: 200px; } </style> </head> <body> <form action="" method="get"> <input id="inputFile" type="file" accept="image/*"> <img src="./301571.jpg" id="previewImage" alt="圖片預(yù)覽" title="活在風(fēng)浪里..."> </form> <!-- 圖片預(yù)覽 --> <script> const $ = document.getElementById.bind(document); const $inputFile = $('inputFile'); const $previewImage = $('previewImage'); $inputFile.addEventListener('change', function() { const file = this.files[0]; $previewImage.src = file ? URL.createObjectURL(file) : ''; }, this); </script> </body> </html>
源碼2:使用 FileReader 預(yù)覽
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> img { width: 300px; height: 200px; } </style> </head> <body> <form action="" method="get"> <input id="inputFile" type="file" accept="image/*"> <img src="./301571.jpg" id="previewImage" alt="圖片預(yù)覽"> </form> <!-- 圖片預(yù)覽 --> <script> const $ = document.getElementById.bind(document); const $inputFile = $('inputFile'); const $previewImage = $('previewImage'); $inputFile.addEventListener('change', function() { const file = this.files[0]; const reader = new FileReader(); reader.addEventListener('load', function() { $previewImage.src = reader.result; }, false); if (file) { reader.readAsDataURL(file); } }, false) </script> </body> </html>
預(yù)覽圖片總結(jié):
兩種方法的對(duì)比
我個(gè)人更加傾向于使用 URL.createObjectURL()
。主要原先它的 API 簡(jiǎn)潔,同步讀取,并且他返回的是一個(gè) URL
,比 FileReaer
返回的base64 更加精簡(jiǎn)。兼容性上,兩者都差不多,都是在 WD
的階段。性能上的對(duì)比, 在 chrome 上, 選擇了一張 2M 的圖片, URL.createObjectURL()
用時(shí)是 0 , 而 FileReader
用時(shí) 20ms 左右。 0 感覺(jué)不太合理,雖然這個(gè)方法立刻就會(huì)返回一個(gè) URL ,但是我猜測(cè)實(shí)際上這個(gè) URL 指定的內(nèi)容還沒(méi)有生成好,應(yīng)該是異步生成的,然后才渲染出來(lái)的。所以并沒(méi)有很好的辦法來(lái)對(duì)比他們的性能。
3.裁剪圖片
關(guān)于圖片的裁剪,很自然的會(huì)想到使用 canvas
,確實(shí)是要通過(guò) canvas
, 但是如果全部我們自己來(lái)實(shí)現(xiàn),可能需要做比較多的工作,所以為了省力,我們可以站在巨人的肩膀上。比較優(yōu)秀的圖片裁剪庫(kù)是cropperjs , 該庫(kù)可以對(duì)圖片進(jìn)行縮放、移動(dòng)和旋轉(zhuǎn)。隨后會(huì)持續(xù)更新canvas,(我也在學(xué)..永遠(yuǎn)保持謙遜,人外人天外天,拒絕凡爾賽 )
cropperjs
的詳細(xì)配置這里就不展開(kāi)了 ,需要的可以自己去看文檔就好。下面我們就以這個(gè)庫(kù)為基礎(chǔ),實(shí)現(xiàn)一個(gè)裁剪人臉的例子:
源碼: 當(dāng)然這個(gè)只是簡(jiǎn)單的寫(xiě)下,為了寫(xiě)博客在電腦操作小伙伴要自行查看下移動(dòng)端兼容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" > <script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.min.js"></script> <style> .preview-image, .cropper-image { max-width: 100%; } .cropper { display: none; position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: #ccc; font-size: 0.27rem; text-align: center; } .inner { height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; } .face-container { position: relative; width: 320px; height: 320px; margin: 50px auto; } .cropper-modal { background: url('https://ok.166.net/gameyw-misc/opd/squash/20191028/152551-m37snfsyu1.png') center no-repeat; background-size: 100% 100%; opacity: 1; } .cropper-bg { background: none; } .cropper-view-box { opacity: 0; } .tips { font-size: 16px; } .toolbar { display: flex; justify-content: center; margin: 50px 0; } .btn { width: 150px; line-height: 40px; font-size: 20px; text-align: center; color: #fff; background: #007fff; } </style> </head> <body> <form name="input" action="html_form_action.php" method="get"> <input id="inputFile" type="file" accept="image/*"> <img class="preview-image" id="previewImage" src="" alt=""> <!-- cropper裁剪框 --> <div class="cropper" id="cropper"> <div class="inner"> <div class="face-container"> <img class="cropper-image" id="cropperImage"> </div> <div class="tips">請(qǐng)將面部區(qū)域置于人臉框架內(nèi)</div> <div class="toolbar"> <div class="btn" id="confirm">確認(rèn)</div> </div> </div> </div> </form> </body> <script> const $ = document.getElementById.bind(document); const $cropper = $('cropper'); const $inputFile = $('inputFile'); const $previewImage = $('previewImage'); const $cropperImage = $('cropperImage'); const $confirmBtn = $('confirm') let cropperInstance = null; // 選擇圖片后,顯示圖片裁剪框 $inputFile.addEventListener('change', function() { const file = this.files[0]; if (!file) return; $cropperImage.src = URL.createObjectURL(file); showCropper(); }, false); // 點(diǎn)擊確認(rèn)按鈕,將裁剪好的圖片放到 img 標(biāo)簽顯示。 $confirmBtn.addEventListener('click', function() { const url = cropperInstance.getCroppedCanvas().toDataURL("image/jpeg", 1.0); $cropper.style.display = 'none'; $previewImage.src = url; }, false); function showCropper() { $cropper.style.display = 'block'; cropperInstance && cropperInstance.destroy(); cropperInstance = new Cropper($cropperImage, { viewMode: 1, aspectRatio: 1, autoCropArea: 1, dragMode: 'move', guides: false, highlight: false, cropBoxMovable: false, cropBoxResizable: false }); } </script> </html>
4.上傳
前面的操作已經(jīng)完成了圖片上傳前的準(zhǔn)備,包括選擇圖片、預(yù)覽圖片、編輯圖片等,那接下來(lái)就可以上傳圖片了。上面的例子中,使用了 cropperInstance.getCroppedCanvas()
方法來(lái)獲取到對(duì)應(yīng)的 canvas
對(duì)象 。有了 canvas
對(duì)象就好辦了,因?yàn)?canvas.toBlob()
方法可以取得相應(yīng)的 Blob
對(duì)象,然后,我們就可以把這個(gè) Blob
對(duì)象添加到 FromData
進(jìn)行無(wú)刷新的提交了。大概的代碼如下:
change(e) { // 1.手寫(xiě)的input需要一個(gè)對(duì)象將本地圖片轉(zhuǎn)換為對(duì)應(yīng)的格式來(lái)上傳 let formData = new FormData(); //2. e.target.files就是選中的圖片的一個(gè) formData.append("file", e.target.files[0]); // 3. 將formData這個(gè)對(duì)象傳給修改頭像的接口 updateImg(formData).then((res) => { //4.此時(shí)已經(jīng)傳到修改頭像接口了 //4.1 傳到修改頭像的接口后 , 在更新接口中 再次更新頭像屬性 update({ avatar: res.data.path }); //存到本地 //info是本地存儲(chǔ)點(diǎn)擊頭像獲取的個(gè)人信息,在此頁(yè)面初始調(diào)用本地存儲(chǔ)數(shù)據(jù), //這里賦值info對(duì)象,因?yàn)樯厦驿秩绢^像用的是本地,所以(修改后端圖片路徑,重新調(diào)用后端更新接口后), //還要重新賦值本地存儲(chǔ),才能后端變化.本地頁(yè)面,因?yàn)槭屈c(diǎn)擊頭像進(jìn)入修改頁(yè),才存儲(chǔ)的數(shù)據(jù),不會(huì)隨后端更新, //所以還要重新賦值本地存儲(chǔ) this.info.avatar = res.data.path; localStorage.setItem("userInfo-Avatar", JSON.stringify(this.info)); this.show2 = false; }); },
浪哥tips: 如果在移動(dòng)端,有的手機(jī)會(huì)檢測(cè)自動(dòng)校正角度,導(dǎo)致有些角度不對(duì)可以使用 CSS 的 transfrom: rotate(-90deg)
順時(shí)針旋轉(zhuǎn) 90 度抵消掉這個(gè)角度就好。
到此這篇關(guān)于Vue項(xiàng)目實(shí)現(xiàn)html5圖片上傳的示例代碼的文章就介紹到這了,更多相關(guān)Vue html5圖片上傳內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 使用Vue實(shí)現(xiàn)圖片上傳的三種方式
- vue+elementUI實(shí)現(xiàn)圖片上傳功能
- vue.js 圖片上傳并預(yù)覽及圖片更換功能的實(shí)現(xiàn)代碼
- vue實(shí)現(xiàn)圖片上傳功能
- vue+element實(shí)現(xiàn)圖片上傳及裁剪功能
- Vue2.0 實(shí)現(xiàn)移動(dòng)端圖片上傳功能
- vue+elementUi圖片上傳組件使用詳解
- vue實(shí)現(xiàn)圖片上傳到后臺(tái)
- 基于vue+ bootstrap實(shí)現(xiàn)圖片上傳圖片展示功能
- Vue formData實(shí)現(xiàn)圖片上傳
相關(guān)文章
報(bào)錯(cuò)[vuex] unknown action type: userLogin問(wèn)
這篇文章主要介紹了報(bào)錯(cuò)[vuex] unknown action type: userLogin問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06Vue 級(jí)聯(lián)下拉框的設(shè)計(jì)與實(shí)現(xiàn)
在前端開(kāi)發(fā)中,級(jí)聯(lián)選擇框是經(jīng)常用到的,這樣不僅可以增加用戶輸入的友好性,還能減少前后端交互的數(shù)據(jù)量。本文就介紹一下使用Vue實(shí)現(xiàn)級(jí)聯(lián)下拉框,感興趣的可以了解一下2021-07-07Vue實(shí)現(xiàn)模糊查詢的簡(jiǎn)單方法實(shí)例
這篇文章主要給大家介紹了關(guān)于Vue實(shí)現(xiàn)模糊查詢的簡(jiǎn)單方法,在vue中,前端模糊搜索主要是用computed屬性實(shí)現(xiàn),本文通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08Vue?uni-app框架實(shí)現(xiàn)上拉加載下拉刷新功能
uni-app是一個(gè)使用Vue.js(opens?new?window)開(kāi)發(fā)所有前端應(yīng)用的框架,開(kāi)發(fā)者編寫(xiě)一套代碼,可發(fā)布到iOS、Android、Web(響應(yīng)式)、以及各種小程序(微信/支付寶/百度/頭條/飛書(shū)/QQ/快手/釘釘/淘寶)、快應(yīng)用等多個(gè)平臺(tái)2022-09-09Vue基礎(chǔ)popover彈出框編寫(xiě)及bug問(wèn)題分析
這篇文章主要為大家介紹了Vue基礎(chǔ)popover彈出框編寫(xiě)及bug問(wèn)題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Vue使用Echarts實(shí)現(xiàn)數(shù)據(jù)可視化的方法詳解
這篇文章主要為大家詳細(xì)介紹了Vue使用Echarts實(shí)現(xiàn)數(shù)據(jù)可視化的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03