1、首先安装vant、axios、cropperjs
npm i vant
npm install axios
npm install cropperjs
2、在main.js中导入并挂载
import Vant from 'vant'
import 'vant/lib/index.css';
createApp(App).use(Vant)
3、app.vue中的内容如下:
<template>
<input type="file" ref="choose_img" name="" id="choose_img" @change="getFileNameToText($event)" hidden="">
<van-cell title="点击编辑头像" @click="openInput">
<template #right-icon>
<span>
<img v-if="myDefaultPath" class="avater" :src="myDefaultPath" alt="">
</span>
</template>
</van-cell>
<van-popup
@opened="openPop"
v-model:show="showBottom"
position="bottom"
:style="{ height: '100%' }"
>
<div class="wrapper" v-if="showBottom">
<img ref="cropImage" id="backgroundImage" :src="image_path" alt="">
</div>
<div class="footer">
<van-button class="cancel" @click="cancelCrop" type="default">取消</van-button>
<van-button class="sure" @click="sureCrop" type="default">确认</van-button>
</div>
</van-popup>
</template>
<script setup>
//导入cropper内容
import 'cropperjs/dist/cropper.css';
import Cropper from 'cropperjs';
import {onMounted, ref} from "vue";
import axios from "axios";
const input_label = ref(null)
const image = ref(null)
const cropImage = ref(null)
const image_path = ref('')
const showBottom = ref(false)
const myDefaultPath = ref('')
const cropper = ref(null)
// const choose_img = ref(null)
// 这个是当弹框动画完成后会自动执行所以这时就有dom了
const openPop = ()=>{
image.value = document.getElementById('backgroundImage');
cropper.value = new Cropper(image.value, {
viewMode: 1,
dragMode: 'move',
aspectRatio: 1, /// //裁剪图片比列
// autoCropArea: 1,
cropBoxMovable: false, /// ///截图区域移动
cropBoxResizable: false, /// //截图区域缩放
background: false/// //默认马赛克背景
})
}
const openInput = () => {
// 给input文本框一个点击事件
input_label.value.click()
}
const getFileNameToText = (e)=>{
// 将本地打开的文件url转变成img标签能够识别的url
image_path.value = window.URL.createObjectURL(input_label.value.files[0])
showBottom.value = true
}
const cancelCrop = ()=>{
// 他的作用是将input的输入的值改变一下
// 如果不改变则下次再次点击同一个文件不会出发change事件
input_label.value.value = ''
// 关闭弹框
showBottom.value = false
}
const sureCrop = ()=>{
cropper.value.getCroppedCanvas().toBlob(blob => {
console.log('blob', blob)
const formData = new FormData();
formData.append('photo', blob)
axios({
url:'http://toutiao.itheima.net/v1_0/user/photo',
method: 'patch',
headers:{
'Authorization': 'Bearer be4168af-bb95-4914-bc98-bdd61fb78e8e'
},
data:formData
}).then(res=>{
myDefaultPath.value=res.data.data.photo
// 作用还是改变一下值
input_label.value.value = ''
// 关闭弹框
showBottom.value = false
})
})
}
onMounted(()=>{
// 只有挂载后才有dom
input_label.value = document.getElementById('choose_img')
})
</script>
<style scoped lang="less">
.avater{
width: 50px;
height: 50px;
border-radius: 25px;
}
#backgroundImage{
display: block;
max-width: 100%;
}
.wrapper{
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: pink;
}
.footer{
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
.cancel, .sure{
width: 100px;
height: 50px;
}
.cancel{
margin-left: 20px;
}
.sure{
margin-right: 20px;
}
}
</style>
4、显示的效果如下: