效果图如下:
一、安装裁剪插件
npm install cropperjs
二、局部组件引入
import Cropper from "cropperjs";
import "cropperjs/dist/cropper.css";
三、所有代码如下
<template>
<div>
<!--
功能需求说明:
1.实现头像上传进行预览
2.裁剪头像
-->
<el-card style="margin-top:20px">
<div slot="header" class="clearfix">
<span>裁剪图片</span>
</div>
<div class="demo-basic--circle">
<div class="block">
<el-avatar :size="100" :src="image"></el-avatar>
<el-button type="primary" @click="handleChangeImage">修改头像</el-button>
</div>
</div>
</el-card>
<!-- 上传头像弹窗 -->
<el-dialog title="上传头像" :visible.sync="dialogVisible" width="767px" :before-close="handleCancel">
<div class="uploadImg">
<el-upload ref='upload' :limit="2" action="#" :file-list="fileList" class="upload-demo" drag :show-file-list="true" list-type="picture" :http-request="handleUploadImg" :on-change="handleChange" :before-upload="beforeUpload">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">
只能上传jpg/jpeg/png/gif文件,且不超过2MB
</div>
</el-upload>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="handleCancel">取 消</el-button>
<el-button type="primary" @click="handleClickSure">确 定</el-button>
</span>
</el-dialog>
<!-- 修改裁剪头像弹窗 -->
<el-dialog title="上传头像" :visible.sync="dialogTx" width="767px">
<div class="imgBox">
<div class="leftBox">
<div class="img">
<img :src="imgUrl" alt="" id="image" />
</div>
<div class="btn">
<el-button size="mini" type="primary" @click="handleRotateLeft">左旋转</el-button>
<el-button size="mini" type="primary" @click="handleRotateRight">右旋转</el-button>
<el-button size="mini" type="primary" @click="handleZoomBig">放大</el-button>
<el-button size="mini" type="primary" @click="handleZoomSmall">缩小</el-button>
<el-button size="mini" type="primary" @click="handleReset">重置</el-button>
</div>
</div>
<div class="rightBox">
<p>预览</p>
<div class="topImg">
<img :src="state.cropperImgBase64" alt="" />
<p>100x100</p>
</div>
<div class="bottomImg">
<img :src="state.cropperImgBase64" alt="" />
<p>50x50</p>
</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="handleDialogTx">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Cropper from "cropperjs";
import "cropperjs/dist/cropper.css";
export default {
data() {
return {
image: require("../assets/person.jpg"),
dialogVisible: false,
dialogTx: false,
imgUrl: "",
fileList:[],
state: {
cropper: null,
cropperImgBase64: "",
},
};
},
methods: {
//修改头像
handleChangeImage() {
this.dialogVisible = true;
},
handleUploadImg(file) {},
//确定按钮
handleClickSure() {
this.dialogVisible = false;
this.fileList = [];
this.dialogTx = true;
this.init();
},
handleCancel(){
this.fileList = [];
this.dialogVisible = false;
},
//change事件
handleChange(file, fileList) {
console.log(file, fileList);
// 解决上传文件limit为1时,不触发onchange方法,在第二次调用的时候将第一个文件删除
if (this.$refs.upload.uploadFiles.length > 1) {
this.$refs.upload.uploadFiles.shift()
}
this.imgUrl = file.url;
},
//上传之前的校验
beforeUpload(file) {
console.log(file);
const isJPG =['image/png','image/jpeg','image/jpg','image/gif'].includes(file.type)
console.log(isJPG);
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!');
this.dialogVisible = true;
this.dialogTx = false;
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
this.dialogVisible = true;
this.dialogTx = false;
}
return isJPG && isLt2M;
},
init() {
this.$nextTick(() => {
const image1 = document.querySelector("#image");
this.state.cropper = new Cropper(image1, {
viewMode: 1,
dragMode: "none",
initialAspectRatio: 1,
aspectRatio: 1,
preview: ".before",
background: true,
autoCropArea: 0.6,
zoomOnWheel: true,
crop: () => {
this.state.cropperImgBase64 = this.state.cropper.getCroppedCanvas().toDataURL("image/jpeg");
// console.log(this.state.cropper.getCroppedCanvas().toDataURL("image/jpeg"));
},
});
});
},
handleDialogTx() {
this.dialogTx = false;
this.image = this.state.cropperImgBase64;
//非常重要,不销毁第二次上传会一直报错
this.state.cropper.destroy();
},
handleClose(){
this.dialogTx = false;
this.state.cropper.destroy();
},
//左旋转
handleRotateLeft() {
//旋转角度可以自定义
this.state.cropper.rotate(-45);
},
// 右旋转
handleRotateRight() {
this.state.cropper.rotate(45);
},
//放大
handleZoomBig() {
this.state.cropper.zoom(0.1);
},
//缩小
handleZoomSmall() {
this.state.cropper.zoom(-0.1);
},
handleReset() {
this.state.cropper.reset()
}
},
};
</script>
<style lang="less" scoped>
/deep/.el-upload-dragger {
width: 100%;
}
/deep/.el-upload {
width: 100%;
}
.block {
display: flex;
flex-direction: column;
justify-content: center;
.el-button {
margin-top: 15px;
align-self: flex-start;
}
}
.imgBox {
display: flex;
.leftBox {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.btn {
padding: 20px;
}
.img {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 400px;
img {
width: 200px;
height: 200px;
}
}
}
.rightBox {
width: 30%;
display: flex;
flex-direction: column;
// border: 1px solid #000;
align-items: center;
text-align: center;
.topImg {
img {
width: 150px;
height: 150px;
border-radius: 50%;
overflow: hidden;
}
}
.bottomImg {
img {
width: 100px;
height: 100px;
border-radius: 50%;
overflow: hidden;
}
}
}
}
</style>