需求:
用户上传图片不符合大小,提供工具进行裁剪(类似上传头像一样处理)
解决:
- 使用
vue-cropper
插件完成 - 插件官网: https://github.com/xyxiao001/vue-cropper
效果图片:
代码:
-
安装依赖
npm install vue-cropper
-
全局挂载(main.js文件中)
import VueCropper from 'vue-cropper'
Vue.use(VueCropper)
-
组件代码
<template>
<div class="cropper-component">
<!-- 工具箱部分 -->
<div class="text">
当前剪辑尺寸为:{{setWidth}} X {{setHeight}}
</div>
<div class="btn-box">
<div class="scope-btn">
<label class="btn" for="uploads">选择封面</label>
<input type="file" id="uploads" style="position:absolute; clip:rect(0 0 0 0);" accept="image/png, image/jpeg, image/gif, image/jpg" @change="uploadImg($event,'blob', 1)">
<el-button size="mini" type="danger" plain icon="el-icon-zoom-in" @click="changeScale(1)">放大</el-button>
<el-button size="mini" type="danger" plain icon="el-icon-zoom-out" @click="changeScale(-1)">缩小</el-button>
<el-button size="mini" type="danger" plain @click="rotateLeft">↺ 左旋转</el-button>
<el-button size="mini" type="danger" plain @click="rotateRight">↻ 右旋转</el-button>
<el-button size="mini" type="primary" plain icon="el-icon-download" @click="down('blob')" >下载</el-button>
</div>
</div>
<!-- 展示内容部分 -->
<div class="show_box">
<!-- 展示选中图片 -->
<div class="cropper" :style="{width:setWidth /2 +'px',height:setHeight/2 + 'px'}">
<vueCropper
ref="cropper"
:img="option.img"
:outputSize="option.size"
:outputType="option.outputType"
:info="option.info"
:full="option.full"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:autoCrop="option.autoCrop"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
:enlarge="option.enlarge"
:fixedBox="option.fixedBox"
@realTime="realTime"
@imgLoad="imgLoad"
></vueCropper>
</div>
<!-- 展示缩略图 -->
<div class="preview-box" v-if="previews.url">
<div>预览:</div>
<div :style="previews.div" class="preview">
<img :src="previews.url" :style="previews.img"/>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'cropper',
props: {
setWidth:{
type:Number,
default:400
},
setHeight:{
type:Number,
default:400
}
},
data() {
return {
//剪切图片上传
crap: false,
previews: {},
option: {
img: '', // 裁剪图片的地址
info: false, // 裁剪框的大小信息
outputSize: 1, // 剪切后的图片质量(0.1-1)
outputType: 'jpg', // 裁剪生成的图片的格式
canMove: true, // 上传图片是否可以移动
original: false, // 上传图片是否显示原始宽高
canMoveBox: true, // 截图框能否拖动
autoCrop: true, // 是否默认生成截图框
autoCropWidth: this.setWidth / 3,
autoCropHeight: this.setHeight /3,
fixedBox: true, // 截图框固定大小
fixed:false, //是否开启截图框宽高固定比例
enlarge:3,//图片根据截图框输出比例倍数
},
fileName:'', // 本机文件地址
downImg: '#',
imgFile:'',
uploadImgRelaPath:'', // 上传后的图片的地址(不带服务器域名)
}
},
methods: {
// 放大/缩小
changeScale(num) {
num = num || 1;
this.$refs.cropper.changeScale(num);
},
// 坐旋转
rotateLeft() {
this.$refs.cropper.rotateLeft();
},
// 右旋转
rotateRight() {
this.$refs.cropper.rotateRight();
},
// 上传图片(点击上传按钮)
finish(type) {
let formData = new FormData();
// 输出
if (type === 'blob') {
this.$refs.cropper.getCropBlob((data) => {
console.log(data)
let img = window.URL.createObjectURL(data);
formData.append('file', data,'da.jpg');
this.$emit('postFile',formData);
})
} else {
this.$refs.cropper.getCropData((data) => {
formData.append('images', data);
this.$emit('postFile',formData);
})
}
},
// 实时预览函数
realTime(data) {
this.previews = data;
},
// 下载图片
down(type) {
var aLink = document.createElement('a');
let timer = new Date().getTime()
aLink.download = timer;//文件名
if (type === 'blob') {
// 获取截图的blob数据
this.$refs.cropper.getCropBlob((data) => {
this.downImg = window.URL.createObjectURL(data);//生成blob格式图片路径
aLink.href = window.URL.createObjectURL(data);
aLink.click();
})
} else {
// 获取截图的base64 数据
this.$refs.cropper.getCropData((data) => {
this.downImg = data;
aLink.href = data;
})
}
},
// 选择本地图片
uploadImg(e, type, num) {//num代表第几个
// 上传图片
var file = e.target.files[0];
this.fileName = file.name;
if (!/\.(jpg)$/.test(e.target.value)) {
this.$Message.info('证件照图片必须是jpg格式');
return false;
}
let reader = new FileReader();
reader.onload =(e) => {
let data = '';//生成图片地址
if (typeof e.target.result === 'object') {
if(type == 'blob'){
// 把Array Buffer转化为blob 如果是base64不需要
data = window.URL.createObjectURL(new Blob([e.target.result]));
}
}
else {
data = e.target.result;
}
if (num === 1) {
this.option.img = data;
}
}
if(type == 'blob'){
// 转化为blob
reader.readAsArrayBuffer(file);
}else{
// 转化为base64
reader.readAsDataURL(file);
}
},
//图片加载的回调 imgLoad 返回结果success, error
imgLoad (msg) {
// console.log('imgLoad')
// console.log(msg)
},
//刷新-清除截图-目前尚未用到
refeshImg(type){
if(type == 'start'){
this.$refs.cropper.startCrop() //开始截图
}else if(type == 'end'){
this.$refs.cropper.stopCrop() //停止截图
}else if(type == 'clear'){
this.$refs.cropper.clearCrop() //清除截图
}
}
}
}
</script>
<style lang="scss" scoped>
.cropper-component {
width: 80%;
height: 500px;
margin: 0 auto;
position: relative;
//工具箱部分
.btn-box {
margin: 20px 0;
.btn {
outline: none;
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
-webkit-appearance: none;
text-align: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
outline: 0;
-webkit-transition: .1s;
transition: .1s;
font-weight: 500;
padding: 8px 15px;
font-size: 12px;
border-radius: 3px;
color: #fff;
background-color: #409EFF;
border-color: #409EFF;
margin-right: 10px;
}
}
//展示内容部分
.show_box{
display: flex;
// 展示选中图片
// .cropper {
// width: 500px;
// height: 500px;
// }
// 展示缩略图
.preview-box {
margin-left: 500px;
top: 60px;
left: 10px;
.preview {
width: 400px;
height: 400px;
// border-radius: 50%;//这里预览是否需要变成圆的
border: 1px solid #ccc;
background-color: #ccc;
margin: 5px;
overflow: hidden;
}
}
}
}
</style>