位置: IT常识 - 正文

在Vue3项目中使用VueCropper裁剪组件(裁剪及预览效果)(vue项目使用rem)

编辑:rootadmin
在Vue3项目中使用VueCropper裁剪组件(裁剪及预览效果) 文章目录前言一、使用步骤1.安装库2.引入库3.在component文件夹中新建一个裁剪Vue文件4.在父组件中使用(HTML)5.定义props传参(TS)6.核心方法(TS)总结前言

推荐整理分享在Vue3项目中使用VueCropper裁剪组件(裁剪及预览效果)(vue项目使用rem),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:vue3项目中使用高德地图,vue3项目中使用高德地图,vue在项目中怎么用的,vue3项目中使用代码编辑工具,vue3项目中使用代码编辑工具,vue3项目中使用vue2组件,vue3项目中使用代码编辑工具,vue3项目中使用el-dialog,内容如对您有帮助,希望把文章链接给更多的朋友!

某次看到后台系统中使用到了裁剪组件,感觉挺好玩的并且最近也在学Vue3和Ts,所以就研究了VueCropper组件,封装了裁剪组件,效果如下图。

一、使用步骤1.安装库在Vue3项目中使用VueCropper裁剪组件(裁剪及预览效果)(vue项目使用rem)

npm i vue-cropper --save

2.引入库

代码如下(示例):

import ‘vue-cropper/dist/index.css’ import { VueCropper } from ‘vue-cropper’

3.在component文件夹中新建一个裁剪Vue文件

TipsDialog是我自己封装的dialog组件,可以替换成el-dialog

