1.安装
npm install vue-picture-cropper
```js
<template>
<div :disabled="isshow">
<el-upload
class="avatar-uploader"
accept="image/png, image/jpeg"
:show-file-list="false"
:on-change="onChange"
:auto-upload="Boolean(false)"
:http-request="UploadLogo"
>
<img
v-if="imageUrl"
:src="
imageUrl
? imageUrl.indexOf('blob') !== -1
? imageUrl
: `${imageUrl}?x-oss-process=image/resize,w_128/quality,q_80`
: ''
"
class="logo"
/>
<el-icon v-else class="logo-uploader-icon">
<Plus />
</el-icon>
</el-upload>
<el-dialog v-model="addDialogVisible" destroy-on-close>
<template #header="{ close, titleId, titleClass }">
<div class="my-header">
<h4 :id="titleId" :class="titleClass">图片裁切</h4>
<el-button type="" @click="close">
取消
</el-button>
<el-button type="" @click="clear">
清除
</el-button>
<el-button type="" @click="reset">
重置
</el-button>
<el-button type="primary" @click="getResult">
裁切
</el-button>
</div>
</template>
<VuePictureCropper
:boxStyle="{
width: '100%',
height: '100%',
backgroundColor: '#f8f8f8',
margin: 'auto'
}"
:img="cropperImageUrl"
:options="options"
@ready="ready"
/>
</el-dialog>
</div>
</template>
<script setup>
import { upload } from '@/api/upload.js'
import { blobToFile, dataURLtoBlob, base64toFile } from '@/component/cropper/photo.js'
import VuePictureCropper, { cropper } from 'vue-picture-cropper'
import { Picture, Download, Share, UploadFilled, Plus } from '@element-plus/icons-vue'
let { elMessage } = useElement()
let Form = ref('')
let imageUrl = ref('')
const props = defineProps({
groupId: { type: String, default: '' },
imgUrl: { type: String, default: '' },
dataForm: { type: Object, default: () => ({}) },
show: { type: Boolean, default: false },
proportion: { type: Number, default: Number(16 / 9) }
})
const options = computed(() => {
return {
viewMode: 1,
dragMode: 'crop',
aspectRatio:props['proportion']
}
})
console.log()
console.log(options)
const emits = defineEmits(['update:imageUrl'])
const isshow = ref(false)
isshow.value = props['show']
imageUrl.value = props['imgUrl']
Form.value = props['dataForm']
watch(
() => props.show,
(newValue, oldValue) => {
isshow.value = newValue
}
)
watch(
() => props.dataForm,
(newValue, oldValue) => {
Form.value = newValue
}
)
watch(
() => props.imgUrl,
(newValue, oldValue) => {
console.log(newValue)
imageUrl.value = newValue
}
)
const UploadLogo = async (file) => {
if (file.size / 1024 / 1024 > 2) {
elMessage('图片大小不得超过2MB', 'error')
return false
} else {
addDialogVisible.value = true
}
}
const addDialogVisible = ref(false)
const cropperImageUrl = ref('')
const imgQuality = 0.7
const beforeLogoUpload = (rawFile) => {
if (rawFile.size / 1024 / 1024 > 2) {
elMessage('图片大小不得超过2MB', 'error')
return false
} else {
addDialogVisible.value = true
const upload_file = ref({})
const onChange = (uploadFile) => {
upload_file.value = uploadFile
addDialogVisible.value = true
cropperImageUrl.value = URL.createObjectURL(uploadFile.raw)
}
const clear = () => {
if (!cropper) return
cropper.clear()
}
const reset = () => {
if (!cropper) return
cropper.reset()
}
const getResult = async () => {
if (!cropper) return
const base64 = cropper.getDataURL()
const blob = await cropper.getBlob()
if (!blob) return
let formData = new FormData()
if (upload_file) {
formData.append('file', blob)
formData.append('group_id', props['groupId'])
}
try {
let res = await upload(formData)
if (res.code == 20000) {
elMessage('上传成功')
imageUrl.value = URL.createObjectURL(blob)
Form.value = Object.assign(Form.value, { cover_id: res.data.id })
addDialogVisible.value = false
}
} catch (err) {
console.log(err)
}
}
</script>
<style lang="scss" scoped>
.logo {
width: 128px;
height: 128px;
display: block;
object-fit: contain;
}
.logo-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.logo-uploader .el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.logo-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 128px;
height: 128px;
text-align: center;
border: 1px dashed #8c939d;
}
.avatar {
width: 128px;
}
</style>