最近在项目中用到上传裁剪,看了一下代码,觉得这插件可可以。梳理了一下代码分享给大家
前端UI组件element-plus
如果你也用到了 ,快速帮你解决了问题,别忘记点赞收藏
1.首先看效果图
- 因为版本
vue-cropper
众多 ,虽然网上有各种写法 为了保证能运行 直接copy代码就能用 - 直接在
package.json
中添加依赖"vue-cropper": "^1.0.9",
然后安装依赖npm install
5 创建一个公用组件
imgcropper.vue
<template>
<el-dialog
v-model="isModel"
title="裁剪图片"
width="1000px"
destroy-on-close
center
draggable
>
<div class="main">
<div class="tip">
<div class="tip-text">上传说明"vue-cropper": "^1.0.9"版本</div>
</div>
<el-row :gutter="20">
<el-col span="14">
<div class="mainbox">
<vue-cropper
ref="cropper"
:img="option.img"
:outputSize="option.outputSize"
:outputType="option.outputType"
:info="option.info"
:canScale="option.canScale"
:autoCrop="option.autoCrop"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
:fixed="option.fixed"
:fixedNumber="option.fixedNumber"
:full="option.full"
:fixedBox="option.fixedBox"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:centerBox="option.centerBox"
:height="option.height"
:infoTrue="option.infoTrue"
:maxImgSize="option.maxImgSize"
:enlarge="option.enlarge"
:mode="option.mode"
@realTime="realTime"
>
</vue-cropper>
<div class="main-btn">
<el-button size="sm" @click="rotateLeft"
>↺ 向左旋转15°</el-button
>
<el-button size="sm" @click="rotateRight"
>↻ 向左旋转15°</el-button
>
<el-button size="sm" @click="changeScale(1)"
><el-icon type="elui-icon-add-circle" color="#fff"></el-icon
>+ 放大</el-button
>
<el-button size="sm" @click="changeScale(-1)" >- 缩小</el-button >
<el-button type="danger" size="sm" @click="changeReset" >重置</el-button >
</div>
</div>
</el-col>
<el-col span="10">
<div class="preview-model">
<div class="preview" style="width: 200px; height: 200px" v-if="previews.url">
<el-image
lazy
style="width: 100px; height: 100px"
:src="previews.url"
:zoom-rate="1.2"
:max-scale="7"
:min-scale="0.2"
:preview-src-list="srcList"
:initial-index="4"
@load="lookImg"
/>
</div>
<div class="upload-btn">
<el-upload v-model="file" :on-change="selectImg">
<el-button type="primary" size="sm">选择图片</el-button>
</el-upload>
<el-button type="success" style="margin-left: 10px;" size="sm" @click="uploadFile">确认上传</el-button>
</div>
</div>
</el-col>
</el-row>
</div>
</el-dialog>
</template>
<script setup>
import { ref, reactive ,watch,defineExpose} from "vue";
import { VueCropper } from "vue-cropper";
import "vue-cropper/dist/index.css";
const isModel = ref(false);
const name = ref();
const file = ref();
const previews = ref({});
const previewImg = ref();
const cropper = ref(null);
const emit = defineEmits([""]);
const option = reactive({
img: "",
name: "",
outputSize: 1, //裁剪生成图片的质量(可选0.1 - 1)
outputType: "png", //裁剪生成图片的格式(jpeg || png || webp)
info: true, //图片大小信息
canScale: true, //图片是否允许滚轮缩放
autoCrop: true, //是否默认生成截图框
autoCropWidth: 200, //默认生成截图框宽度
autoCropHeight: 200, //默认生成截图框高度
fixed: false, //是否开启截图框宽高固定比例
fixedNumber: [1.53, 1], //截图框的宽高比例
full: false, //false按原比例裁切图片,不失真
fixedBox: false, //固定截图框大小,不允许改变
canMove: true, //上传图片是否可以移动
canMoveBox: true, //截图框能否拖动
original: false, //上传图片按照原始比例渲染
centerBox: true, //截图框是否被限制在图片里面
height: false, //是否按照设备的dpr 输出等比例图片
infoTrue: false, //true为展示真实输出图片宽高,false展示看到的截图框宽高
maxImgSize: 3000, //限制图片最大宽度和高度
enlarge: 1, //图片根据截图框输出比例倍数
mode: "100% 100%", //图片默认渲染方式
});
//预览
const srcList = ref([])
//当再次打开时 清空图片
watch(isModel, (val) => {
if (!val) {
previews.value = {};
option.img = ''
srcList.value = []
}
});
//实时预览
const realTime = (data) => {
previews.value = data;
option.autoCropWidth = data.img.width;
option.autoCropHeight = data.img.height;
};
//图片缩放
const changeScale = (num) => {
num = num || 1;
cropper.value.changeScale(num);
};
// 向左旋转
const rotateLeft = () => {
cropper.value.rotate = cropper.value.rotate - 15 / 90;
//直接旋转90度
cropper.value.rotateLeft()
};
//向右旋转
const rotateRight = () => {
cropper.value.rotate = cropper.value.rotate + 15 / 90;
//直接旋转90度
// cropper.value.rotateRight()
};
// 重置
const changeReset = () => {
cropper.value.refresh();
};
//图片预览图片
const lookImg = () => {
cropper.value.getCropBlob((data) => {
file.value = data;
let img = window.URL.createObjectURL(data);
srcList.value.push(img)
});
};
//选择图片
const selectImg = (e) => {
//这里需要注意 每个UI组件 返回的数据格式不一样 需要什么取什么
srcList.value = [];
option.img = URL.createObjectURL(e.raw);
option.name = e.raw.name;
};
/**
* @function 确认上传
*
* */
const uploadFile = () => {
cropper.value.getCropBlob((data) => {
if (data) {
data.fileName = option.name;
}
emit("uploadImgSuccess", data);
});
};
/**
* @function 开启弹窗
* */
const open = () => {
isModel.value = true;
};
/**
* @function 关闭
* */
const close = () => {
isModel.value = false;
};
defineExpose({
open,
close,
});
</script>
<style lang="scss" scoped>
.main {
box-sizing: border-box;
min-height: 450px;
padding: 20px;
.tip {
display: flex;
align-items: center;
margin-bottom: 20px;
.tip-text {
color: red;
}
}
.mainbox {
width: 100%;
height: 300px;
}
.preview-model {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
.preview {
overflow: hidden;
}
.upload-btn {
display: flex;
width: 100%;
justify-content: space-evenly;
margin-top: 20px;
}
}
.main-btn {
display: flex;
justify-content: center;
margin-top: 20px;
}
}
</style>
直接在页面中使用 例如index.vue
index.vue
<template>
<div class='content'>
<el-button type="danger" @click="addimg">上传图片 </el-button>
<img v-if="imgurl" :src="imgurl" alt="" width='200' height="100">
<comCutimgcropper ref="imgref" @uploadImgSuccess="uploadImgSuccess" ></comCutimgcropper>
</div>
</template>
<script setup>
import comCutimgcropper from '../components/imgcropper.vue'
import { ref ,watch} from 'vue'
import {useRoute, useRouter} from 'vue-router'
const router = useRouter();
const imgref = ref(null);
const imgurl = ref("");
const addimg = () => {
imgref.value.open();
}
const uploadImgSuccess = data => {
//调用接口
// uploadImage(data)
//这里为了展示 直接 写死一张图片 关闭弹框
imgurl.value = "https://img2.baidu.com/it/u=3354585195,1512541150&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1700845200&t=636a3f6d0f2d46b6753a203f48801a98"
imgref.value.close()
}
const uploadImage = async data => {
console.log(data)
//这里就是跟后台约定好需要传递什么参数
const params = {
file: data,
fileName: data.fileName,
}
//上传接口
const res = await uploads(params);
if (res && res.code === 200) {
//页面上显示图片 后端返回的图片地址
imgurl.value = res.data.url;
//关闭弹窗
imgref.value.close()
}
}
/**
* axiso 封装一般这么写 都是采用 FormData的形式 注意请求头 headers 'Content-Type': 'multipart/form-data'
*
* export const uploads = params => {
const data = new FormData()
data.append('file', params.file, params.fileName)
return request({
headers: {
'Content-Type': 'multipart/form-data'
},
url: '/,
method: 'post',
data,
})
}
*/
</script>