vue-cropper图片裁剪(vue2与vue3)
在项目中,前端开发经常会遇到有图片上传的需求,而别人的组件大多都满足不了当下产品的需求,这是往往我们得去依靠组件自己自定义一个项目通用的裁剪组件
一、vue-cropper安装依赖:
vue2:
npm install vue-cropper 或 yarn add vue-cropper
vue3:
npm install vue-cropper@next 或 yarn add vue-cropper@next
二、引入相关css文件
import 'vue-cropper/dist/index.css'
vue3才需要引入样式,vue2不需要
注意:这个样式一定记得引啊,我就是忘引入,裁剪框一直弄不出来
三、自定义组件
<!-- 裁剪图片工具--> <template> <view class="upgrade-box"> <szy-common-popup poptitle="裁剪图片" showPopup position="center" @close_popup="close_popup"> <view class="prompt-content"> <view class="inner-box"> <view class="tip">提示:按微信公众号封面图2:35:1或1:1比例选择保留区域后,裁剪上传。</view> <!-- 选择裁剪比例 --> <view class="group-btn"> <view class="item" :class="option.fixedNumber[0] === 2.35 ? 'item active' : 'item'" @click="cropSize(2.35, 1)" >2:35:1</view > <view class="item" :class="option.fixedNumber[0] === 1 ? 'item active' : 'item'" @click="cropSize(1, 1)" >1:1</view > </view> <!-- 裁剪区域 --> <view class="cropper-box" :style="{ width: `${imgObj.width}px`, height: `${imgObj.height}px` }" > <VueCropper ref="cropperRef" :img="option.img" :output-size="option.outputSize" :output-type="option.outputType" :can-scale="option.canScale" :auto-crop="option.autoCrop" :full="option.full == '0'" :auto-crop-width="option.autoCropWidth" :auto-crop-height="option.autoCropHeight" :can-move-box="option.canMoveBox" :can-move="option.canMove" :center-box="option.centerBox" :info="option.info" :fixed-box="option.fixedBox" :fixed="option.fixed" :fixed-number="option.fixedNumber" /> </view> </view> <view class="button-group"> <view class="dialog-button" @click="close_popup"> <text class="dialog-button-text">取消</text> </view> <view class="dialog-button button-confirm" @click="cropperClick"> <text class="dialog-button-text">保存/上传</text> </view> </view> </view> </szy-common-popup> </view> </template> <script lang="ts" setup> import { onMounted, ref } from 'vue'; import { VueCropper } from 'vue-cropper'; import 'vue-cropper/dist/index.css'; // vue3才需要引入样式,vue2不要 const props = defineProps({ coverFile: { type: String, require: '', }, }); // 裁剪组件Ref const cropperRef: any = ref({}); // 裁剪组件需要使用到的参数 interface Options { img: string; outputSize: number; // 裁剪生成图片质量 outputType: string; // 裁剪生成图片格式 canScale: boolean; // 图片是否允许滚轮播放 autoCrop: boolean; // 是否默认生成截图框 false info: boolean; // 是否展示截图框信息 autoCropWidth: number; // 生成截图框的宽度 autoCropHeight: number; // 生成截图框的高度 canMoveBox: boolean; // 截图框是否可以拖动 enlarge: number; fixedBox: boolean; // 固定截图框的大小 fixed: boolean; // 是否开启截图框宽高固定比例 fixedNumber: number[]; // 截图框的宽高比例 默认2.35, 1:1, canMove: boolean; // 上传图片是否可拖动 centerBox: boolean; // 截图框限制在图片里面 accept: string; // 上传允许的格式 infoTrue: boolean; original: boolean; full: boolean | string; } const option = ref<Options>({ img: String(props.coverFile), // 裁剪图片地址 outputSize: 1, // 裁剪生成图片质量 outputType: 'jpeg', // 裁剪生成图片格式 canScale: true, // 图片是否允许滚轮播放 autoCrop: true, // 是否默认生成截图框 false info: true, // 是否展示截图框信息 autoCropWidth: 235, // 生成截图框的宽度 autoCropHeight: 100, // 生成截图框的高度 enlarge: 1, // 采集后放大倍数 full: '0', // 是否开启原尺寸裁剪 0 原尺寸 1当前尺寸 infoTrue: true, original: true, canMoveBox: true, // 截图框是否可以拖动 fixedBox: false, // 固定截图框的大小 fixed: true, // 是否开启截图框宽高固定比例 fixedNumber: [2.35, 1], // 截图框的宽高比例 默认2.35, 1:1, canMove: true, // 上传图片是否可拖动 centerBox: true, // 截图框限制在图片里面 accept: 'image/jpeg,image/jpg,image/png,image/gif,image/x-icon', }); const handleSelectImg = (imgItem: any) => { option.value.img = String(imgItem); }; // 外框大小 const imgObj = ref({ width: 300, height: 200, }); // 修改截图框尺寸,宽,高 const cropSize = (w: number, h: number) => { option.value.fixedNumber = [w, h]; cropperRef.value.refresh(); }; // 裁剪后 const cropperClick = () => { cropperRef.value.getCropData((data: any) => { emit('cropperClick', data); }); }; // const emit = defineEmits(['onClose', 'cropperClick']); const close_popup = () => { emit('onClose'); }; onMounted(() => { handleSelectImg(String(props.coverFile)); }); </script> <style lang="scss" scoped> .upgrade-box { .inner-box { .tip { font-size: 30rpx; text-align: left; } .group-btn { display: flex; align-items: center; justify-content: flex-start; margin: 20rpx 0rpx; .item { flex: 1; display: inline-flex; background: rgba(0, 0, 0, 0.03); border-radius: 6rpx 6rpx 0 0; text-align: center; justify-content: center; align-items: center; padding: 0 30rpx; height: 80rpx; white-space: nowrap; font-size: 34rpx; cursor: pointer; color: #353535; position: relative; &:after { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 1rpx; background: #eee; height: 100%; display: block; } &:first-child { border-radius: 6rpx 0 0 6rpx; &:after { display: none; } } &.active { background: $uni-main-color; color: #fff; border-radius: 6rpx; } } } .cropper-box { background: #eee; overflow: hidden; } } } </style>
四、展示样式
蓦然、回首,那人就在灯火阑珊处
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南