Vue3使用vue-cropper截图上传
!!!!!!!已使用另一个截图上传工具,稍后更新博客!!!!!!
使用vue-cropper进行截图上传
先安装
npm i vue-cropper
编写组件
在components中添加imageCropper.vue
代码如下
<template>
<div>
<div>
<img
v-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">
<vueCropper
style="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">
<a
href="javascript:;"
class="btn btn-primary"
style="width: 180px"
@click="selectFile"
>重新选择图片</a
>
<input
type="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, blob
outputSize: 1, // 裁剪生成图片的质量
outputType: "png", // 裁剪生成图片的格式 jpeg, png, webp
info: 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% auto
limitMinSize: [10,10], // 图片默认渲染方式 contain , cover, 100px, 100% auto
maxImgSize: 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>
文件上传和消息提示使用的是我其他封装的组件,见其他博客
本文来自博客园,作者:静坐仰望星空,转载请注明原文链接:https://www.cnblogs.com/itljf/p/18200763