效果图
1.安装vue-cropper
pnpm add vue-cropper@next
2.组件内引用
import 'vue-cropper/dist/index.css'//引入圖片裁剪
import { VueCropper } from "vue-cropper";
3.html部分
<van-popup v-model:show="showCropper" overlay-class="dialog" @click-overlay="delCropper">
<div class="button-group">
<van-button type="success" size="mini" @click="getCropBlob">Confirm</van-button>
<van-button type="danger" size="mini" @click="delCropper">Cancel</van-button>
</div>
<VueCropper
ref="cropper"
:img="option.img"
:outputSize="option.outputSize"
:outputType="option.outputType"
:info="option.info"
:full="option.full"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
: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"
:high="option.high"
:mode="option.mode"
>
</VueCropper>
</van-popup>
4.css部分
<style lang="scss" scoped>
:deep(.van-popup) {
width: 80%;
height: 80%;
overflow: hidden;
}
.button-group {
display: flex;
justify-content: space-between;
button {
margin: 10px;
}
}
</style>
5.js部分
const first_name = ref()
const last_name = ref()
const phone = ref()
const email = ref()
const wechat = ref()
const line_id = ref()
const fileList = ref([])
const cropper = ref(null)//截取的dom元素
const file = ref()
const option = ref({//裁剪參數
img: null,
outputSize: 1,
info: false, // 裁剪框的大小信息
outputType: 'jpeg', // 裁剪生成图片的格式
canScale: false, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: '100px', // 默认生成截图框宽度
autoCropHeight: '100px', // 默认生成截图框高度
high: true, // 是否按照设备的dpr 输出等比例图片
fixedBox: false, // 固定截图框大小 不允许改变
fixed: true, // 是否开启截图框宽高固定比例
fixedNumber: [1, 1], // 截图框的宽高比例
full: true, // 是否输出原图比例的截图
canMoveBox: true, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: true, // 截图框是否被限制在图片里面
infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
mode: '100% auto' // 图片默认渲染方式
})
const showCropper = ref(false)
const router = useRouter()
/**
* 選取圖片後
* @param file
* @returns {boolean}
*/
function beforeRead(file) {
option.value.img = URL.createObjectURL(file)
showCropper.value = true
return true
}
/**
* 取消截圖
*/
function delCropper() {
fileList.value = []
showCropper.value = false
}
/**
* 確認截圖
*/
function getCropBlob() {
cropper.value.getCropData(e => {
file.value = e
showCropper.value = false
})
}
/**
* 修改個人信息
* @type {(function(): void)|*}
*/
const onSubmit = useThrottleFn(() => {
if(fileList.value.length === 0) {
let form = {
first_name: first_name.value,
last_name: last_name.value,
phone: phone.value,
email: email.value,
wechat: wechat.value,
line_id: line_id.value
}
updateMeApi(form).then(res => {
if(res.status === 201 || res.status === 200) {
Toast.success('Success');
setTimeout(() => {
router.push('/me')
},2000)
}
})
}else {
let form = {
image: file.value,
first_name: first_name.value,
last_name: last_name.value,
phone: phone.value,
email: email.value,
wechat: wechat.value,
line_id: line_id.value
}
updateMeApi(form).then(res => {
if(res.status === 201 || res.status === 200) {
Toast.success('Success');
setTimeout(() => {
router.push('/me')
},2000)
}
})
}
},1000)
6.表单部分仅供参考
<van-form @submit="onSubmit">
<header>
<h1>Personal</h1>
<h4>Edit</h4>
<van-field name="uploader" class="upload">
<template #input>
<van-uploader :max-count="1" multiple v-model="fileList" :before-read="beforeRead"/>
</template>
</van-field>
</header>
<h3>Information</h3>
<van-cell-group inset>
<van-field
v-model="first_name"
name="名"
placeholder="First Name"
:rules="[{ required: true, message: 'Please fill your first name' }]"
/>
</van-cell-group>
<van-cell-group inset>
<van-field
v-model="last_name"
name="姓"
placeholder="Last Name"
:rules="[{ required: true, message: 'Please fill your last name' }]"
/>
</van-cell-group>
<van-cell-group inset>
<van-field
v-model="phone"
name="手機號"
type="Number"
placeholder="Phone Number such as 886xxxx"
:rules="[{ required: true, message: 'Please fill your phone number' }]"
/>
</van-cell-group>
<van-cell-group inset>
<van-field
v-model="email"
type="email"
name="用户名"
placeholder="E-mail"
/>
</van-cell-group>
<van-cell-group inset>
<van-field
v-model="wechat"
name="用户名"
placeholder="WeChat ID"
/>
</van-cell-group>
<van-cell-group inset>
<van-field
v-model="line_id"
name="用户名"
placeholder="LINE ID"
/>
</van-cell-group>
<div>
<van-button round block type="success" native-type="submit">
Save
</van-button>
</div>
</van-form>