【VUE】vue+vue-cropper实现上传剪裁图片
第一次做上传剪裁图片,找了许多框架,最后找到一个优雅的图片裁剪插件vue-cropper,很方便新手入手安装npm install vue-cropper使用import VueCropper from vue-cropperimport axios from 'axios'const host = 'xxx';//预上传export function uploa...
·
一个优雅的图片裁剪插件vue-cropper,很方便新手入手
安装
npm install vue-cropper
使用
import VueCropper from vue-cropper
import axios from 'axios'
const host = 'xxx';
//预上传
export function uploadBefore(md5, size, ext) {
const url = host + "/file/upload/before";
return axios.post(url, {
md5: md5,
size: size,
ext: ext
}).then((res) => {
return Promise.resolve(res)
})
}
//保存文件
export function saveImage(key) {
const url = host + "/file/save";
return axios.put(url, {
key: key
}).then((res) => {
return Promise.resolve(res)
})
}
import * as qiniu from 'qiniu-js'
import browserMD5File from 'browser-md5-file'
import { uploadBefore as preUploadFile, saveImage as saveFile } from 'api/uploadImage'
export function uploadFile(file) {
return new Promise((resolve, reject) => {
function checkError(res) {
if (res.data.code !== 0) {
reject(new Error(res.data.msg))
}
}
// 预上传
new Promise(preResolve => {
// 生成文件 MD5 以便校验服务器上是否存在该文件
browserMD5File(file, function (err, md5) {
// size 转换成 kb
const size = file.size / 1024
const ext = file.name.substr(file.name.lastIndexOf('.') + 1)
preUploadFile(md5, size, ext).then(res => {
checkError(res)
// 当 file_id 存在时表示文件已经上传过,所以进行秒传处理
if (res.data.data.file_id) {
resolve(res.data.data)
} else {
preResolve(res.data.data)
}
})
})
}).then(res => {
let observable = qiniu.upload(file, res.key, res.token)
return new Promise((uploadResolve, uploadReject) => {
observable.subscribe({
next(res) {
},
error(err) {
uploadReject(err)
},
complete(res) {
uploadResolve(res)
}
})
})
}).then(res => {
const key = res.key
return saveFile(key)
}).then(res => {
checkError(res)
resolve(res.data.data)
}).catch(e => {
console.log(e)
this.$message.warning(e.message)
})
})
}
<template>
<div>
<!-- element 上传图片按钮 -->
<el-upload class="uploader"
action
:show-file-list="false"
:on-success="handleUploadSuccess"
:http-request="customUpload">
<img v-if="fileinfo.url"
:src="fileinfo.url"
class="upload">
<i v-else
class="el-icon-plus uploader-icon" />
</el-upload>
......
<!-- vueCropper 剪裁图片实现-->
<div class="vue-cropper-box"
v-if="isShowCropper">
<div class="vue-cropper-content">
<vueCropper 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"></vueCropper>
</div>
<el-button v-if="isShowCropper"
type="danger"
@click="onCubeImg">确定裁剪图片</el-button>
</div>
</div>
</template>
<script>
import VueCropper from "vue-cropper"
import { uploadFile } from './uploadFile'
export default {
components: {
VueCropper
},
data() {
return {
//裁剪组件的基础配置option
option: {
img: '', //裁剪图片的地址
info: true, //裁剪框的大小信息
outputSize: 1, // 裁剪生成图片的质量
outputType: 'jpeg', //裁剪生成图片的格式
canScale: false, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 150, // 默认生成截图框宽度
autoCropHeight: 150, // 默认生成截图框高度
fixed: false, //是否开启截图框宽高固定比例
fixedNumber: [4, 4] //截图框的宽高比例
},
isShowCropper: false, //是否显示截图框
fileUpload: null,
fileinfo: {},
form: {},
}
},
methods: {
//上传按钮上传成功执行事件
handleUploadSuccess(response, file, fileList) {
this.log('Upload response is %o', response)
this.fileinfo = response
this.fileUpload = file;
//上传成功后将图片地址赋值给裁剪框显示图片
this.$nextTick(() => {
this.option.img = file.url;
this.isShowCropper = true
})
},
// 确定裁剪图片
onCubeImg() {
// 获取cropper的截图的base64 数据
this.$refs.cropper.getCropData(data => {
this.fileinfo.url = data
this.isShowCropper = false
//先将显示图片地址清空,防止重复显示
this.option.img = ''
//将剪裁后base64的图片转化为file格式
let file = this.convertBase64UrlToBlob(data)
file.name = this.fileUpload.name
//将剪裁后的图片执行上传
this.uploadFile(file).then(res => {
this.form.content = res.file_id //将上传的文件id赋值给表单from的content
})
})
},
// 将base64的图片转换为file文件
convertBase64UrlToBlob(urlData) {
let bytes = window.atob(urlData.split(',')[1]);//去掉url的头,并转换为byte
//处理异常,将ascii码小于0的转换为大于0
let ab = new ArrayBuffer(bytes.length);
let ia = new Uint8Array(ab);
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], { type: 'image/jpeg' });
},
代码暂时都是从项目中抽出来的,只适合借鉴参考,等有时间再单独将这些功能单独写项目,欢迎大家提供更好用的方法或指出不足之处,一起进步。
更多推荐
已为社区贡献3条内容
所有评论(0)