在專案中,前端開發經常會遇到有圖片上傳的需求,而別人的元件大多都滿足不了當下產品的需求,這是往往我們得去依靠元件自己自定義一個專案通用的裁剪元件
一、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>