基本需求:
- 對上傳圖片有大小、比例的要求,在上傳之前可以進行裁剪
- 先上傳到本地,再上傳至服務器,要求bsae64格式
剪裁效果圖如下:
vue-cropper的使用
安裝
npm install vue-cropper --save
在main.js中引入
import VueCropper from 'vue-cropper'
Vue.use(VueCropper)
前端代碼 這里使用ant-design-vue組件
代碼如下
<a-modal
title="頭像上傳"
:visible="visible"
:mask-closable="false"
:confirm-loading="confirmLoading"
:width="700"
:footer="null"
@cancel="cancelHandel">
<a-row>
<a-col :xs="24" :md="12" :style="{ height: '350px' }">
<vue-cropper
ref="cropper"
:img="options.img"
:info="true"
:auto-crop="options.autoCrop"
:auto-crop-width="options.autoCropWidth"
:auto-crop-height="options.autoCropHeight"
:fixed-box="options.fixedBox"
@realTime="realTime"
>
</vue-cropper>
</a-col>
<a-col :xs="24" :md="12" :style="{ height: '350px' }">
<div :style="previews.div" class="avatar-upload-preview">
<img :src="previews.url" :style="previews.img" />
</div>
</a-col>
</a-row>
<a-row style="margin-top: 20px;">
<a-col :lg="2" :md="2" style="margin-right: 20px;">
<a-upload
name="file"
accept="image/*"
:before-upload="beforeUpload"
:show-upload-list="false">
<a-button icon="upload">選擇圖片</a-button>
</a-upload>
</a-col>
<a-col :lg="{ span: 1, offset: 2 }" :md="2">
<a-button icon="plus" @click="changeScale(1)" />
</a-col>
<a-col :lg="{ span: 1, offset: 1 }" :md="2">
<a-button icon="minus" @click="changeScale(-1)" />
</a-col>
<a-col :lg="{ span: 1, offset: 1 }" :md="2">
<a-button icon="undo" @click="rotateLeft" />
</a-col>
<a-col :lg="{ span: 1, offset: 1 }" :md="2">
<a-button icon="redo" @click="rotateRight" />
</a-col>
<a-col :lg="{ span: 2, offset: 6 }" :md="2">
<a-button type="primary" @click="finish('blob')">保存</a-button>
</a-col>
</a-row>
</a-modal>
這里用到了a-upload
組件,因為是上傳到本地,且不需要展示列表,所以需要將show-upload-list
設為false
,before-upload
也需要返回false
,阻止直接上傳至服務器。
js代碼如下
<script>
export default {
name: 'avatarModal',
data () {
return {
visible: false,
id: null,
confirmLoading: false,
options: {
img: '', // 需要剪裁的圖片
autoCrop: true, // 是否默認生成截圖框
autoCropWidth: 150, // 默認生成截圖框的寬度
autoCropHeight: 150, // 默認生成截圖框的長度
fixedBox: true // 是否固定截圖框的大小 不允許改變
},
previews: {} // 裁剪之后的結果
}
},
methods: {
edit (id) {
this.visible = true
this.id = id
},
close () {
this.id = null
this.visible = false
},
cancelHandel () {
this.close()
},
// 圖片放大/縮小
changeScale (num) {
num = num || 1
this.$refs.cropper.changeScale(num)
},
// 左旋轉
rotateLeft () {
this.$refs.cropper.rotateLeft()
},
// 右旋轉
rotateRight () {
this.$refs.cropper.rotateRight()
},
beforeUpload (file) {
const reader = new FileReader()
// 轉化為base64
reader.readAsDataURL(file)
reader.onload = () => {
// 獲取到需要剪裁的圖片 展示到剪裁框中
this.options.img = reader.result
}
return false
},
// 上傳圖片(點擊保存按鈕)
finish (type) {
this.$refs.cropper.getCropData((data) => {
this.visible = false
console.log(data)
// data為base64圖片,供接口使用
this.$emit('save', data)
})
},
// 裁剪之后的數據
realTime (data) {
this.previews = data
}
}
}
</script>
裁剪之后的數據格式
{
div: {
height: "150px",
width: "150px"
},
img: {
height: "640px",
transform: "scale(0.509375)translate3d(-422.0858895705521px, -361.22699386503064px, 0px)rotateZ(0deg)",
width: "640px"
},
h: 150,
w: 150,
url: "blob:http://dev.paas.25.honops.com:8001/fe5d60f5-ce30-40e6-83a7-2a0d9ccb1c68",
html: "
<div class="show-preview" style="width: 150px; height: 150px,; overflow: hidden">
<div style="width: 150px; height: 150px">
<img src=blob:http://dev.paas.25.honops.com:8001/fe5d60f5-ce30-40e6-83a7-2a0d9ccb1c68 style="width: 640px; height: 640px; transform:
scale(0.509375)translate3d(-422.0858895705521px, -361.22699386503064px, 0px)rotateZ(0deg)">
</div>
</div>"
}
主要用於右側的圖片裁剪預覽展示。
vue-cropper的其他屬性,僅供參考
option: {
img: '', // 裁剪圖片的地址
info: true, // 裁剪框的大小信息
outputSize: 0.8, // 裁剪生成圖片的質量 [1至0.1]
outputType: 'jpeg', // 裁剪生成圖片的格式
canScale: false, // 圖片是否允許滾輪縮放
autoCrop: true, // 是否默認生成截圖框
autoCropWidth: 300, // 默認生成截圖框寬度
autoCropHeight: 200, // 默認生成截圖框高度
fixedBox: true, // 固定截圖框大小 不允許改變
fixed: true, // 是否開啟截圖框寬高固定比例
fixedNumber: [7, 5], // 截圖框的寬高比例
full: true, // 是否輸出原圖比例的截圖
canMoveBox: false, // 截圖框能否拖動
original: false, // 上傳圖片按照原始比例渲染
centerBox: false, // 截圖框是否被限制在圖片里面
infoTrue: true // true 為展示真實輸出圖片寬高 false 展示看到的截圖框寬高
}