el-upload 搭配 vue-cropper 实现裁剪图片, 后 上传 回显 ,搭配el-image-viewer实现自定义浏览大图
1 安装 vue-cropper
npm install vue-cropper
2 话不多说 直接上代码 , 复制直接可用(建议新建一个页面 复制进去根据自己的需求去修改 , 感觉好的麻烦动动小手点个赞)
<template>
<div class="clip">
<div>
<span class="pl_button">
<!-- v-loading='loading' -->
<el-upload
ref="pl_upload"
class="upload-demo upload"
list-type="picture-card"
:headers="{
Authorization: tok
}"
action="#"
:on-success="importData_handleAvatarSuccess"
:on-preview="handlePreview"
:on-remove="handleRemove"
:on-change="handleChange"
:file-list="fileList"
:auto-upload='false'
:show-file-list="false"
>
<div class="upload-text" >
<div slot="trigger" v-show="!imgSrc" class="upload-plus">
<i class="el-icon-plus"></i>
<div v-if="fileList.length == 1">重新上传</div>
<div v-else>上传图片</div>
</div>
<div class="upload-icon" v-show="imgSrc" @click.stop>
<el-image
:src="imgSrc"
:fit="'scale-down'"
@click.stop='ensss'
>
</el-image>
<div class="img_mc">
<span><i class="el-icon-delete" @click.stop='expurgate'></i></span>
<span><i class="el-icon-zoom-in" @click.stop='enlargement'></i></span>
</div>
</div>
</div>
</el-upload>
<el-image-viewer v-if="showViewer" :on-close="closeViewer" :url-list="imgSrc_obj" index="9999"/>
</span>
</div>
<div class="">
<el-dialog
:title="'剪裁图片'"
append-to-body
:visible.sync="outerVisible"
width="60%"
@close='closeDialog'
>
<div class="cropper-content">
<div class="cropper" style="text-align:center">
<vue-cropper
ref="cropper"
:img="option.img"
:outputSize="option.outputSize"
:outputType="option.outputType"
:info="option.info"
:canScale="option.canScale"
:autoCrop="option.autoCrop"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
:fixed="option.fixed"
:fixedNumber="option.fixedNumber"
:full="option.full"
:fixedBox="option.fixedBox"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:centerBox="option.centerBox"
:height="option.height"
:infoTrue="option.infoTrue"
:maxImgSize="option.maxImgSize"
:enlarge="option.enlarge"
:mode="option.mode"
@realTime="realTime"
@imgLoad="imgLoad">
</vue-cropper>
<!--底部操作工具按钮-->
<div class="footer-btn">
<div class="scope-btn">
<input type="file" id="uploads" style="position:absolute; clip:rect(0 0 0 0);" accept="image/png, image/jpeg, image/gif, image/jpg" @change="selectImg($event)">
<el-button size="mini" type="danger" plain icon="el-icon-zoom-in" @click="changeScale(1)">放大</el-button>
<el-button size="mini" type="danger" plain icon="el-icon-zoom-out" @click="changeScale(-1)">缩小</el-button>
<el-button size="mini" type="danger" plain @click="rotateLeft">? 左旋转</el-button>
<el-button size="mini" type="danger" plain @click="rotateRight">? 右旋转</el-button>
</div>
<div class="upload-btn">
<el-button size="mini" type="success" @click="submitUpload('blob')">上传图片</el-button>
</div>
</div>
</div>
</div>
</el-dialog>
</div>
</div>
</template>
<script>
import { VueCropper } from 'vue-cropper'
export default {
// mixins: [imageViewMixins],
name: 'UserIndex',
components: {
'el-image-viewer': () => import('element-ui/packages/image/src/image-viewer'),
VueCropper,
},
props: {},
data() {
return {
loading:false,
outerVisible:false,
showViewer:false,//大图
fileList:[],
imgSrc:'',
imgSrc_obj:[],
tok:'',
list_show:'',
previews:{},
option:{
img: '', // 裁剪图片的地址
info: true, // 裁剪框的大小信息
outputSize: 1, // 裁剪生成图片的质量
outputType: 'png', // 裁剪生成图片的格式
canScale: true, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 212, // 默认生成截图框宽度
autoCropHeight: 106, // 默认生成截图框高度
fixedBox: false, // 固定截图框大小 不允许改变
fixed: false, // 是否开启截图框宽高固定比例
fixedNumber: [2, 1], // 截图框的宽高比例
full: false, // 是否输出原图比例的截图
canMoveBox: true, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: false, // 截图框是否被限制在图片里面
infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
canMove: true,
},
};
},
computed: {},
watch: {},
created () {
},
mounted () {
},
methods: {
closeDialog(){//关闭模态框时执行
this.fileList = []
console.log('模态框关闭');
},
importData_handleAvatarSuccess(res, file){//批量导入
console.log(res);
},
handlePreview(val){
console.log('成功',val);
},
handleRemove(val){
console.log("失败",val);
},
handleChange(file, fileList) {
console.log(file);
console.log(fileList);
this.fileList = fileList;
fileList.forEach(item=>{
//文件信息中raw才是真的文件
this.name = item.name
this.list_show = item.raw
})
//转化为blob
let reader = new FileReader()
reader.onload = (e) => {
console.log(e);
let data
if (typeof e.target.result === 'object') {
data = window.URL.createObjectURL(new Blob([e.target.result]))
} else {
data = e.target.result
}
// console.log(data);
this.option.img = data
}
reader.readAsDataURL(this.list_show)
console.log(this.list_show);
this.outerVisible = true
},
async submitUpload(){
this.loading = true
let that = this;
this.$refs.cropper.getCropBlob(async (data) => {
let formData = new FormData();
formData.append('file',data)
console.log(formData);
let file = formData.get("file");
let reader = new FileReader();
that.imgSrc_obj = []
reader.onload = function () {
// base64结果
that.imgSrc = this.result;
that.imgSrc_obj.push(this.result)
// that.loading = false;
};
reader.readAsDataURL(file);
//这里用你自己的上传接口
// let resData = await this.common.Ajax(this, {
// url: this.action_url,
// params: formData
// });
// if (resData.data.code === 200) {
// this.outerVisible = false
// }else{
// // 上传失败后清除 等等 根据自己的代码去修改
// that.imgSrc = ''
// that.imgSrc_obj = []
// }
this.outerVisible = false
})
},
//初始化函数
imgLoad (msg) {
console.log("工具初始化函数====="+msg)
console.log(this.option);
},
//图片缩放
changeScale (num) {
num = num || 1
this.$refs.cropper.changeScale(num)
},
//向左旋转
rotateLeft () {
this.$refs.cropper.rotateLeft()
},
//向右旋转
rotateRight () {
this.$refs.cropper.rotateRight()
},
//实时预览函数
realTime (data) {
this.previews = data
// console.log(this.previews);
},
expurgate(){
console.log('点击删除');
this.imgSrc=''
this.imgSrc_obj=[]
this.fileList = []
},
enlargement(){
console.log('点击浏览大图');
this.showViewer= true
},
closeViewer(){
this.showViewer= false
console.log('关闭浏览大图');
},
}
}
</script>
<style scoped lang="less">
//设置裁剪框样式
.cropper-content {
.cropper {
width: auto;
height: 600px;
.vue-cropper[data-v-6dae58fd]{
height: 84%;
}
}
}
.footer-btn{
margin-top: 30px;
display: flex;
justify-content: center;
.scope-btn{
display: flex;
justify-content: space-between;
padding-right: 10px;
}
.upload-btn{
// flex: 1;
// -webkit-flex: 1;
// display: flex;
// display: -webkit-flex;
// justify-content: center;
}
.btn {
outline: none;
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
-webkit-appearance: none;
text-align: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
outline: 0;
-webkit-transition: .1s;
transition: .1s;
font-weight: 500;
padding: 8px 15px;
font-size: 12px;
border-radius: 3px;
color: #fff;
background-color: #409EFF;
border-color: #409EFF;
margin-right: 10px;
}
}
.upload-text, .upload-icon, .el-image, .img_mc{
width: 100%;
height: 100%;
}
.upload-plus{
display: flex;
justify-content: space-between;
flex-direction: column;
align-items: center;
width: 100%;
height: 100%;
position: relative;
i{
position: absolute;
top: 30px
}
div{
position: absolute;
top: 20px
}
}
.upload-icon{
position: relative;
z-index: 999;
.img_mc{
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
cursor: default;
text-align: center;
color: #fff;
opacity: 0;
font-size: 20px;
background-color: rgba(0,0,0,.5);
-webkit-transition: opacity .3s;
transition: opacity .3s;
span{
display: none;
cursor: pointer;
i{
color: #fff;
font-size: 22px;
}
}
span:nth-child(2){
margin-left: 25%;
}
}
.img_mc:hover{
opacity: 1;
}
.img_mc:hover span{
display: inline-block;
}
}
</style>