<template>
<div :class="$options.name">
<div class="icon-img">
<img :src="previewsUrl || ''" class="img" v-default="'avatar'" />
</div>
<div class="middle">
<div class="button" @click="showModal">头像编辑</div>
</div>
<div class="bottom">请选择JPG、PNG格式,小于2M的图片</div>
<a-modal
v-model="visible"
:maskClosable="false"
title="头像编辑"
:footer="null"
dialogClass="cut-pic"
>
<i class="close-icon lkrfont icon-dacha" slot="closeIcon"></i>
<div class="content">
<div class="left">
<div class="cropper-content">
<div class="cropper" style="text-align: center">
<component
v-bind:is="cropper"
ref="cropper"
:img="option.img"
:outputSize="option.size"
:outputType="option.outputType"
:info="true"
:full="option.full"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:autoCrop="option.autoCrop"
:fixed="option.fixed"
:fixedNumber="option.fixedNumber"
:centerBox="option.centerBox"
:infoTrue="option.infoTrue"
:fixedBox="option.fixedBox"
@realTime="realTime"
></component>
</div>
</div>
</div>
<div class="right">
<div class="text text1">100px × 100px</div>
<div class="text text2">50px × 50px</div>
<div class="text text3">30px × 30px</div>
<div class="child">
<div class="show-preview1">
<div :style="previews.div" class="preview">
<img :src="previews.url" :style="previews.img" />
</div>
</div>
</div>
<div class="child">
<div class="show-preview2">
<div :style="previews.div" class="preview">
<img :src="previews.url" :style="previews.img" />
</div>
</div>
</div>
<div class="child">
<div class="show-preview3">
<div :style="previews.div" class="preview">
<img :src="previews.url" :style="previews.img" />
</div>
</div>
</div>
</div>
</div>
<label class="btn" for="uploads">{{
option.img ? "重新上传" : "上传图片"
}}</label>
<input
type="file"
id="uploads"
style="position: absolute; clip: rect(0 0 0 0); display: none"
accept="image/png, image/jpeg, image/gif, image/jpg"
ref="image"
@change="selectImg($event)"
/>
<div class="footer">
<div class="cancel" @click="visible = false">取 消</div>
<div class="submit" type="primary" @click="finish" :loading="loading">
确认
</div>
</div>
</a-modal>
</div>
</template>
<script>
import axios from "axios";
import Vue from "vue";
import $utils from "@/plugins/utils";
export default {
name: "HeadEdit",
props: {
initAvatarUrl: {
type: String,
default: "",
},
},
mounted() {
const res = require("vue-cropper");
Vue.component("VueCropper", res.VueCropper);
this.cropper = "vue-cropper";
},
data() {
return {
visible: false,
cropper: "",
previews: {},
previewsUrl: this.initAvatarUrl,
// 裁剪组件的基础配置option
option: {
img: "", // 裁剪图片的地址
info: true, // 裁剪框的大小信息
outputSize: 1, // 裁剪生成图片的质量
outputType: "jpeg", // 裁剪生成图片的格式
canScale: false, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 100, // 默认生成截图框宽度
autoCropHeight: 100, // 默认生成截图框高度
fixedBox: true, // 固定截图框大小 不允许改变
fixed: true, // 是否开启截图框宽高固定比例
fixedNumber: [1, 1], // 截图框的宽高比例
full: true, // 是否输出原图比例的截图
canMoveBox: false, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: false, // 截图框是否被限制在图片里面
infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
},
// 防止重复提交
loading: false,
};
},
methods: {
showModal() {
this.visible = true;
},
//选择图片
selectImg(e) {
let file = e.target.files[0];
this.fileName = file.name;
if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) {
this.$message.error("图片类型要求:jpeg、jpg、png");
return false;
}
let reader = new FileReader();
//读取为base64
reader.readAsDataURL(file);
// 读取操作完成触发
reader.onload = (e) => {
let data;
if (typeof e.target.result === "object") {
// 把Array Buffer转化为blob 如果是base64不需要
data = window.URL.createObjectURL(new Blob([e.target.result])); // 转化为url
} else {
data = e.target.result;
}
// 因为调用了readAsDataURL方法规定将文件读取为base64,所以data为当前选择文件的base64形式
this.option.img = data;
};
},
//实时预览函数
realTime(data) {
this.previews = data;
},
// 点击裁剪,这一步是可以拿到处理后的地址
finish() {
console.log(this.$refs.cropper, ".this.$refs.cropper");
this.$refs.cropper.getCropBlob((data) => {
this.loading = true;
let url = window.URL.createObjectURL(data); // 生成data的URl
this.previewsUrl = url || "";
this.visible = false;
var cookie = $utils.getCookieArray();
var formData = new FormData();
formData.append("file", data, "this.fileName");
formData.append("sign", "sdeweEFr@#$@");
formData.append("t", new Date().getTime() + "");
formData.append("stk", cookie.token);
var configs = {
headers: {
"Content-Type": "multipart/form-data",
},
};
const Axios = axios.create({
baseURL: process.env.UPLOAD_URL,
// baseURL,
timeout: 10000,
});
Axios.post(`/IFUserHeadUploadFile`, formData, configs)
.then((res) => {
if (res.data.code == "0") {
this.$axios
.post(`/UserCenter/IFAppModifyUserInfo`, {
avatar: res.data.data.url,
})
.then((res) => {
this.$emit("getUserInfo");
this.$message.success("头像上传成功");
})
.catch((err) => {
this.$message.error(err.message);
});
}
})
.catch((err) => {
this.$message.error(err.message);
});
});
},
},
};
</script>
<style lang="less" scoped>
.HeadEdit {
padding-top: 70px;
.icon-img {
margin-bottom: 40px;
text-align: center;
.img {
display: inline-block;
width: 168px;
height: 168px;
border-radius: 50%;
}
}
.middle {
text-align: center;
margin-bottom: 19px;
.button {
display: inline-block;
width: 120px;
height: 34px;
background: @heavyDarkColor;
line-height: 34px;
border-radius: 8px;
cursor: pointer;
text-align: center;
font-size: 14px;
font-weight: bold;
color: @defaultColor;
}
}
.bottom {
text-align: center;
height: 24px;
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: @darkColor;
padding-bottom: 61px;
}
}
.cropper-content {
.cropper {
width: auto;
height: 280px;
}
}
.content {
clear: both;
overflow: hidden;
height: 280px;
display: flex;
position: relative;
.left {
width: 280px;
float: left;
}
.child {
text-align: center;
position: absolute;
right: 0;
width: 232px;
height: 232px;
float: right;
font-size: 12px;
line-height: 18px;
color: @darkColor;
.show-preview1 {
flex: 1;
-webkit-flex: 1;
display: flex;
height: 182px;
display: -webkit-flex;
justify-content: center;
position: absolute;
top: -62px;
left: 70px;
.preview {
overflow: hidden;
transform: scale(0.446428);
border-radius: 50%;
background: @defaultColor;
.img {
width: 100px;
height: 100px;
}
}
}
.show-preview2 {
position: absolute;
top: 52px;
left: 70px;
.preview {
transform: scale(0.2232);
border-radius: 50%;
overflow: hidden;
background: @defaultColor;
}
}
.show-preview3 {
position: absolute;
top: 132px;
left: 70px;
.preview {
overflow: hidden;
background: @defaultColor;
border-radius: 50%;
transform: scale(0.1339);
}
}
}
.text {
width: 86px;
height: 14px;
font-size: 12px;
line-height: 14px;
text-align: center;
right: 6px;
color: @darkColor;
position: absolute;
}
.text1 {
top: 108px;
}
.text2 {
top: 196px;
}
.text3 {
top: 264px;
}
}
.btn {
height: 14px;
font-size: 14px;
line-height: 14px;
color: @primaryColor;
margin-top: 12px;
cursor: pointer;
display: block;
}
.footer {
height: 114px;
border-top: none;
padding-top: 40px;
padding-left: 63px;
.cancel {
width: 128px;
height: 34px;
background: @heavyDarkColor;
border-radius: 8px;
cursor: pointer;
line-height: 34px;
font-size: 14px;
text-align: center;
font-weight: bold;
color: @defaultColor;
display: inline-block;
float: left;
}
.cancel:hover {
color: @brightColor;
}
.submit {
width: 128px;
margin-left: 54px;
height: 34px;
background: linear-gradient(90deg, #e5bc7e 0%, #b28c55 100%);
border-radius: 8px;
cursor: pointer;
line-height: 34px;
font-size: 14px;
text-align: center;
font-weight: bold;
color: #2f2c35;
display: inline-block;
float: left;
}
}
</style>
<style>
.cut-pic {
width: 452px !important;
}
.cut-pic * {
box-sizing: border-box;
}
.cut-pic .ant-modal-content {
background: linear-gradient(135deg, #34343a 0%, #201e1e 100%);
box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.2);
border-radius: 8px;
}
.cut-pic .ant-modal-title {
color: #fff;
}
.cut-pic .ant-modal-close {
color: #fff;
margin-top: 20px;
margin-right: -4px;
}
.cut-pic .ant-modal-close:hover {
color: #cfad7a;
}
.cut-pic .ant-modal-header {
height: 88px;
padding: 40px 16px 0;
font-weight: bold;
font-size: 20px;
background: initial;
border-bottom: none;
color: #fff;
box-sizing: border-box;
}
.cut-pic .ant-modal-body {
padding: 0 16px;
}
.cut-pic .cropper-crop-box {
border-radius: 150px;
overflow: hidden;
}
</style>
nuxt实现图片裁剪
最新推荐文章于 2023-12-19 15:42:02 发布