<template> <div> <input ref="reuploadInput" type="file" accept="image/*" @change="onChange" id="fileBtn" style="display: none" > <TipsDialog :visible="dialogVisible" :title="'图片裁剪'" :width="'40%'" :custom-class="'upload_dialog'" @close="dialogVisible = false" > // 核心内容 <template #default> <div class="cropper"> // 裁剪左侧内容 <div class="cropper_left"> <vueCropper :tyle="{ width: '400px'}" ref="cropperRef" :img="options.img" :info="true" :info-true="options.infoTrue" :auto-crop="options.autoCrop" :fixed-box="options.fixedBox" :can-move="options.canMoveBox" :can-scale="options.canScale" :fixed-number="fixedNumber" :fixed="options.fixed" :full="options.full" :center-box="options.centerBox" @real-time="previewHandle" /> <div class="reupload_box"> <div class="reupload_text" @click="uploadFile('reload')" > 重新上传 </div> <div> <el-icon class="rotate_right" @click="changeScale(1)" > <CirclePlus /> </el-icon> <el-icon class="rotate_right" @click="changeScale(-1)" > <Remove /> </el-icon> <el-icon class="rotate_right" @click="rotateRight" > <RefreshRight /> </el-icon> </div> </div> </div> <div class="cropper_right"> <div class="preview_text"> 预览 </div> <div :style="getStyle" class="previewImg" > <div :style="previewFileStyle"> <img :style="previews.img" :src="previews.url" alt="" > </div> </div> </div> </div> </template> <template #footer> <span class="dialog-footer"> <el-button @click="dialogVisible = false">取消</el-button> <el-button type="" @click="refreshCrop" >重置</el-button> <el-button type="primary" @click="onConfirm" > 确认 </el-button> </span> </template> </TipsDialog> </div></template><script lang="ts" setup>// 需要引入的库import 'vue-cropper/dist/index.css'import { VueCropper } from 'vue-cropper'import { ref, watch, reactive } from 'vue'import TipsDialog from '~/components/TipsDialog/TipsDialog.vue' // 封装的dialog组件import { ElMessage } from 'element-plus'import { commonApi } from '../../api' // 封装的apiconst dialogVisible = ref<boolean>(false) // dialog的显示与隐藏const emits = defineEmits(['confirm']) // 自定义事件// 裁剪组件需要使用到的参数interface Options { img: string | ArrayBuffer | null // 裁剪图片的地址 info: true // 裁剪框的大小信息 outputSize: number // 裁剪生成图片的质量 [1至0.1] outputType: string // 裁剪生成图片的格式 canScale: boolean // 图片是否允许滚轮缩放 autoCrop: boolean // 是否默认生成截图框 autoCropWidth: number // 默认生成截图框宽度 autoCropHeight: number // 默认生成截图框高度 fixedBox: boolean // 固定截图框大小 不允许改变 fixed: boolean // 是否开启截图框宽高固定比例 fixedNumber: Array<number> // 截图框的宽高比例 需要配合centerBox一起使用才能生效 full: boolean // 是否输出原图比例的截图 canMoveBox: boolean // 截图框能否拖动 original: boolean // 上传图片按照原始比例渲染 centerBox: boolean // 截图框是否被限制在图片里面 infoTrue: boolean // true 为展示真实输出图片宽高 false 展示看到的截图框宽高 accept: string // 上传允许的格式}// 父组件传参propsinterface IProps { type: string // 上传类型, 企业logo / 浏览器logo allowTypeList: string[] // 接收允许上传的图片类型 limitSize: number // 限制大小 fixedNumber: number[] // 截图框的宽高比例 fixedNumberAider?: number[] // 侧边栏收起截图框的宽高比例 previewWidth: number // 预览宽度 title?: string // 裁剪标题}// 预览样式interface IStyle { width: number | string, height: number | string}/* 父组件传参 */const props = withDefaults(defineProps<IProps>(), { type: 'systemLogo', allowTypeList: () => ['jpg', 'png', 'jpeg'], limitSize: 1, fixedNumber: () => [1, 1], fixedNumberAider: () => [1, 1], previewWidth: 228, title: 'LOGO裁剪'})// 裁剪组件需要使用到的参数const options = reactive<Options>({ img: '', // 需要剪裁的图片 autoCrop: true, // 是否默认生成截图框 autoCropWidth: 150, // 默认生成截图框的宽度 autoCropHeight: 150, // 默认生成截图框的长度 fixedBox: false, // 是否固定截图框的大小 不允许改变 info: true, // 裁剪框的大小信息 outputSize: 1, // 裁剪生成图片的质量 [1至0.1] outputType: 'png', // 裁剪生成图片的格式 canScale: true, // 图片是否允许滚轮缩放 fixed: true, // 是否开启截图框宽高固定比例 fixedNumber: [1, 1], // 截图框的宽高比例 需要配合centerBox一起使用才能生效 1比1 full: true, // 是否输出原图比例的截图 canMoveBox: false, // 截图框能否拖动 original: false, // 上传图片按照原始比例渲染 centerBox: true, // 截图框是否被限制在图片里面 infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高 accept: 'image/jpeg,image/jpg,image/png,image/gif,image/x-icon'})const getStyle = ref<IStyle>({ width: '', height: ''})/* 允许上传的类型 */const acceptType = ref<string[]>([])// 裁剪后的预览样式信息const previews: any = ref({})const previewFileStyle = ref({})// 裁剪组件Refconst cropperRef: any = ref({})// input组件Refconst reuploadInput = ref<HTMLElement | null | undefined>()// 回显图片使用的方法const onChange = (e: any) => { const file = e.target.files[0] const URL = window.URL || window.webkitURL // 上传图片前置钩子,用于判断限制类型用 if (beforeUploadEvent(file)) { options.img = URL.createObjectURL(file) dialogVisible.value = true }}/* 上传图片前置拦截函数 */const beforeUploadEvent = (file: File) => { const type = file.name.substring(file.name.lastIndexOf('.') + 1) // 获得图片上传后缀 // 判断是否符合上传类型 const isAllowTye = props.allowTypeList.some(item => { return item === type }) if (!isAllowTye) { ElMessage.error(`仅支持${acceptType.value.join('、')}格式的图片`) return false } return true}/* 重置裁剪组件 */const refreshCrop = () => { // cropperRef裁剪组件自带很多方法,可以打印看看 cropperRef.value.refresh()}/* 右旋转图片 */const rotateRight = () => { cropperRef.value.rotateRight()}/* 放大缩小图片比例 */const changeScale = (num: number) => { const scale = num || 1 cropperRef.value.changeScale(scale)}// 缩放的格式const tempScale = ref<number>(0)// 点击上传const uploadFile = (type: string): void => { /* 打开新的上传文件无需生成新的input元素 */ if (type === 'reupload') { reuploadInput.value?.click() return } let input: HTMLInputElement | null = document.createElement('input') input.type = 'file' input.accept = options.accept input.onchange = onChange input.click() input = null}/* 上传成功方法 */const cropperSuccess = async (dataFile: File) => { const fileFormData = new FormData() fileFormData.append('file', dataFile) // 在接口请求中需要上传file文件格式, 并且该接口需要改header头部为form-data格式 const { code, data } = await commonApi.uploadFile(fileFormData) if (code.value === 200 && data.value) { return data.value } // 之前调用接口的方式 // axios('http://localhost:3001/adminSystem/common/api/upload', { // data: fileFormData, // method: 'POST', // headers: { // 'Content-Type': 'multipart/form-data' // } // }).then(async (result: any) => { // const res = await result // console.log(res, 'res') // }).catch((err: any) => { // console.log(err, 'err') // })} // base64转图片文件const dataURLtoFile = (dataUrl: string, filename: string) => { const arr = dataUrl.split(',') const mime = arr[0].match(/:(.*?);/)[1] const bstr = atob(arr[1]) let len = bstr.length const u8arr = new Uint8Array(len) while (len--) { u8arr[len] = bstr.charCodeAt(len) } return new File([u8arr], filename, { type: mime })}// 上传图片(点击保存按钮)const onConfirm = () => { cropperRef.value.getCropData(async (data: string) => { const dataFile: File = dataURLtoFile(data, 'images.png') const res = await cropperSuccess(dataFile) // 触发自定义事件 emits('confirm', res) return res }) dialogVisible.value = false}// 裁剪之后的数据const previewHandle = (data: any) => { previews.value = data // 预览img图片 tempScale.value = props.previewWidth / data.w previewFileStyle.value = { width: data.w + 'px', height: data.h + 'px', margin: 0, overflow: 'hidden', zoom: tempScale.value, position: 'relative', border: '1px solid #e8e8e8', 'border-radius': '2px' }}watch( () => props, () => { /* 预览样式 */ getStyle.value = { width: props.previewWidth + 'px', // 预览宽度 height: props.previewWidth / props.fixedNumber[0] + 'px' // 预览高度 } // 上传格式tips信息 acceptType.value = [] for (let i = 0; i < props.allowTypeList.length; i++) { acceptType.value.push(props.allowTypeList[i].toUpperCase()) } }, { deep: true })/* 向子组件抛出上传事件 */defineExpose({ uploadFile})</script><style lang="scss" scoped>.cropper { width: 100%; height: 50vh; display: flex; overflow: hidden; .cropper_left { display: flex; flex-direction: column; .reupload_box { display: flex; align-items: center; justify-content: space-between; margin-top: 10px; .reupload_text { color: var(--primary-color); cursor: pointer; } .rotate_right { margin-left: 16px; cursor: pointer; } } } .cropper_right { flex: 1; margin-left: 44px; .preview_text { margin-bottom: 12px; } }}</style>4.在父组件中使用(HTML)// 引入裁剪组件import clipperDialog from '~/components/clipperDialog/clipperDialog.vue'HTML<clipperDialog ref="clipperRef" :type="clipperData.type" :allow-type-list="clipperData.allowTypeList" :limit-size="clipperData.limitSize" :fixed-number="clipperData.fixedNumber" :fixed-number-aider="clipperData.fixedNumberAider" :preview-width="clipperData.previewWidth" @confirm="onConfirm"/>5.定义props传参(TS)JS// 定义interface类型interface IClipper { type: string // 上传类型 allowTypeList: string[] // 接收允许上传的图片类型 limitSize: number // 限制大小 fixedNumber: number[] // 截图框的宽高比例 fixedNumberAider?: number[] // 侧边栏收起截图框的宽高比例 previewWidth: number // 预览宽度 previewWidthAider?: number // 侧边栏收起预览宽度}const clipperData = ref<IClipper>({ type: '', allowTypeList: [], limitSize: 1, fixedNumber: [], previewWidth: 0})6.核心方法(TS)/* 浏览器logo上传 */const browserUpload = (): void => { clipperData.value = { type: 'browserLogo', // 该参数可根据实际要求修改类型 allowTypeList: ['png', 'jpg', 'jpeg', 'peeee'], // 允许上传的图片格式 limitSize: 1, // 限制的大小 fixedNumber: [1, 1], // 截图比例,可根据实际情况进行修改 previewWidth: 100 // 预览宽度 } // 打开裁剪组件 clipperRef.value.uploadFile()}/* 保存logo自定义事件, 实际业务在此编写 */const onConfirm = (val: any): void => { console.log(val, '点击保存按钮后的图片信息')}总结

