!!!!!!!已使用另一个截图上传工具,稍后更新博客!!!!!!
使用vue-cropper进行截图上传
先安装
npm i vue-cropper
编写组件
在components中添加imageCropper.vue
代码如下
<template><div><div><imgv-if="value"class="mb-2"style="max-width: 200px; max-height: 200px":src="value"/></div><input type="hidden" v-model="value" :name="props.name" /><el-button size="large" type="primary" @click="updateImage">上传图片</el-button><el-dialog v-model="dialogVisible" title="上传图片" width="50%" v-loading="loading"><div class="d-flex"><div class="flex-grow-1" style="height: 400px"><vueCropperstyle="width: 100%; height: 100%"ref="cropper"@realTime="realTime":img="option.img":outputSize="option.outputSize":outputType="option.outputType":info="option.info":canScale="option.canScale":autoCrop="option.autoCrop":autoCropWidth="option.autoCropWidth":autoCropHeight="option.autoCropHeight":fixedBox="option.fixedBox":fixed="option.fixed":fixedNumber="option.fixedNumber":canMove="option.canMove":canMoveBox="option.canMoveBox":original="option.original":centerBox="option.centerBox":infoTrue="option.infoTrue":full="option.full":enlarge="option.enlarge":mode="option.mode":maxImgSize="option.maxImgSize":limitMinSize="option.limitMinSize"></vueCropper></div><div style="flex-basis: 250px"><div class="d-flex justify-content-center"><div v-if="option.img" :style="previewStyle" class="mb-4"><div :style="previews.div"><img :src="previews.url" :style="previews.img" /></div></div></div><div class="text-center"><ahref="javascript:;"class="btn btn-primary"style="width: 180px"@click="selectFile">重新选择图片</a><inputtype="file"style="width: 0; height: 0"accept="image/*"ref="ref1"@change="handleFileChange"/></div><div class="text-center mt-4"><el-button type="primary" @click="chengeSize(1)" size="large"><i class="fas fa-search-plus text-white me-1"></i>放大</el-button><el-button type="primary" @click="chengeSize(-1)" size="large"><i class="fas fa-search-minus text-white me-1"></i>缩小</el-button></div><div class="text-center mt-4"><el-button type="primary" @click="rotateLeft()" size="large"><i class="bi bi-arrow-counterclockwise text-white me-1"></i>左转</el-button><el-button type="primary" @click="rotateRight()" size="large"><i class="bi bi-arrow-clockwise text-white me-1"></i>右转</el-button></div><div class="text-center mt-4">截图大小:{{ option.autoCropWidth }}px *{{ option.autoCropHeight }}px</div></div></div><template #footer><span class="dialog-footer"><el-button size="large" @click="dialogVisible = false">取消</el-button><el-button size="large" ref="submitButton" type="primary" @click="getImage">确定选择</el-button></span></template></el-dialog></div>
</template><script setup lang="ts">
import "vue-cropper/dist/index.css";
import { VueCropper } from "vue-cropper";
import { type ComponentInternalInstance, getCurrentInstance, nextTick, onMounted, reactive, ref } from "vue";
import ApiService from "@/core/services/ApiService";
import { computed, defineEmits } from "vue";
import swalMessage from "@/core/helpers/swalMessage";const { proxy } = getCurrentInstance() as ComponentInternalInstance;const props = defineProps(["modelValue","name","success","width","height","fixedBox",
]);const option = ref({img: "", // 裁剪图片的地址 url 地址, base64, bloboutputSize: 1, // 裁剪生成图片的质量outputType: "png", // 裁剪生成图片的格式 jpeg, png, webpinfo: true, // 裁剪框的大小信息canScale: true, // 图片是否允许滚轮缩放autoCrop: true, // 是否默认生成截图框autoCropWidth: 150, // 默认生成截图框宽度autoCropHeight: 150, // 默认生成截图框高度fixedBox: true, // 固定截图框大小 不允许改变// fixedBox: props.fixedBox ?? true, // 固定截图框大小 不允许改变fixed: true, // 是否开启截图框宽高固定比例,这个如果设置为true,截图框会是固定比例缩放的,如果设置为false,则截图框的宽高比例就不固定了fixedNumber: [1, 1], // 截图框的宽高比例 [ 宽度 , 高度 ]canMove: true, // 上传图片是否可以移动canMoveBox: true, // 截图框能否拖动original: false, // 上传图片按照原始比例渲染centerBox: false, // 截图框是否被限制在图片里面infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高full: true, // 是否输出原图比例的截图enlarge: 1, // 图片根据截图框输出比例倍数mode: "contain", // 图片默认渲染方式 contain , cover, 100px, 100% autolimitMinSize: [10,10], // 图片默认渲染方式 contain , cover, 100px, 100% automaxImgSize: 2000, // 图片默认渲染方式 contain , cover, 100px, 100% auto
});
const ref1 = ref<any>([]);
const cropper = ref<any>({});const emit = defineEmits(["update:modelValue", "onSuccess"]);const value = computed({get() {return props.modelValue;},set(value) {emit("update:modelValue", value);},
});const loading=ref(false);
const submitButton = ref<HTMLButtonElement | null>(null);//修改大小
const chengeSize = (num) => {cropper.value.changeScale(num);
};
//向左边旋转90度
const rotateLeft = () => {cropper.value.rotateLeft();
};
//向右边旋转90度
const rotateRight = () => {cropper.value.rotateRight();
};
const selectFile = () => {ref1.value.click();option.value.img = "";
};
const updateImage = () => {let width=(props.width && props.width>0) ? props.width : 150;let height=(props.height && props.height>0) ? props.height : 150;option.value.autoCropWidth=width;option.value.autoCropHeight=height;option.value.fixedNumber=[1,height/width];option.value.limitMinSize=[width,height];dialogVisible.value = true;nextTick(() => {selectFile();});
};
const handleFileChange = (e) => {let file = e.target.files[0];const reader = new FileReader();reader.readAsDataURL(file);reader.onload = () => {option.value.img = reader.result as string;};
};
const getImage = async () => {loading.value = true;await nextTick();await cropper.value.getCropBlob(async (data2) => {data2.name = 'image.png';// console.log(data2);var data = await ApiService.uploadFile(data2);// loading.value=false;if (data.success) {if (import.meta.env.VITE_APP_API_URL != "/") {value.value = import.meta.env.VITE_APP_API_URL + data.url;} else {value.value = data.url;}dialogVisible.value = false;emit("onSuccess");} else {swalMessage.error("上传失败")}});
};
const dialogVisible = ref(false);const show = () => {dialogVisible.value = true;
};
//实时预览
const previewStyle = ref({});
const previews = ref<any>({});const realTime = (data) => {previews.value = data as any;option.value.maxImgSize = option.value.autoCropWidth;option.value.full = option.value.autoCropWidth > previews.value.w;// 固定为 100 宽度previewStyle.value = {overflow: "hidden",margin: "0",zoom: 200 / previews.value.w,};
};
</script>
<style scoped></style>
文件上传和消息提示使用的是我其他封装的组件,见其他博客