wms-antdvue/.svn/pristine/a8/a8707c954a96786bad39d57620426481a400d417.svn-base
2024-11-07 16:33:03 +08:00

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>