项目中上传图片的宽高不统一,导致图片显示的时候出现变形的问题。故而用到了图片裁剪这个组件。
代码仓库
https://github.com/xyxiao001/vue-cropper
实现效果
下载的话用npm
和yarn
都可以,你喜欢就好。
npm i vue-cropper
yarn add vue-cropper
如图,项目可以上传缩略图。
- 点击
上传图片
,添加一张本地图片。- 裁剪框固定长宽且可移动,图片可移动且放大,缩小。
- 点击
确定
,返回裁剪框内容给后台(File格式
),同Element-UI的upload组件上传的文件格式一致。
代码实现
如果兄弟们这个组件用的有点多,可以自行封装一个组件。 日常偷懒(封装组件太麻烦了),没有封装
HTML
里面有很多属性都用不到或者是默认值,都可以删掉。根据项目需求配置。有些样式按照自己的需求写CSS。
<div>
<div style="width: 500px;height: 350px;float: left; margin-bottom: 20px">
<vueCropper ref="cropper"
style="width: 500px;height: 350px"
:img="option.img"
:output-size="option.size"
:output-type="option.outputType"
:info="true"
:full="option.full"
:fixed="option.fixed"
:can-move="option.canMove"
:can-move-box="option.canMoveBox"
:fixed-box="option.fixedBox"
:original="option.original" :auto-crop="option.autoCrop"
:auto-crop-width="option.autoCropWidth"
:auto-crop-height="option.autoCropHeight" :center-box="option.centerBox"
:high="option.high" mode="cover" :max-img-size="option.max"
@img-load="imgLoad"></vueCropper>
</div>
<!-- @crop-moving="cropMoving" @real-time="realTime" @img-load="imgLoad" -->
<label class="label-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)">
</div>
data
里面用到了两个属性。
option
: 裁剪组件的基础配置
isLoadingImg
: 项目可以不上传图片,所以这个属性判断是否上传了图片。
option: {
img: '', // 裁剪的图片
size: 1, // 裁剪出的图片质量
full: false, // 是否输出原始比例的图片
outputType: 'png', // 输出格式
canMove: true, // 底图是否可以移动
fixedBox: true, // 固定截图框大小
// fixedBox: false,
original: false, // 上传图片以原始比例展现
canMoveBox: true, // 截图框是否可以移动
autoCrop: true, // 是否默认生成截图框
// 只有自动截图开启 宽度高度才生效
autoCropWidth: 250, // 截图框默认宽度
autoCropHeight: 250, // 截图框默认高度
centerBox: false,
high: true,
fixed: false, // 截图框宽高是否固定比例
max: 99999 // 图片的最大宽高
},
isLoadingImg: false
method
里面用到了四个方法。
imgLoad
: 这是组件自带的方法,这边这要用来查看是否添加了图片
uploadImg
: 这是上传本地图片的方法,大多都是**在线例子**里面的代码复制粘贴过来。这里面提供图片格式有Blob
和base64
两种格式(我用的是Blob格式,方便转换为File格式)
uploadProjectModel
: 这个方法是确定上传之后的操作。具体还是看项目需求。
upload
: 这个方法同样也是上传的代码。判断是否有file
参数,然后进行上传。
imgLoad(msg) {
msg == 'success' && (this.isLoadingImg = true)
},
uploadImg(e) {
//上传图片
// this.option.img
var file = e.target.files[0]
if(!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
alert('图片类型必须是.gif,jpeg,jpg,png,bmp中的一种')
return false
}
var reader = new FileReader()
reader.onload = (e) => {
let data
if(typeof e.target.result === 'object') {
// 把Array Buffer转化为blob 如果是base64不需要
data = window.URL.createObjectURL(new Blob([e.target.result]))
} else {
data = e.target.result
}
this.option.img = data
}
// 转化为base64
// reader.readAsDataURL(file)
// 转化为blob
reader.readAsArrayBuffer(file)
},
uploadProjectModel() {
// ElementUI自带的哈,这个都不知道可以去跳两米高的悬崖了,看看劫后重生能不能成浴火凤凰。
this.$refs.addVRForm.validate(valid => {
if(valid) {
if(this.isLoadingImg) {
this.$refs.cropper.getCropBlob((data) => {
// 这里是Blob转File,可以在MDNl里面自行查看File的构造函数。第二个参数是文件名称,
// 这里你可以在上传本地图片的方法中获得,我们后台对名字没有要求所以我随便传了一个。
var file = new File([data], '1.png')
this.upload(file)
})
} else {
this.$confirm('还未选择缩略图, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.upload();
}).catch(() => {
this.$message({
type: 'info',
message: '已取消'
});
});
}
}
})
},
upload(file = null) {
var formData = new FormData();
if(file != null) {
formData.append("file", file);
}
formData.append("720vr", JSON.stringify(this.modelItem));
let config = {
headers: {
"Content-Type": "multipart/form-data",
}
};
// 后面写上传代码,具体业务具体操作,咱就不写了
}