以上就是我封装的裁剪组件,或许存在一些不足之处,还请大佬们多多指教!

灵感来源:vue项目添加图片裁剪组件

本文链接地址:https://www.jiuchutong.com/zhishi/299465.html 转载请保留说明!

上一篇:JavaScript数组(四):判断数组相等的4种方法

下一篇:CSS盒子模型(css盒子模型怎么做)

  • 宝贝标题这样写才能增加曝光度(宝贝标题一般由哪些词组成)

    宝贝标题这样写才能增加曝光度(宝贝标题一般由哪些词组成)

  • iqoo8pro传奇版后盖材质(iqoo8pro传奇版后盖脏了怎么办)

    iqoo8pro传奇版后盖材质(iqoo8pro传奇版后盖脏了怎么办)

  • 荣耀手机怎么截屏的4种方法(荣耀手机怎么截长图)

    荣耀手机怎么截屏的4种方法(荣耀手机怎么截长图)

  • 腾讯视频原手机号忘了怎么办(腾讯视频原手机号登不上去了怎么办)

    腾讯视频原手机号忘了怎么办(腾讯视频原手机号登不上去了怎么办)

  • 手机怎么截图只截一小块(手机怎么截图只截一小块软件)

    手机怎么截图只截一小块(手机怎么截图只截一小块软件)

  • 手机视频怎么镜像翻转?(手机视频怎么镜像处理)

    手机视频怎么镜像翻转?(手机视频怎么镜像处理)

  • 苹果11有回音怎么办(苹果11手机有回音是怎么回事)

    苹果11有回音怎么办(苹果11手机有回音是怎么回事)

  • 苹果手机换后壳后有啥影响(苹果手机换后壳需要多少钱)

    苹果手机换后壳后有啥影响(苹果手机换后壳需要多少钱)

  • 小米云备份会备份微信记录吗(小米云备份会备份什么)

    小米云备份会备份微信记录吗(小米云备份会备份什么)

  • 华为mate30pro自动关机怎么回事(华为mate30pro自动重启怎么解决)

    华为mate30pro自动关机怎么回事(华为mate30pro自动重启怎么解决)

  • 苹果手机电池老化会出现什么情况(苹果手机电池老化充不进去电怎么办)

    苹果手机电池老化会出现什么情况(苹果手机电池老化充不进去电怎么办)

  • 网易云音乐的积分有什么用(网易云音乐的积极作用)

    网易云音乐的积分有什么用(网易云音乐的积极作用)

  • 荣耀9x有面部解锁吗(荣耀9x面部解锁)

    荣耀9x有面部解锁吗(荣耀9x面部解锁)

  • y5s字体大小在哪设置(y5s字体在哪里调)

    y5s字体大小在哪设置(y5s字体在哪里调)

  • ipad可以换电池吗(ipad mini换电池)

    ipad可以换电池吗(ipad mini换电池)

  • qq电话静音对面会有显示吗(qq电话静音对面知道吗)

    qq电话静音对面会有显示吗(qq电话静音对面知道吗)

  • 苹果11多少级防水(苹果11多少级防摔)

    苹果11多少级防水(苹果11多少级防摔)

  • 怎么自己设计手机壁纸(怎么自己设计手机主题)

    怎么自己设计手机壁纸(怎么自己设计手机主题)

  • 手机缓存数据可以清除吗(手机缓存数据可以删吗)

    手机缓存数据可以清除吗(手机缓存数据可以删吗)

  • 荣耀20怎么清理垃圾(荣耀20怎么清理软件缓存)

    荣耀20怎么清理垃圾(荣耀20怎么清理软件缓存)

  • 小米手环4nfc充电多久(小米手环4NFC充电电压)

    小米手环4nfc充电多久(小米手环4NFC充电电压)

  • 手机hd2什么意思(手机上hd2什么意思)

    手机hd2什么意思(手机上hd2什么意思)

  • 安卓手机怎么设置动态壁纸(安卓手机怎么设置陌生号码打不进来)

    安卓手机怎么设置动态壁纸(安卓手机怎么设置陌生号码打不进来)

  • 微信付款码截图多久失效(微信付款码截图有效期)

    微信付款码截图多久失效(微信付款码截图有效期)

  • 快手直播没有声音怎么设置(快手直播没有声音在哪里可以打开)

    快手直播没有声音怎么设置(快手直播没有声音在哪里可以打开)

  • 火山小视频怎么搜索人(火山小视频怎么注销)

    火山小视频怎么搜索人(火山小视频怎么注销)

  • MAC系统如何连接Windows共享文件?(mac系统如何连接北通手柄)

    MAC系统如何连接Windows共享文件?(mac系统如何连接北通手柄)

  • 蚁群算法详解-解决TSP问题(蚁群算法是什么)

    蚁群算法详解-解决TSP问题(蚁群算法是什么)

  • 非营利组织缴纳社保
  • 设计费用计入产品成本吗
  • 发票没认证可以作废吗?
  • 建筑业出售废旧电脑取的收入如何申报
  • 母公司代子公司付款合法吗
  • 房地产开发临时用电
  • 个人所得税手续费奖励办税人员文件
  • 企业房产税如何申报缴纳
  • 需要预缴增值税
  • 代收车船税是什么意思必须收吗
  • 无偿取得票据的持票人不享有追索权
  • 债券折价摊销属于借款费用吗
  • 汽车保险费里的钱能退吗
  • 运费计入采购成本会计分录
  • 预付账款收不到发票怎么冲账
  • 增值税减免附加税用计提吗
  • 增值税系统技术维护费需要勾选吗
  • 印花税的征收项目
  • iphone微信透明壁纸怎么设置
  • Win11怎么不显示图标
  • win7系统里没有无线网络连接
  • 销售自己2008年1月购入并作为
  • uniapp webgl
  • php命名空间和自由空间
  • 企业向个人租房子需要缴纳什么税
  • vue3技巧
  • phpcms怎么用
  • php微信分享源码
  • 没有销售收入月报怎么填
  • 映射器可以定义参数类型
  • 几种财务自由
  • 附有销售退回条件的商品销售,如果不能对退货
  • 车到4s店后还需办什么手续
  • 固定什么意思
  • 适用5%征收率的范围
  • 财务费用账户属于什么账户
  • 收到提供劳务的收入
  • 保险公司报销修车流程
  • 交易性金融资产公允价值变动怎么算
  • 现金等价物的特征是
  • 转让专利技术使用权是什么收入
  • 业务招待费文件
  • 多计提的税费怎么处理
  • 年底结账会计要怎么做账
  • 进项税和销项税抵扣的会计分录
  • 可交换债券发行方的会计处理
  • 实收资本会变吗?
  • 物流行业会计核算特征有哪些
  • mysql安装过程中报错
  • 让windows server 2003 32位支持8G内存大内存
  • win2003和2003r2
  • ubuntu的命令行快捷键
  • 苹果mac电脑打不开
  • bios如何设置
  • ubuntu linux
  • ubuntu 命令大全
  • linux 命令大全
  • 怎么设置开机启动项?
  • win8打游戏卡吗
  • windows10总是弹出用户账户控制
  • perl中的$1
  • cssimage
  • android layout布局
  • 怎样屏蔽锁屏广告
  • linux共享内存最大值
  • javascript要怎么学
  • pythonandroid开发
  • unity 3d游戏开发(第2版)
  • javascript 类
  • 反编译android动态库
  • 国家税务系统电子税务局电话
  • 企业公示信息怎么查询
  • 四川国家税务局官网
  • 防伪税控维护费普通发票怎么申报
  • 法院执行的房子可以卖吗
  • 国家税务总局公告2017年第21号
  • 税务局登记是什么
  • 税收征管工作的基本目标
  • 建筑类的发票
  • 广东省地税总局领导班子
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设