web技术分享| 图片上传与图片裁剪结合 vue3
Posted anyRTC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了web技术分享| 图片上传与图片裁剪结合 vue3相关的知识,希望对你有一定的参考价值。
需求:
-
上传的图片限制长宽相同;
-
只能上传图片;
-
图片大小限制 500k
-
当前项目仅需要上传的图片信息
项目组件使用
裁剪:vue-cropper
import "vue-cropper/dist/index.css";
import VueCropper from "vue-cropper";
上传: Upload 上传(element plus 组件)
实现理论:
- 通过组件 Upload 进行图片上传前校验方法判断是否需要裁剪、是否是图片、是否超过大小限制;
- 裁剪后的图片限制大小;
- 上传的图片信息暴漏出组件;
组件调用
img-url 默认预览的图片
@img-upload 上传所需的最终图片
代码实现
页面
裁剪时弹窗显示
<!-- 上传 -->
<el-upload
class="uploader_cutsom"
action=""
:show-file-list="false"
:accept="imgUpload.imgBmp"
:http-request="updataImg"
:before-upload="beforUpload"
>
<div v-if="imgUpload.imageUrl" class="w-full h-full relative">
<img class="w-full h-full" :src="imgUpload.imageUrl" />
<!-- 删除 -->
<div
@click="clearImg"
class="absolute top-0 right-0 w-8 h-8 rounded flex items-center justify-center bg-black bg-opacity-30 text-white text-base z-20 cursor-pointer"
>
<i class="iconfont icon-shanchu"></i>
</div>
</div>
<div v-else class="uploader_cutsom_default">
<p>从你的计算机中</p>
<p class="uploader_cutsom_default_button">选择文件</p>
</div>
</el-upload>
<!-- 裁剪 -->
<el-dialog
v-model="imgUpload.dialogCropping"
custom-class="dialog_custom"
title="裁剪图片"
append-to-body
:close-on-press-escape="false"
:show-close="false"
:close-on-click-modal="false"
>
<div>
<div class="h-96 w-full">
<vueCropper
ref="cropper"
class="vue_cropper_custom"
:img="imgCropping.imageUrl"
:outputType="imgCropping.outputType"
:autoCrop="imgCropping.autoCrop"
:autoCropWidth="imgCropping.autoCropWidth"
:autoCropHeight="imgCropping.autoCropHeight"
:fixed="imgCropping.fixed"
:fixedNumber="imgCropping.fixedNumber"
:centerBox="imgCropping.centerBox"
:full="imgCropping.full"
></vueCropper>
</div>
</div>
<template #footer>
<el-button v-focus @click="handleCropping($refs.cropper, false)">
取消
</el-button>
<el-button
v-focus
type="primary"
@click="handleCropping($refs.cropper, true)"
>
确定
</el-button>
</template>
</el-dialog>
逻辑
/** 图片地址传递 */
const prop = defineProps(
imgUrl:
type: String,
default: "",
,
);
/** 事件通知 */
const emit = defineEmits(["img-upload"]);
/** 图片上传 */
const imgUpload = reactive(
// 是否展示裁剪
dialogCropping: false,
isCropping: false, // 判断是否已经截图
// 图片
imageUrl: "",
// 图片格式
imgBmp: "image/*",
// 图片名称
imgName: "",
);
// 图片上传前校验
const beforUpload: UploadProps["beforeUpload"] = async (rawFile) =>
// 判断是否需要进行裁剪
imgUpload.isCropping = (await imgSize(rawFile)) as boolean;
// 图片名称
imgUpload.imgName = rawFile.name;
if (imgUpload.isCropping)
if (rawFile.type.indexOf("image/") === -1)
ElMessage.error("请上传正确的图片格式");
return false;
else if (rawFile.size / 1024 / 1024 > 0.5)
ElMessage.error("图片大小不能超过 500k");
return false;
else
// 进入裁剪
imgCropping.imageUrl = URL.createObjectURL(rawFile);
imgUpload.dialogCropping = true;
return false;
;
// 上传
const updataImg = async (data: any) =>
// 如果未截图,打开裁剪
if (imgUpload.isCropping)
// 图片预览
imgUpload.imageUrl = URL.createObjectURL(data.file);
imgUpload.dialogCropping = false;
imgUpload.isCropping = false;
// 图片信息
emit("img-upload", data.file);
;
/** 图片裁剪 */
const imgCropping = reactive(
imageUrl: "",
// 裁剪生成图片的格式
outputType: "png",
// 是否默认生成截图框
autoCrop: true,
// 上传图片按照原始比例渲染
// original: true,
// 是否输出原图比例的截图
full: false,
// 默认生成截图框宽度
autoCropWidth: 160,
// 默认生成截图框高度
autoCropHeight: 160,
// 是否开启截图框宽高固定比例
fixed: true,
// 截图框的宽高比例
fixedNumber: [1, 1],
// 截图框是否被限制在图片里面
centerBox: true,
);
// 生成裁剪图片
const handleCropping = (roleRefs: any, type: boolean) =>
if (type)
roleRefs.getCropBlob((data: any) =>
// 判断裁剪图片大小
if (data.size / 1024 / 1024 > 0.5)
ElMessage.error("裁剪图片大小不能超过 500k");
else
// 图片预览
imgUpload.imageUrl = URL.createObjectURL(data);
imgUpload.dialogCropping = false;
// 图片信息
emit("img-upload", blobToFile(data, imgUpload.imgName));
);
else
imgUpload.imageUrl = "";
imgUpload.dialogCropping = false;
;
// 清除图片
const clearImg = () =>
imgUpload.imageUrl = "";
emit("img-upload");
;
onMounted(() =>
// 图片地址传递
imgUpload.imageUrl = prop.imgUrl;
);
图片相关方法封装
/** 查询图片大小 */
export const imgSize = (file: any) =>
return new Promise((resolve, reject) =>
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () =>
// 让页面中的img标签的src指向读取的路径
let img = new Image();
img.src = reader.result as string;
if (img.complete)
// 如果存在浏览器缓存中
if (img.width / img.height !== 1)
resolve(false);
else
resolve(true);
else
img.onload = () =>
if (img.width / img.height !== 1)
resolve(false);
else
resolve(true);
;
;
);
;
/**
* 文件格式转换
* @description blobToFile
* @param Blob blob
* @param String fileName
*/
export const blobToFile = (blob: any, fileName: string) =>
return new window.File([blob], fileName,
type: blob.type,
);
;
以上是关于web技术分享| 图片上传与图片裁剪结合 vue3的主要内容,如果未能解决你的问题,请参考以下文章
支持移动端裁剪图片插件Jcrop(结合WebUploader上传)
APP开发-使用Vue3+vant+html5+ 实现相机拍照,选取相册图片,裁剪图片以及提取图片中的文字等功能
APP开发-使用Vue3+vant+html5+ 实现相机拍照,选取相册图片,裁剪图片以及提取图片中的文字等功能