1. 安装依赖
npm install vue-cropper
2. 引入 可以单页面引入 也可以全局引入
单页面
import VueCropper from 'vue-cropper'
全局 - 在main.js里
import VueCropper from 'vue-cropper'
Vue.use(VueCropper)
3. HTML页面
<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"
:fixedBox="option.fixedBox"
></vueCropper>
4. data
option: {
img: "", // 裁剪图片的地址
info: true, // 裁剪框的大小信息
outputSize: 0.8, // 裁剪生成图片的质量
outputType: "jpeg", // 裁剪生成图片的格式
canScale: false, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 200, // 默认生成截图框宽度
autoCropHeight: 100, // 默认生成截图框高度
fixedBox: false, // 固定截图框大小 不允许改变
fixed: true, // 是否开启截图框宽高固定比例
fixedNumber: [7, 5], // 截图框的宽高比例
full: true, // 是否输出原图比例的截图
canMoveBox: true, // 截图框能否拖动
original: true, // 上传图片按照原始比例渲染
centerBox: false, // 截图框是否被限制在图片里面
infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
},
methods
handleConfirm() {
this.$refs.cropper.getCropBlob((data) => {
// if (data.size > 2097152) {
// this.showMsg("图片大于2M,请进行裁剪或重新选择");
// }
let blob = window.URL.createObjectURL(data);
this.downImg = blob;
var base64;
var img = new Image();
img.src = blob;
var _that = this;
img.onload = function () {
var that = this;
//生成比例
var w = that.width,
h = that.height,
scale = w / h;
h = w / scale;
//生成canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = w;
canvas.height = h;
ctx.drawImage(that, 0, 0, w, h);
// 生成base64
_that.cropperPic = canvas.toDataURL("image/jpeg", 0.8);
let files = _that.transformToFiles(_that.cropperPic, _that.filename);
_that.temporaryCloseCropper = true;
// XMLHttpRequest 请求 --最后决定使用 XMLHttpRequest 来进行上传图片
var xhr = new XMLHttpRequest();
xhr.timeout = 3000;
xhr.ontimeout = function (event) {
console.log("请求超时!");
};
let param = new FormData();
param.append("file", files, _that.filename);
param.append("deadline", 0); // 按照接口需求情况添加
param.append("file_size", 512 * 1024); // 按照接口需求情况添加
xhr.open(
"POST",
"https://xxxxxxxxxxxx"
);
xhr.send(param);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(JSON.parse(xhr.responseText));
let data = JSON.parse(xhr.responseText);
_that.imageUrl = data.url;
console.log(_that.imageUrl);
_that.dialogVisible = false;
} else {
console.log(xhr.statusText);
}
};
// 生成图片
// _that.$refs.upload.$children[0].handleChange({
// target: { files: [files] },
// });
// 未解决 调用上传 但是无法获取返回信息(可能有我什么不知道的方法可以获取接口返回)
// _that.$refs.upload.$children[0].post(files)
};
});
},
全部代码
<template>
<div>
<el-upload
class="avatar-uploader"
action="https://xxxxxxxxxxxx"
:show-file-list="false"
:before-upload="beforeAvatarUpload"
:data="{ deadline: 0, file_size: 512 * 1024 }"
:model="imageUrl"
ref="upload"
accept="image/*"
:limit="1"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
<el-dialog
title="封面裁剪"
ref="dialog"
width="40%"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
>
<div class="cropper-w">
<div class="cropper" :style="{ width: '100%', height: '280px' }">
<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"
:fixedBox="option.fixedBox"
></vueCropper>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="handleConfirm">确认</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
dialogVisible: false,
imageUrl: "",
option: {
img: "", // 裁剪图片的地址
info: true, // 裁剪框的大小信息
outputSize: 0.8, // 裁剪生成图片的质量
outputType: "jpeg", // 裁剪生成图片的格式
canScale: false, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 200, // 默认生成截图框宽度
autoCropHeight: 100, // 默认生成截图框高度
fixedBox: false, // 固定截图框大小 不允许改变
fixed: true, // 是否开启截图框宽高固定比例
fixedNumber: [7, 5], // 截图框的宽高比例
full: true, // 是否输出原图比例的截图
canMoveBox: true, // 截图框能否拖动
original: true, // 上传图片按照原始比例渲染
centerBox: false, // 截图框是否被限制在图片里面
infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
},
};
},
methods: {
beforeAvatarUpload(file) {
this.filename = file.name;
this.openCropper(file);
return false;
},
openCropper(file) {
var _this = this;
console.log(_this);
const isJPG =
file.type === "image/jpeg" ||
file.type === "image/jpg" ||
file.type === "image/png" ||
file.type === "image/PNG" ||
file.type === "image/JPG";
if (!isJPG) {
this.$message.error("上传图片只能为jpg或png格式");
return;
}
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;
_this.dialogVisible = true;
};
// 转化为base64
reader.readAsDataURL(file);
// 转化为blob
// reader.readAsArrayBuffer(file);
},
handleConfirm() {
this.$refs.cropper.getCropBlob((data) => {
// if (data.size > 2097152) {
// this.showMsg("图片大于2M,请进行裁剪或重新选择");
// }
let blob = window.URL.createObjectURL(data);
this.downImg = blob;
var base64;
var img = new Image();
img.src = blob;
var _that = this;
img.onload = function () {
var that = this;
//生成比例
var w = that.width,
h = that.height,
scale = w / h;
h = w / scale;
//生成canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = w;
canvas.height = h;
ctx.drawImage(that, 0, 0, w, h);
// 生成base64
_that.cropperPic = canvas.toDataURL("image/jpeg", 0.8);
let files = _that.transformToFiles(_that.cropperPic, _that.filename);
_that.temporaryCloseCropper = true;
// XMLHttpRequest 请求 --最后决定使用 XMLHttpRequest 来进行上传图片
var xhr = new XMLHttpRequest();
xhr.timeout = 3000;
xhr.ontimeout = function (event) {
console.log("请求超时!");
};
let param = new FormData();
param.append("file", files, _that.filename);
param.append("deadline", 0); // 按照接口需求情况添加
param.append("file_size", 512 * 1024); // 按照接口需求情况添加
xhr.open(
"POST",
"https://xxxxxxxxxxxx"
);
xhr.send(param);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(JSON.parse(xhr.responseText));
let data = JSON.parse(xhr.responseText);
_that.imageUrl = data.url;
console.log(_that.imageUrl);
_that.dialogVisible = false;
} else {
console.log(xhr.statusText);
}
};
// 生成图片
// _that.$refs.upload.$children[0].handleChange({
// target: { files: [files] },
// });
// 使用此方法 需要在 upload 里 action 设置接口地址
// _that.$refs.upload.$children[0].post(files)
};
});
},
// base64转成files
transformToFiles(dataurl, filename) {
var arr = dataurl.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, { type: mime });
},
},
};
</script>
<style lang='scss'>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>