196 lines
5.2 KiB
Plaintext
196 lines
5.2 KiB
Plaintext
<template>
|
|
<a-modal
|
|
v-model:visible="props.visible"
|
|
title="图片裁剪"
|
|
class="cropper_model_dlg"
|
|
width="500px"
|
|
@ok="submit"
|
|
@cancel="dialogClose"
|
|
>
|
|
<div class="cropper_content">
|
|
<div class="cropper" style="text-align: center">
|
|
<vueCropper
|
|
ref="cropperRef"
|
|
:img="options.img"
|
|
:outputSize="options.outputSize"
|
|
:outputType="options.outputType"
|
|
:info="options.info"
|
|
:canScale="options.canScale"
|
|
:autoCrop="options.autoCrop"
|
|
:autoCropWidth="options.autoCropWidth"
|
|
:autoCropHeight="options.autoCropHeight"
|
|
:fixed="options.fixed"
|
|
:maximgSize="options.maximgSize"
|
|
:fixedBox="options.fixedBox"
|
|
:enlarge="options.enlarge"
|
|
:fixedNumber="options.fixedNumber"
|
|
/>
|
|
</div>
|
|
<div class="cropper_btns">
|
|
<a-button @click="rotateLeft" size="mini" title="左旋转">
|
|
<template #icon><RotateLeftOutlined /></template>
|
|
</a-button>
|
|
<a-button @click="rotateRight" size="mini" title="右旋转">
|
|
<template #icon><RotateRightOutlined /></template>
|
|
</a-button>
|
|
<a-button @click="changeScale(1)" size="mini" title="放大">+</a-button>
|
|
<a-button @click="changeScale(-1)" size="mini" title="缩小">-</a-button>
|
|
</div>
|
|
</div>
|
|
</a-modal>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import VueCropper from 'vue-cropper/src/vue-cropper.vue';
|
|
import { RotateLeftOutlined, RotateRightOutlined } from '@ant-design/icons-vue';
|
|
import { ref, reactive } from 'vue';
|
|
|
|
const props = defineProps({
|
|
visible: {
|
|
type: Boolean,
|
|
required: true,
|
|
default: false,
|
|
},
|
|
cropperSize: {
|
|
type: Object,
|
|
default() {
|
|
return null;
|
|
},
|
|
},
|
|
oImg: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
fileName: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
folder: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
});
|
|
|
|
const dialogClose = () => {
|
|
emit('update:visible', false);
|
|
};
|
|
const options = reactive({
|
|
img: props.oImg, // 裁剪图片的地址
|
|
outputSize: 1, // 裁剪生成图片的质量
|
|
outputType: 'png', // 裁剪生成图片的格式
|
|
info: true, // 裁剪框的大小信息
|
|
canScale: true, // 图片是否允许滚动缩放
|
|
autoCrop: true, // 是否默认生成截图框
|
|
autoCropWidth: props.cropperSize ? props.cropperSize.width : 200, // 默认生成截图框宽度
|
|
autoCropHeight: props.cropperSize ? props.cropperSize.height : 200, // 默认生成截图框高度
|
|
fixed: false, // 是否开启截图框宽高固定比例
|
|
fixedNumber: [1, 1], // 截图框的宽高比例
|
|
full: true, // 是否输出原图比例的截图
|
|
fixedBox: true, // 固定截图框大小 不允许改变
|
|
canMove: true, // 上传图片是否可以移动
|
|
canMoveBox: true, // 截图框能否拖动
|
|
original: true, // 上传图片按照原始比例渲染
|
|
centerBox: false, // 截图框是否被限制在图片里面
|
|
high: false, // 是否按照设备的dpr输出等比例图片
|
|
infoTrue: true, // true为展示真实输出图片宽高false展示看到的截图框宽高
|
|
maximgSize: 100, // 限制图片最大宽度和高度
|
|
enlarge: 1, // 图片根据截图框输出比例倍数
|
|
mode: 'contain', // 图片默认渲染方式(contain, cover, 100px, 100% auto)
|
|
});
|
|
const cropperRef = ref();
|
|
|
|
const addImgLoading = ref(false);
|
|
|
|
// 左旋转
|
|
const rotateLeft = () => {
|
|
cropperRef.value.rotateLeft();
|
|
};
|
|
// 右旋转
|
|
const rotateRight = () => {
|
|
cropperRef.value.rotateRight();
|
|
};
|
|
// 放大缩小
|
|
const changeScale = (num: any) => {
|
|
num = num || 1;
|
|
cropperRef.value.changeScale(num);
|
|
};
|
|
|
|
const emit = defineEmits(['success', 'update:visible']);
|
|
|
|
// base64转图片文件
|
|
const dataURLtoFile = (dataurl: any, filename: any) => {
|
|
let arr = dataurl.split(',');
|
|
let mime = arr[0].match(/:(.*?);/)[1];
|
|
let bstr = atob(arr[1]);
|
|
let len = bstr.length;
|
|
let u8arr = new Uint8Array(len);
|
|
while (len--) {
|
|
u8arr[len] = bstr.charCodeAt(len);
|
|
}
|
|
return new File([u8arr], filename, { type: mime });
|
|
};
|
|
|
|
const submit = () => {
|
|
cropperRef.value.getCropData((fileData) => {
|
|
let file = dataURLtoFile(fileData, props.fileName);
|
|
emit('update:visible', false);
|
|
emit('success', file);
|
|
});
|
|
};
|
|
|
|
// 暴露变量
|
|
defineExpose({});
|
|
</script>
|
|
|
|
<style lang="less">
|
|
.cropper_model_dlg {
|
|
.ant-dialog__body {
|
|
padding: 0px 20px 60px !important;
|
|
}
|
|
|
|
.cropper_content {
|
|
margin: 0 auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
|
|
.add-img {
|
|
opacity: 0;
|
|
position: absolute;
|
|
width: 80px;
|
|
height: 28px;
|
|
top: 0px;
|
|
left: 0px;
|
|
}
|
|
|
|
.cropper {
|
|
width: 400px;
|
|
height: 400px;
|
|
background: yellow;
|
|
}
|
|
|
|
.cropper500 {
|
|
width: 600px;
|
|
height: 600px;
|
|
background: yellow;
|
|
border: 1px solid #e3e3e3;
|
|
}
|
|
|
|
.cropper_right {
|
|
width: 520px;
|
|
text-align: center;
|
|
}
|
|
|
|
.cropper_preview {
|
|
margin: 0 auto;
|
|
display: inline-block;
|
|
border: 1px solid #ddd;
|
|
}
|
|
|
|
.cropper_btns {
|
|
margin-top: 20px;
|
|
}
|
|
}
|
|
</style>
|