效果图:
实现步骤:
1,项目中添加vue-cropper插件 :npm install vue-cropper --save 或者 yarn add vue-cropper --save
2,在main.js中引入一下:
import VueCropper from 'vue-cropper'
Vue.use(VueCropper)
3,.vue文件内容:
<template>
<div style="width:1200px;margin:12px auto 0 auto;display:flex;justify-content:space-between;">
<!-- 头像区域 -->
<a-card style="width:260px;">
<!-- 头像 -->
<a-avatar :size="80" :src="src2"
style="margin:0 auto;display:flex;" @click="myPortrait"/>
<!-- <a-avatar :size="80" :src="avatar()?avatar():src"
style="margin:0 auto;display:flex;" @click="myPortrait"/> -->
<!-- 修改密码按钮 -->
<a-row>
<a-col :span="24"
style="font-size:12px;color:#767885;display:flex;justify-content:center;">
<a-button @click="alertPassword">修改密码</a-button>
</a-col>
</a-row>
</a-card>
<!-- 修改头像弹窗 -->
<a-modal title="修改头像" v-model="visible2" :footer="null"
:bodyStyle="{padding:0}" @cancel="resetForm">
<a-row style="padding:24px 24px 16px 24px;margin:0;">
<a-col :span="16">
<div class="cropper">
<vueCropper
ref="cropper"
:img="option.img"
:outputSize="option.size"
:outputType="option.outputType"
:info="option.info"
:full="option.full"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:autoCrop="option.autoCrop"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
:fixedBox="option.fixedBox"
@realTime="realTime"
></vueCropper>
</div>
</a-col>
<a-col :span="8" style="text-align: center;">
<div class="preview">
<!-- <div :style="previews.div" class="preview"> -->
<img :src="previews.url" :style="previews.img" />
</div>
<div style="text-align:center;">头像预览</div>
</a-col>
</a-row>
<a-row style="padding:0 0 8px 24px;margin:0;">
<a-col :span="24">
<label class="btn" for="uploads" style="color:#3264D5;">上传头像</label>
<input
type="file"
id="uploads"
:value="imgFile"
style="position:absolute; clip:rect(0 0 0 0);width: 1px;"
accept="image/png, image/jpeg, image/gif, image/jpg"
@change="uploadImg($event, 1)"
/>
</a-col>
</a-row>
<a-row>
<a-col
:span="24"
style="display:flex;justify-content:center;border-top:1px solid #e8e8e8;padding:14px 0;"
>
<a-button type="primary" @click="submitForm" style="background:#3264D5;">确定</a-button>
<a-button style="margin-left: 10px" @click="resetForm">取消</a-button>
</a-col>
</a-row>
</a-modal>
</div>
</template>
<script>
import { baseUrl } from '@/api/manage'
import { uploadImage } from '@/api/api' // 引入接口
export default {
data() {
return {
src2:'',
src: '../../assets/tx.png', // 头像默认地址
visible: false, // 修改密码弹窗是否显示的标志
labelCol: { span: 4 },
wrapperCol: { span: 14 },
visible2: false,
//剪切图片上传
previews: {},
option: {
img: "", // 裁剪图片的地址
outputSize: 1, // 裁剪生成图片的质量
outputType: "png", // 裁剪生成图片的格式
info: true, // 裁剪框的大小信息
canScale: false, // 图片是否允许滚轮缩放
// autoCrop: false, // 是否默认生成截图框
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 120, // 默认生成截图框宽度
autoCropHeight: 120, // 默认生成截图框高度
fixedBox: true, // 固定截图框大小 不允许改变
fixed: true, // 是否开启截图框宽高固定比例
fixedNumber: [1, 1], // 截图框的宽高比例
canMove: true, // 上传图片是否可以移动
canMoveBox: true, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: true, // 截图框是否被限制在图片里面
infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
full: false, // 是否输出原图比例的截图
enlarge: 0.5, // 图片根据截图框输出比例倍数
mode: "contain" // 图片默认渲染方式
},
fileName: "", // 本机文件地址
downImg: "#",
imgFile: "",
}
},
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
created() {
},
computed: {},
methods: {
// 点击我的头像触发
myPortrait(){
this.visible2 = true;
},
// 点击修改头像弹窗的确定按钮触发
submitForm() {
this.$refs.cropper.getCropData((data) => {
// 拿到的data 其实是base64格式的图片
var blob = this.dataURItoBlob(data); // 调用方法将base64格式的转为二进制大对象格式
var fd = new FormData();
fd.append("file", blob);
fd.append("ossModuleCode","image")
// 该接口用于上传图片;后台要求的是 formData 格式的,所以将blob放入FormData;下面的接口根据自己需要进行更改
uploadImage(fd).then(res=>{
// 接口返回的res.data.imgUrl 是一个图片的链接,以 .blob格式结尾的;放入img标签的src可以显示图片
this.src2 = res.data.imgUrl
})
})
},
// 该方法将base64格式的图片转换为blob格式;blob:二进制大对象
dataURItoBlob(base64Data) {
var byteString;
if (base64Data.split(',')[0].indexOf('base64') >= 0){
byteString = atob(base64Data.split(',')[1]);
}else{
byteString = unescape(base64Data.split(',')[1]);
}
var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
},
// 点击修改头像弹窗的取消按钮触发
resetForm() {
this.visible2 = false;
setTimeout(()=>{
this.option.img = '';
},500)
},
// 实时预览函数
realTime(data) {
this.previews = data;
},
// 选择本地图片
uploadImg(e, num) {
var _this = this;
// 上传图片
var file = e.target.files[0];
_this.fileName = file.name;
if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
//改提示使用了ant-design-vue中的提示框,项目中需要引入ant-design-vue,不想使用该提示可以注释,使用alert()
this.$message.warning("图片类型必须是.gif,jpeg,jpg,png,bmp中的一种")
return false;
}
var reader = new FileReader();
reader.onload = e => {
let data;
if (typeof e.target.result === "object") {
// 把Array Buffer转化为blob 如果是base64不需要
data = window.URL.createObjectURL(new Blob([e.target.result]));
} else {
data = e.target.result;
}
if (num === 1) {
_this.option.img = data;
} else if (num === 2) {
_this.example2.img = data;
}
};
// 转化为base64
// reader.readAsDataURL(file)
// 转化为blob
reader.readAsArrayBuffer(file);
},
}
}
</script>
<style lang="scss" scoped>
.col-3 { color: #767885; font-size: 14px; text-align: right; }
.col-6 { color: #3c3d43; font-size: 14px; padding-left: 24px; font-weight: 500; }
.password { text-align: right; }
.password2 { padding-left: 16px; }
.ant-row { margin: 16px 0; }
.cropper { width: 100%; height: 300px; }
.preview { width: 120px; height: 120px; border-radius: 50%;
border: 1px solid #ccc; background-color: #ccc; margin: 5px; overflow: hidden;
display: inline-block; }
</style>