一. 先看效果演示
二. 图片上传
用的el-upload加el-image组件
html部分
<el-dialog>
...//无关代码已省略
<div v-for="item in imgArr" :key="item.index">
<span>{{ item.name }}</span>
<el-upload action="#" list-type="picture-card" :on-change="onChange.bind(null, item.index)" :auto-upload="false" :file-list="item.fileList" :class="{ hide: item.hideUpload }">
<i slot="default" class="el-icon-plus"></i>
<div slot="file" slot-scope="{ file }">
<el-image class="el-upload-list__item-thumbnail" :src="item.aimgSrc" alt="" :onerror="defaultImg" :preview-src-list="item.fileList"></el-image>
<span class="el-upload-list__item-actions">
// 预览按钮
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<i class="el-icon-zoom-in"></i>
</span>
// 删除按钮
<span class="el-upload-list__item-delete" @click="handleRemove(file, item.index)">
<i class="el-icon-delete"></i>
</span>
// 裁剪按钮
<span v-if="item.index == 6" class="el-upload-list__item-delete" @click="beforeCrop(file)">
<i class="el-icon-scissors"></i>
</span>
</span>
</div>
</el-upload>
</div>
</el-dialog>
....
注释:
el-upload
:on-change=“onChange.bind(null, item.index)” 不加.bind会报错,
:auto-upload=“false” 表示不自动上传,也就是手动上传
:file-list=“item.fileList” 上传的图片列表,数组对象格式[{url:xxxx}]
:class=“{ hide: item.hideUpload }” 到el-image使用,上传完后影藏那个加号和虚线框
el-image
:οnerrοr=“defaultImg” 图片加载失败,报错时候的默认图片.
:preview-src-list=“item.fileList” 预览的图片列表,同:file-list=“item.fileList”
预览,删除,裁剪,三个按钮,目前功能与预览无关,预览功能有空再另写吧
js部分
imgArr: [
// aimgFile调接口, aimgSrc回显, hideUpload影藏加号, fileList预览大图
{ index: 0, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
{ index: 1, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
{ index: 2, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
{ index: 3, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
{ index: 4, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
{ index: 5, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
{ index: 6, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
],
files :'', //裁剪图片的标记
// 上传图片 index 图片下标 file图片内容 flag裁剪图片的标记
onChange(index, file, flag) {
this.files = file.raw
const isJPG = file.raw.type === 'image/jpeg' || file.raw.type == 'image/png'
const isLt2M = file.raw.size / 1024 / 1024 < 2
if (!isJPG) {
this.$message.error('上传图片只能是 JPG 或 PNG 格式!')
this.handleRemove(file.raw, index)
return
}
if (!isLt2M) {
this.$message.error('上传图片大小不能超过 2MB!')
this.handleRemove(file.raw, index)
return
}
// 上传图片
const fileData = new FormData()
fileData.append('imgFile', file.raw)
fileData.append('imgType', 1)
// 调接口
doctorAccessoryUpload(fileData).then((res) => {
if (res) {
this.imgArr[index].hideUpload = true
this.imgArr[index].aimgSrc = file.url
this.imgArr[index].aimgFile = res.result
// 裁剪后上传
if (flag === 1) this.imgArr[index].fileList = [{ url: file.url }]
} else {
this.handleRemove(file.raw, index)
}
})
},
// 删除上传图片
handleRemove(file, index) {
this.imgArr[index].aimgSrc = ''
this.imgArr[index].aimgFile = ''
this.imgArr[index].fileList = []
this.imgArr[index].hideUpload = false
},
三. 裁剪图片
下载vueCropper插件
npm i vue-cropper --save // 我的版本是^0.6.4
另起一个dialog
<!-- 图片裁剪 -->
<el-dialog title="图片裁剪" :visible.sync="cropDialog" width="40%" :modal="true" :close-on-click-modal="false" center @close="cropCancles" v-dialogDrag>
<div class="cropBox">
<template>
<div>
<vueCropper
@mouseenter.native="enter"
@mouseleave.native="leave"
ref="cropper"
:img="option.uploadImg"
:outputSize="option.size"
:outputType="option.outputType"
:info="true"
:full="option.full"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:autoCrop="option.autoCrop"
:fixed="option.fixed"
:fixedNumber="option.fixedNumber"
:centerBox="option.centerBox"
:infoTrue="option.infoTrue"
:fixedBox="option.fixedBox"
></vueCropper>
</div>
</template>
<div>
<img :src="cropImg" alt="" />
</div>
</div>
<div slot="footer">
<el-button @click="cropCancles">取 消</el-button>
<el-button type="primary" @click="cropConfirm">裁剪图片</el-button>
</div>
</el-dialog>
<script>
import { VueCropper } from 'vue-cropper'
export default {
components: { VueCropper },
data() {
return {
cropDialog: false,
option: {
uploadImg: '', // 原图地址
info: true, // 裁剪框的大小信息
outputSize: 1, // 裁剪生成图片的质量
outputType: 'jpeg', // 裁剪生成图片的格式
canScale: true, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
fixedBox: true, // 固定截图框大小 不允许改变
fixed: true, // 是否开启截图框宽高固定比例
fixedNumber: [3, 4], // 截图框的宽高比例
full: false, // 是否输出原图比例的截图
canMove: true, //是否可以移动原图
canMoveBox: true, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: true, // 截图框是否被限制在图片里面
infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
},
cropImg: require('../../public/img/default.png'),
}
}
//开始裁剪
enter() {
if (this.option.uploadImg == '') {
return
}
this.$refs.cropper.startCrop()
},
//停止裁剪
leave() {
this.$refs.cropper.stopCrop()
this.$refs.cropper.getCropData((data) => {
this.cropImg = data
})
},
// 裁剪前
beforeCrop(file) {
this.option.uploadImg = file.url
this.cropDialog = true
setTimeout(() => {
this.$refs.cropper.getCropData((data) => {
this.cropImg = data
})
}, 500)
},
// 确认裁剪
cropConfirm() {
//获取截图的base64格式数据
this.$refs.cropper.getCropData((data) => {
this.cropImg = data
this.handleRemove(this.files, this.imgArr.length - 1)
this.cropCancles()
setTimeout(() => {
this.onChange(this.imgArr.length - 1, { raw: this.dataURLtoFile(data, 'Default.jpg'), url: data }, 1)
}, 1000)
})
},
// 取消裁剪
cropCancles() {
this.cropDialog = false
this.option.uploadImg = ''
this.cropImg = require('../../public/img/default.png')
},
// base64转file
dataURLtoFile(dataurl, filename) {
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, { type: mime })
},
}
</script>
ok 结束了,记录一下