先給大家看一下最終效果。
大多數功能都是由Cropper.js封裝好的,調整並製作了:
- 上傳圖片
- 對圖片的裁剪以及調整(旋轉、縮放)、
- 實時預覽
- 將裁剪後的資料儲存為blob傳送至後端。
Q1:為什麼選擇Cropper.js和如何安裝Cropper.js?
一開始製作這個需求思路有兩個,使用canvas原生或者尋找現成的庫,對比了一番覺得canvas實現時間耗費較長,且秉承著不重複造輪子的原則(其實是菜),決定使用Cropper.js。官方封裝了很多引數、方法、事件,上手容易,文件閱讀體驗較好、而且便於擴充套件。
Cropper.js官方倉庫+文件:github.com/fengyuanche…
Installation
npm install cropperjs
複製程式碼
Q2:如何上傳圖片?
我們實現上述功能需要的核心HTMl部分只有:
<!-- 1.一個用於獲取上傳檔案的input,type="file",並且監聽onchange事件 -->
<input
type="file"
accept="image/*"
id="imgReader"
onchange="loadingImg"
>
<!-- 2.一個用於給Cropper.js覆蓋使用的img -->
<img id="cropImg">
<!-- 3.兩個用於預覽的div -->
<div class="previewText">裁剪預覽</div>
<div class="previewBox"></div>
<div class="previewBoxRound"></div>
複製程式碼
首先先將用於上傳的input隱藏起來,我們並不需要它的樣式
.inpuFile{
display: none;
}
複製程式碼
然後給你專案中的某個按鈕新增一個點選事件,並且呼叫
function uploadImg(){
document.querySelector('#imgReader').click()
},
複製程式碼
即可開啟上傳檔案的視窗,然後選擇你需要的圖片
Q3:如何將圖片讀取顯示和使用Cropper.js新增裁剪控制元件?
上傳檔案成功後,會觸發onchange事件,呼叫loadingImg()
//引入Cropper.js
import 'cropperjs/dist/cropper.css';
import Cropper from 'cropperjs';
let CROPPER //建立一個cropper的全域性物件
function loadingImg(eve){
//讀取上傳檔案
let reader = new FileReader();
if(event.target.files[0]){
//readAsDataURL方法可以將File物件轉化為data:URL格式的字串(base64編碼)
reader.readAsDataURL(eve.target.files[0]);
reader.onload = (e)=>{
let dataURL = reader.result;
//將img的src改為剛上傳的檔案的轉換格式
document.querySelector('#cropImg').src = dataURL;
const image = document.getElementById('cropImg');
//建立cropper例項-----------------------------------------
CROPPER = new Cropper(image, {
aspectRatio: 16 / 16,
viewMode:0,
minContainerWidth:500,
minContainerHeight:500,
dragMode:'move',
preview:[ document.querySelector('.previewBox'),
document.querySelector('.previewBoxRound')]
})
}
}
}
複製程式碼
new Cropper方法:
new Cropper(element[, options])
第一個引數:element
- 型別:HTMLImageElement 或 HTMLCanvasElement;
- 作用:用於顯示裁剪功能;
第二個引數(可選):
- 型別: Object;
- 作用:用於新增具體引數設定
我們需要用到的引數有:
{
aspectRatio: 16 / 16, //固定裁剪框的比例(橫/豎),此處16/16則固定為正方形
minContainerWidth:500, //容器最小的寬度
minContainerHeight:500, //容器最小的高度
dragMode:'move', //設定裁剪框為可以移動
preview:[ document.querySelector('.previewBox'), //設定我們需要新增實時預覽的地方
document.querySelector('.previewBoxRound')]
//更多引數請參照官方倉庫...我們這裡用不著
}
複製程式碼
先忽略實時預覽,完成到這裡我們就可看到我們上傳的圖片以及裁剪功能:
Q4:如何進行實時預覽?
上面建立cropper的時候,我們在選項中新增了
preview:[ document.querySelector('.previewBox'),
document.querySelector('.previewBoxRound')]
複製程式碼
preview就是用來設定我們需要實時預覽的地方,但是設定完成之後要給上述的兩個div新增一下樣式,才可以正常顯示
.previewBox,.previewBoxRound{
box-shadow: 0 0 5px #adadad;
width: 100px;
height: 100px;
margin-top: 30px;
overflow: hidden; /*這個超出設定為隱藏很重要,否則就會整個顯示出來了*/
}
.previewBoxRound{
border-radius: 50%; /*設定為圓形*/
}
複製程式碼
Q5:如何獲取裁剪資料併傳送至後端?
function GetData(){
//getCroppedCanvas方法可以將裁剪區域的資料轉換成canvas資料
CROPPER.getCroppedCanvas({
maxWidth: 4096,
maxHeight: 4096,
fillColor: '#fff',
imageSmoothingEnabled: true,
imageSmoothingQuality: 'high',
}).toBlob((blob) => {
//然後呼叫瀏覽器原生的toBlob方法將canvas資料轉換成blob資料
//之後就可以愉快的將blob資料傳送至後端啦,可根據自己情況進行傳送,我這裡用的是axios
const formData = new FormData();
// 第三個引數為檔名,可選填.
formData.append('croppedImage', blob/*, 'example.png' */);
let config = {
headers:{'Content-Type':'multipart/form-data'}
}
this.$axios.post(flow_mission_UploadFile(),param,config)
.then((response)=>{
console.log(response)
})
.catch((err)=>{
console.log(err)
})
})
}
複製程式碼
其他需要注意的地方:
1.裁剪框尺寸問題
裁剪部分預設會根據上傳圖片的大小進行改變
- 解決圖片過小的問題:
//在new Cropper的引數中設定
minContainerWidth:500, //容器最小的寬度
minContainerHeight:500, //容器最小的高度
複製程式碼
- 解決圖片過大的問題: 給新增固定寬度樣式
#cropImg{
height: 450px;
width: 450px;
box-shadow: 0 0 5px #adadad;
}
複製程式碼
2.重複上傳的問題
再次上傳不同圖片的時候,還是出現原來的圖片,只需要在上傳檔案的時候,對之前存在的CROPPER進行摧毀就可以了
function uploadImg(){
document.querySelector('#imgReader').click()
if(CROPPER){
CROPPER.destroy()
}
},
複製程式碼
3.其他功能的實現
這裡列舉幾個我這裡用到的
- CROPPER.rotate(90) :旋轉圖片,單位為數字,90為順時針旋轉90度
- CROPPER.zoom(0.1) :縮放圖片,單位為數字,0.1為在原縮放基礎上增加0.1倍
- CROPPER.reset() :重置對圖片的所有操作
還有很多其他方法和事件可以自行參照倉庫,一個普通的上傳頭像功能就這樣應該夠用了!這裡就不一一列舉啦
如果覺得寫得有不好的地方請多多指教,喜歡的話可以點個贊哈!