基本需求:
- 对上传图片有大小、比例的要求,在上传之前可以进行裁剪
- 先上传到本地,再上传至服务器,要求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",
"150px"
},
img: {
height: "640px",
transform: "scale(0.509375)translate3d(-422.0858895705521px, -361.22699386503064px, 0px)rotateZ(0deg)",
"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=" 150px; height: 150px,; overflow: hidden">
<div style=" 150px; height: 150px">
<img src=blob:http://dev.paas.25.honops.com:8001/fe5d60f5-ce30-40e6-83a7-2a0d9ccb1c68 style=" 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 展示看到的截图框宽高
}