需求
vue-cropper官网
https://github.com/xyxiao001/vue-cropper
需求:上传图片之前,进行剪裁成690*350尺寸的图片,剪裁后上传到服务器
步骤
-
安装
npm install vue-cropper
-
使用
main.js里面全局使用import VueCropper from 'vue-cropper' Vue.use(VueCropper)
-
组件使用 --父组件
<el-form-item label="添加封面" prop="imageUrl">
<userAvatar :user="form.imageUrl" @getimg="getavatar" v-if="flag"/>
</el-form-item>
// 引入子组件
import userAvatar from "./userAvatar";
components: { userAvatar},
// 获取头像地址 父子传参-->子传父 函数
getavatar(val){
this.form.imageUrl = val
},
- 组件使用 --封装子组件userAvatar
template
<template>
<div>
<div class="avr" @click="editCropper()" v-show="isup">
<i class="el-icon-plus"></i>
</div>
<img v-show="!isup" v-bind:src="options.img" @click="editCropper()" title="点击上传头像" class="img-circle img-lg190" />
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body @opened="modalOpened">
<el-row>
<el-col :xs="24" :md="14" :style="{height: '450px'}">
<vue-cropper
ref="cropper"
:img="options.img"
:output-size="options.size"
:output-type="options.outputType"
:info="options.info"
:full="options.full"
:canScale="options.canScale"
:can-move="options.canMove"
:can-move-box="options.canMoveBox"
:fixed="options.fixed"
:fixed-box="options.fixedBox"
:original="options.original"
:auto-crop="options.autoCrop"
:auto-crop-width="options.autoCropWidth"
:auto-crop-height="options.autoCropHeight"
:center-box="options.centerBox"
:high="options.high"
:info-true="options.infoTrue"
:max-img-size="options.maxImageSize"
:enlarge="options.enlarge"
:mode="options.mode"
:maxImgSize="options.maxImgSize"
@realTime="realTime"
v-if="visible"
/>
</el-col>
<el-col :xs="24" :md="10" :style="{height: '350px'}">
<div class="avatar-upload-preview zidingyi">
<img :src="previews.url" :style="previews.img" />
</div>
</el-col>
</el-row>
<br />
<el-row>
<el-col :lg="2" :md="2">
<el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
<el-button size="small">
上传
<i class="el-icon-upload el-icon--right"></i>
</el-button>
</el-upload>
</el-col>
<el-col :lg="{span: 1, offset: 2}" :md="2">
<el-button icon="el-icon-plus" size="small" @click="changeScale(1)"></el-button>
</el-col>
<el-col :lg="{span: 1, offset: 1}" :md="2">
<el-button icon="el-icon-minus" size="small" @click="changeScale(-1)"></el-button>
</el-col>
<el-col :lg="{span: 1, offset: 1}" :md="2">
<el-button icon="el-icon-refresh-left" size="small" @click="rotateLeft()"></el-button>
</el-col>
<el-col :lg="{span: 1, offset: 1}" :md="2">
<el-button icon="el-icon-refresh-right" size="small" @click="rotateRight()"></el-button>
</el-col>
<el-col :lg="{span: 2, offset: 6}" :md="2">
<el-button type="primary" size="small" @click="uploadImg()">提 交</el-button>
</el-col>
</el-row>
</el-dialog>
</div>
</template>
script
<script>
import { VueCropper } from "vue-cropper";
import { uploadAvatarHttp } from "@/api/system/user";
export default {
components: { VueCropper },
props: {
user: '',// 接收父组件的url值
},
data() {
return {
isup: true,
// 是否显示弹出层
open: false,
// 是否显示cropper
visible: false,
// 弹出层标题
title: "上传封面",
options: {
img: this.user, //裁剪图片的地址
outputSize: 1, // 裁剪生成图片的质量
outputType: 'png', // 裁剪生成图片的格式
full: false, // 是否输出原图比例的截图
info: true, // 图片大小信息
canScale: true, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 345, // 默认生成截图框宽度
autoCropHeight: 175, // 默认生成截图框高度
canMove: true, // 上传图片是否可以移动
fixedBox: true, // 固定截图框大小 不允许改变
fixed: false, // 是否开启截图框宽高固定比例
canMoveBox: true, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: false, // 截图框是否被限制在图片里面
height: true,
infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
enlarge: 2, // 图片根据截图框输出比例倍数
mode: 'cover', // 图片默认渲染方式
maxImgSize: 690 // 限制图片最大宽度和高度
},
previews: {}
};
},
mounted(){
console.log(this.user)
if(this.options.img){
this.isup = false
}else{
this.isup = true
}
},
methods: {
// 编辑头像
editCropper() {
console.log('1')
this.open = true;
},
// 打开弹出层结束时的回调
modalOpened() {
console.log('2')
this.visible = true;
},
// 覆盖默认的上传行为
requestUpload() {
},
// 向左旋转
rotateLeft() {
this.$refs.cropper.rotateLeft();
},
// 向右旋转
rotateRight() {
this.$refs.cropper.rotateRight();
},
// 图片缩放
changeScale(num) {
num = num || 1;
this.$refs.cropper.changeScale(num);
},
// 上传预处理
beforeUpload(file) {
console.log(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;
};
}
},
// 上传图片
uploadImg() {
this.$refs.cropper.getCropBlob(data => {
let formData = new FormData();
// 利用File Api中blob转成File对象
let files = new window.File([data], 'fileName.jpg')
formData.append("file", files);
console.log(files)
uploadAvatarHttp(formData,1).then(response => { // uploadAvatarHttp上传封装的函数
this.open = false;
this.options.img = response.data.url;
// this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl;
if(this.options.img){
this.isup = false
}else{
this.isup = true
}
this.$emit('getimg',this.options.img)
// store.commit('SET_AVATAR', this.options.img);
// this.msgSuccess("修改成功");
this.visible = false;
});
});
},
// 实时预览
realTime(data) {
this.previews = data;
console.log(this.previews)
}
}
};
</script>
<style scoped>
.img-lg190{
width: 315.4px;
height: 160px;
border-radius: 0;
}
.avr{
width: 315px;
height: 160px;
border: 1px solid #E3E3E3;
border-radius: 2px;
line-height: 190px;
text-align: center;
}
.el-icon-plus{
font-size: 40px;
color: #E3E3E3;
}
.zidingyi{
width: 345px;
height: 175px;
border-radius: 0;
transform:scale(0.7);
}
</style>
- 解释
上传逻辑
<el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
<el-button size="small">
上传
<i class="el-icon-upload el-icon--right"></i>
</el-button>
</el-upload>
before-upload:上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。
http-request:覆盖默认的上传行为,可以自定义上传的实现
show-file-list:是否显示已上传文件列表
// 上传预处理
beforeUpload(file) {
console.log(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;
};
}
},
FileReader 对象:允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,
使用 File 或 Blob 对象指定要读取的文件或数据。
readAsDataURL file 将文件读取为 DataURL
onload 文件读取成功完成时触发
更多参考:https://www.jianshu.com/p/cde728c4e334
<vue-cropper
ref="cropper"
:img="options.img"
:output-size="options.size"
:output-type="options.outputType"
:info="options.info"
:full="options.full"
:canScale="options.canScale"
:can-move="options.canMove"
:can-move-box="options.canMoveBox"
:fixed="options.fixed"
:fixed-box="options.fixedBox"
:original="options.original"
:auto-crop="options.autoCrop"
:auto-crop-width="options.autoCropWidth"
:auto-crop-height="options.autoCropHeight"
:center-box="options.centerBox"
:high="options.high"
:info-true="options.infoTrue"
:max-img-size="options.maxImageSize"
:enlarge="options.enlarge"
:mode="options.mode"
:maxImgSize="options.maxImgSize"
@realTime="realTime"
v-if="visible"
/>
options: {
img: this.user, //裁剪图片的地址
outputSize: 1, // 裁剪生成图片的质量
outputType: 'png', // 裁剪生成图片的格式
full: false, // 是否输出原图比例的截图
info: true, // 图片大小信息
canScale: true, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 345, // 默认生成截图框宽度
autoCropHeight: 175, // 默认生成截图框高度
canMove: true, // 上传图片是否可以移动
fixedBox: true, // 固定截图框大小 不允许改变
fixed: false, // 是否开启截图框宽高固定比例
canMoveBox: true, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: false, // 截图框是否被限制在图片里面
height: true,
infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
enlarge: 2, // 图片根据截图框输出比例倍数
mode: 'cover', // 图片默认渲染方式
maxImgSize: 690 // 限制图片最大宽度和高度
},
vue-cropper插件注释
裁剪为690*350
autoCropWidth: 345, // 默认生成截图框宽度
autoCropHeight: 175, // 默认生成截图框高度
enlarge: 2, // 图片根据截图框输出比例倍数
full: false, // 是否输出原图比例的截图
fixedBox: true, // 固定截图框大小 不允许改变
fixed: false, // 是否开启截图框宽高固定比例
original: false, // 上传图片按照原始比例渲染
点击提交传url地址给父组件
uploadImg() {
this.$refs.cropper.getCropBlob(data => {
let formData = new FormData();
// 利用File Api中blob转成File对象
let files = new window.File([data], 'fileName.jpg')
formData.append("file", files);
console.log(files)
uploadAvatarHttp(formData,1).then(response => { // uploadAvatarHttp上传封装的函数
this.open = false;
this.options.img = response.data.url;
// this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl;
if(this.options.img){
this.isup = false
}else{
this.isup = true
}
this.$emit('getimg',this.options.img) // 子传父
this.visible = false;
});
});
},