場景
前後端分離的項目,前端修改頭像時,需要對頭像進行裁剪并且能實時預覽,然後上傳到SpringBoot背景。
實作效果如下

注:
部落格:
https://blog.csdn.net/badao_liumang_qizhi
關注公衆号
霸道的程式猿
擷取程式設計相關電子書、教程推送與免費下載下傳。
實作
插件官網
https://github.com/xyxiao001/vue-cropper
安裝插件
install vue-cropper
引用插件
元件内使用
import { VueCropper } from 'vue-cropper'
components: {
VueCropper,
},
main.js裡面使用
import VueCropper from 'vue-cropper'
Vue.use(VueCropper)
cdn方式使用
Vue.use(window['vue-cropper'].default)
nuxt 使用方式
if(process.browser) {
vueCropper = require('vue-cropper')
Vue.use(vueCropper.default)
}
這裡隻是在頭像上傳元件内使用,是以采用
import { VueCropper } from 'vue-cropper'
components: {
VueCropper,
},
的方式。
使用
把上傳圖檔和裁剪圖檔和預覽都放在一個dialog裡面,隻有在點選修改頭像按鈕時才顯示此dialog
ref="cropper"
:img="options.img"
:info="true"
:autoCrop="options.autoCrop"
:autoCropWidth="options.autoCropWidth"
:autoCropHeight="options.autoCropHeight"
:fixedBox="options.fixedBox"
@realTime="realTime"
v-if="visible"
/>
cesium加載entity圖檔縮放_Vue中使用vuecroper插件實作圖檔上傳裁剪并傳到SpringBoot背景接口...場景實作
上傳
提 交
這個dialog的布局的效果如下
通過:visible.sync="open" 綁定的是否顯示的變量為open,需要聲明
data() {
return {
// 是否顯示彈出層
open: false,
然後在修改頭像按鈕的點選事件中
// 編輯頭像
editCropper() {
this.open = true;
},
顯示此dialog
然後圖檔裁剪控件的代碼為
ref="cropper"
:img="options.img"
:info="true"
:autoCrop="options.autoCrop"
:autoCropWidth="options.autoCropWidth"
:autoCropHeight="options.autoCropHeight"
:fixedBox="options.fixedBox"
@realTime="realTime"
v-if="visible"
/>
此控件的屬性
名稱 | 功能 | 預設值 | 可選值 |
img | 裁剪圖檔的位址 | 空 | url 位址 || base64 || blob |
outputSize | 裁剪生成圖檔的品質 | 1 | 0.1 - 1 |
outputType | 裁剪生成圖檔的格式 | jpg (jpg 需要傳入jpeg) | jpeg || png || webp |
info | 裁剪框的大小資訊 | true | true || false |
canScale | 圖檔是否允許滾輪縮放 | true | true || false |
autoCrop | 是否預設生成截圖框 | false | true || false |
autoCropWidth | 預設生成截圖框寬度 | 容器的80% | 0~max |
autoCropHeight | 預設生成截圖框高度 | 容器的80% | 0~max |
fixed | 是否開啟截圖框寬高固定比例 | true | true | false |
fixedNumber | 截圖框的寬高比例 | [1, 1] | [寬度, 高度] |
full | 是否輸出原圖比例的截圖 | false | true | false |
fixedBox | 固定截圖框大小 不允許改變 | false | true | false |
canMove | 上傳圖檔是否可以移動 | true | true | false |
canMoveBox | 截圖框能否拖動 | true | true | false |
original | 上傳圖檔按照原始比例渲染 | false | true | false |
centerBox | 截圖框是否被限制在圖檔裡面 | false | true | false |
high | 是否按照裝置的dpr 輸出等比例圖檔 | true | true | false |
infoTrue | true 為展示真實輸出圖檔寬高 false 展示看到的截圖框寬高 | false | true | false |
maxImgSize | 限制圖檔最大寬度和高度 | 2000 | 0-max |
enlarge | 圖檔根據截圖框輸出比例倍數 | 1 | 0-max(建議不要太大不然會卡死的呢) |
mode | 圖檔預設渲染方式 | contain | contain , cover, 100px, 100% auto |
這裡設定此插件的一些屬性與對象options的屬性綁定。
聲明對象options并設定一些屬性
options: {
img: 'https://images.cnblogs.com/cnblogs_com/badaoliumangqizhi/1539113/o_qrcode_for_gh_f76a8d7271eb_258.jpg', //裁剪圖檔的位址
autoCrop: true, // 是否預設生成截圖框
autoCropWidth: 200, // 預設生成截圖框寬度
autoCropHeight: 200, // 預設生成截圖框高度
fixedBox: true // 固定截圖框大小 不允許改變
},
這裡給裁剪的圖檔設定了一張預設圖檔,在上傳後會重新給該img屬性指派,img就是裁剪圖檔的位址。
實時預覽是通過 @realTime="realTime"
綁定的函數realTime
// 實時預覽
realTime(data) {
this.previews = data;
}
會将參數data指派給定義的對象preview
previews: {}
然後上面的布局中預覽的img是
cesium加載entity圖檔縮放_Vue中使用vuecroper插件實作圖檔上傳裁剪并傳到SpringBoot背景接口...場景實作
給img标簽指派參數的url style指派img屬性就可。可以參照其官方案例
@realTime="realTime"
// Real time preview function
realTime(data) {
var previews = data;
var h = 0.5;
var w = 0.2;
this.previewStyle1 = {
width: previews.w + "px",
height: previews.h + "px",
overflow: "hidden",
margin: "0",
zoom: h
};
this.previewStyle2 = {
width: previews.w + "px",
height: previews.h + "px",
overflow: "hidden",
margin: "0",
zoom: w
};
固定為100寬度
this.previewStyle3 = {
width: previews.w + "px",
height: previews.h + "px",
overflow: "hidden",
margin: "0",
zoom: 100 / preview.w
};
固定為100高度
this.previewStyle4 = {
width: previews.w + "px",
height: previews.h + "px",
overflow: "hidden",
margin: "0",
zoom: 100 / preview.h
};
this.previews = data;
},
cesium加載entity圖檔縮放_Vue中使用vuecroper插件實作圖檔上傳裁剪并傳到SpringBoot背景接口...場景實作
中等大小
cesium加載entity圖檔縮放_Vue中使用vuecroper插件實作圖檔上傳裁剪并傳到SpringBoot背景接口...場景實作
迷你大小
cesium加載entity圖檔縮放_Vue中使用vuecroper插件實作圖檔上傳裁剪并傳到SpringBoot背景接口...場景實作
下方那一排的圖檔的縮放和旋轉都是調用的插件自帶的函數
// 向左旋轉
rotateLeft() {
this.$refs.cropper.rotateLeft();
},
// 向右旋轉
rotateRight() {
this.$refs.cropper.rotateRight();
},
// 圖檔縮放
changeScale(num) {
num = num || 1;
this.$refs.cropper.changeScale(num);
},
此插件的其他内置函數
this.$refs.cropper.startCrop() 開始截圖
this.$refs.cropper.stopCrop() 停止截圖
this.$refs.cropper.clearCrop() 清除截圖
this.$refs.cropper.changeScale() 修改圖檔大小 正數為變大 負數變小
this.$refs.cropper.getImgAxis() 擷取圖檔基于容器的坐标點
this.$refs.cropper.getCropAxis() 擷取截圖框基于容器的坐标點
this.$refs.cropper.goAutoCrop 自動生成截圖框函數
this.$refs.cropper.rotateRight() 向右邊旋轉90度
this.$refs.cropper.rotateLeft() 向左邊旋轉90度
圖檔加載的回調 imgLoad 傳回結果success, error
擷取截圖資訊
this.$refs.cropper.cropW 截圖框寬度
this.$refs.cropper.cropH 截圖框高度
// 擷取截圖的base64 資料
this.$refs.cropper.getCropData((data) => {
// do something
console.log(data)
})
// 擷取截圖的blob資料
this.$refs.cropper.getCropBlob((data) => {
// do something
console.log(data)
})
前端上傳圖檔的實作是使用ElementUI的el-upload實作。
上傳
這裡要對其進行一些設定
将其action設定為#不讓其上傳到遠端url,然後重寫覆寫其http-request
// 覆寫預設的上傳行為
requestUpload() {
},
來覆寫其預設的上傳行為。
然後重寫其上傳前的方法進行上傳預處理
// 上傳預處理
beforeUpload(file) {
if (file.type.indexOf("image/") == -1) {
this.msgError("檔案格式錯誤,請上傳圖檔類型,如:JPG,PNG字尾的檔案。");
} else {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
this.options.img = reader.result;
};
}
},
在方法中判斷上傳檔案的類型是否是圖檔,然後擷取圖檔的url并将其指派給option的img屬性,這樣裁剪控件就能擷取到上傳的圖檔的url并能顯示。
而實時預覽也能通過裁剪控件的data的url擷取到。
然後就是點選送出按鈕裁剪後的照片送出給SpringBoot背景
// 上傳圖檔
uploadImg() {
this.$refs.cropper.getCropBlob(data => {
let formData = new FormData();
formData.append("file", data);
uploadimg(formData).then(response => {
if (response.code === 200) {
this.open = false;
this.options.img = process.env.VUE_APP_BASE_API + response.data;
console.log(this.options.img)
this.$emit('changezp', this.options.img)
this.msgSuccess("修改成功");
}
this.visible = false;
});
});
},
通過this.$refs.cropper以及設定的ref="cropper"來擷取裁剪控件,然後調用他的内置函數擷取blob資料。
然後建構一個FormData對象,并設定其file為裁剪圖檔的data
然後将此formData采用post請求的方式送出到SpringBoot背景
// 使用者頭像上傳
export function uploadAvatar(data) {
return request({
url: '/system/user/profile/avatar',
method: 'post',
data: data
})
}
這裡的request是封裝的axios請求對象向背景發動post請求并傳遞data參數。
在SpringBoot背景
@PostMapping("/upload")
public AjaxResult uploadProfile(MultipartFile file){
try {
String path = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file);
path = path.replaceAll("//","/");
System.out.println("========path: " + path);
return AjaxResult.success("success",path);
}catch (Exception e){
e.printStackTrace();
return AjaxResult.error("上傳失敗");
}
}
就能通過MultipartFile file接受到圖檔檔案并上傳到伺服器傳回前端能通路靜态資源的路徑。
具體實作可以參照下面部落格
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108383134