1.安装引入依赖包
npm i vue-cropper
在组件vueCropper引入依赖包
import {VueCropper} from 'vue-cropper'
2.添加vueCropper.vue组件
<template>
<div>
<div class="cropper-content">
<!-- 剪裁框 -->
<div class="cropper">
<vueCropper ref="cropper" :img="option.img"
:outputSize="option.size"
:outputType="option.outputType"
:info="true" :full="option.full"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:autoCrop="option.autoCrop"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
:fixedBox="option.fixedBox"
@realTime="realTime"
:fixed="option.fixed"
:fixedNumber="fixedNumber"></vueCropper>
</div>
<!-- 预览框 -->
<div class="show-preview"
:style="{'width': '300px', 'height': '300px', 'overflow': 'hidden', 'margin': '0 25px', 'display':'flex', 'align-items' : 'center'}">
<div :style="previews.div" class="preview">
<img :src="previews.url" :style="previews.img">
</div>
</div>
</div>
<div class="footer-btn">
<!-- 缩放旋转按钮 -->
<div class="scope-btn">
<el-button type="primary" icon="el-icon-zoom-in" @click="changeScale(1)"></el-button>
<el-button type="primary" icon="el-icon-zoom-out" @click="changeScale(-1)"></el-button>
<el-button type="primary" @click="rotateLeft">逆时针旋转</el-button>
<el-button type="primary" @click="rotateRight">顺时针旋转</el-button>
</div>
<!-- 确认上传按钮 -->
<div class="upload-btn">
<el-button type="primary" @click="uploadImg('blob')">上传</el-button>
</div>
</div>
</div>
</template>
<script>
import {VueCropper} from 'vue-cropper'
export default {
data() {
return {
previews: {}, // 预览数据
option: {
img: '', // 裁剪图片的地址 (默认:空)
size: 1, // 裁剪生成图片的质量 (默认:1)
full: false, // 是否输出原图比例的截图 选true生成的图片会非常大 (默认:false)
outputType: 'jpg', // 裁剪生成图片的格式 (默认:jpg)
canMove: true, // 上传图片是否可以移动 (默认:true)
original: true, // 上传图片按照原始比例渲染 (默认:false)
canMoveBox: false, // 截图框能否拖动 (默认:true)
autoCrop: true, // 是否默认生成截图框 (默认:false)
autoCropWidth: this.imgW*(256/320), // 默认生成截图框宽度 (默认:80%)
autoCropHeight: this.imgH*(256/320), // 默认生成截图框高度 (默认:80%)
fixedBox: true, // 固定截图框大小 不允许改变 (默认:false)
fixed: false, // 是否开启截图框宽高固定比例 (默认:true)
fixedNumber: [1, 1] // 截图框比例 (默认:[1:1])
},
downImg: '#'
}
},
props: ['imgFile', 'fixedNumber','imgW','imgH'],
methods: {
changeScale(num) {
// 图片缩放
num = num || 1
this.$refs.cropper.changeScale(num)
},
rotateLeft() {
// 向左旋转
this.$refs.cropper.rotateLeft()
},
rotateRight() {
// 向右旋转
this.$refs.cropper.rotateRight()
},
Update() {
// this.file = this.imgFile
this.option.img = this.imgFile.url
},
realTime(data) {
// 实时预览
this.previews = data
},
uploadImg(type) {
// 将剪裁好的图片回传给父组件
event.preventDefault()
let that = this
if (type === 'blob') {
this.$refs.cropper.getCropBlob(data => {
const reader = new FileReader();
reader.readAsDataURL(data);
reader.onload = (e) => {
that.$emit('upload', reader.result)
}
})
} else {
this.$refs.cropper.getCropData(data => {
that.$emit('upload', data)
})
}
}
},
components: {VueCropper}
}
</script>
<style>
.cropper-content {
display: flex;
display: -webkit-flex;
justify-content: flex-end;
-webkit-justify-content: flex-end;
}
.cropper-content .cropper {
width: 350px;
height: 300px;
}
.cropper-content .show-preview {
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
overflow: hidden;
border: 1px solid #cccccc;
background: #cccccc;
margin-left: 40px;
}
.preview {
overflow: hidden;
border: 1px solid #000000;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC");
}
.footer-btn {
margin-top: 30px;
display: flex;
display: -webkit-flex;
justify-content: flex-end;
-webkit-justify-content: flex-end;
}
.footer-btn .scope-btn {
width: 250px;
display: flex;
display: -webkit-flex;
justify-content: space-between;
-webkit-justify-content: space-between;
}
.footer-btn .upload-btn {
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
}
.footer-btn .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;
margin: 0;
-webkit-transition: 0.1s;
transition: 0.1s;
font-weight: 500;
padding: 8px 15px;
font-size: 12px;
border-radius: 3px;
color: #fff;
background-color: #67c23a;
border-color: #67c23a;
}
</style>
3.上传组件
单张上传要在el-upload加上list-type="picture"属性
<el-upload
class="avatar-uploader"
style="width: 150px;height: 150px;"
action="http://upload-z2.qiniup.com/"
:auto-upload="false" :show-file-list="false"
list-type="picture"
:on-change="handleCrop"
:http-request="upload">
<img class="up-img" v-if="groupForm.logoUrl" :src="groupForm.logoUrl">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
updated生命周期加上以下代码
updated () {
if (this.$refs.vueCropper) {
this.$refs.vueCropper.Update()
}
},
4.el-upload的on-change事件函数 handleCrop方法
handleCrop(file, files) {
// 点击弹出剪裁框
this.cropperModel = true
this.file = file
this.upPost.key = file.name
},
5.自定义el-upload上传方法 upload方法
使用原生xhr上传base64格式图片到七牛,this.upPost.key和than.upPost.token分别是上传文件名和七牛token,七牛token是从后端获取的token
upload(data) {
let than = this
//截取base64
data = data.substring(22);
let timestamp = Date.parse(new Date());
let key = timestamp + this.upPost.key
let url = "http://upload-z2.qiniup.com/putb64/" + this.fileSize(data) + '/key/' + this.baseCode64(key);
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
let json = JSON.parse(xhr.responseText)
than.groupForm.logoUrl = '七牛资源路径' + json.key
than.$message.success('上传成功!')
than.cropperModel = false
}
}
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/octet-stream");
xhr.setRequestHeader("Authorization", "UpToken " + than.upPost.token);
xhr.send(data);
},
6.工具方法
//计算文件大小函数
fileSize(str) {
let fileSize;
if (str.indexOf('=') > 0) {
let indexOf = str.indexOf('=');
str = str.substring(0, indexOf); //把末尾的’=‘号去掉
}
fileSize = parseInt(str.length - (str.length / 8) * 2);
return fileSize;
},
//转换base64函数
baseCode64(input){
var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = this._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
_keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
_keyStr.charAt(enc3) + _keyStr.charAt(enc4);
}
return output;
},
//字节转换
_utf8_encode(string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。