(效果图预览)
一、使用步骤
1、引入库
# npm 安装 npm install vue-cropper # vue2 局部引入 import { VueCropper } from 'vue-cropper' components: { VueCropper }
2、使用
示例中只给出了部分参数配置,可以参考官方文档查看更多参数:
<vueCropper
ref="cropper"
:img="option.img"
:outputSize="option.size"
:outputType="option.outputType"
></vueCropper>
示例中配置的是获取截图的base64数据,所以这里主要介绍将base64格式的图片上传到七牛云的方法。
官方文档——上传base64编码图片到七牛云 (通过javascript方式上传,xhr原生请求)
//上传图片
uploadImg() {
let _this = this;
let pic;
this.$refs.cropper.getCropData( data => { // 获取截图的 base64 数据
pic = data.substring(23); // 是23!!!!! 去掉头部的 “data:image/png;base64,”(包括base64后面的逗号)
var url = "http://upload-z2.qiniup.com/putb64/" + this.fileSize(pic); // upload.qiniup.com 上传域名适用于华东空间。华北空间使用 upload-z1.qiniup.com,华南空间使用 upload-z2.qiniup.com,北美空间使用 upload-na0.qiniup.com。
// axios上传,this.qiniuToken由后端提供
axios.post(url,pic,{
headers: {
'Content-Type': 'application/octet-stream',
'Authorization': "UpToken " + this.qiniuToken
},
signature: 'yes'
}).then(res => {
let imgInfo = {
name: _this.Name,
url: pic, // 截图的base64路径
data: res.data // 上传的截图在七牛云中保存的hash和key值
};
}).catch(err => { })
});
},
// 通过base64编码字符流计算文件流大小
fileSize(str){
var fileSize;
if (str.indexOf('=') > 0) {
var indexOf = str.indexOf('=');
str = str.substring(0, indexOf); //把末尾的'='号去掉
}
fileSize = parseInt(str.length - (str.length / 8) * 2);
return fileSize;
},
axios请求中的url地址前缀需要根据所在地区变更,参考注释或者上面给出的官方文档都可以。
3、完整代码
<template>
<div class="cropper-content">
<div class="cropper-box">
<div class="cropper">
<vue-cropper
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"
:full="option.full"
:fixedBox="option.fixedBox"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:centerBox="option.centerBox"
:height="option.height"
:infoTrue="option.infoTrue"
:maxImgSize="option.maxImgSize"
:enlarge="option.enlarge"
:mode="option.mode"
@realTime="realTime"
@imgLoad="imgLoad">
</vue-cropper>
</div>
<p v-show="resolutionRatio.length > 0" style="font-size: 14px;">图片原始分辨率{
{ resolutionRatio }}</p>
<p v-show="errorMessage.length > 0" style="font-size: 14px;color: #ff4545;">{
{ errorMessage }}</p>
<!--底部操作工具按钮-->
<div class="footer-btn">
<div class="scope-btn">
<el-upload
class="avatar-uploader"
action="upload"
:show-file-list="false"
:before-upload="(file) => beforeAvatarUpload(file)">
<el-button size="mini" type="success" style="height:32px;margin-right:10px;">选择封面</el-button>
</el-upload>
<el-button size="mini" type="danger" plain icon="el-icon-zoom-in" @click="changeScale(1)" :disabled="btnDisabled">放大</el-button>
<el-button size="mini" type="danger" plain icon="el-icon-zoom-out" @click="changeScale(-1)" :disabled="btnDisabled">缩小</el-button>
<el-button size="mini" type="danger" plain @click="rotateLeft" :disabled="btnDisabled"><Icon type="ios-undo-outline" style="font-size:16px;margin: -2px 5px 0 0;"/>左旋转</el-button>
<el-button size="mini" type="danger" plain @click="rotateRight" :disabled="btnDisabled"><Icon type="ios-share-alt-outline" style="font-size:16px;margin: -2px 5px 0 0;"/>右旋转</el-button>
</div>
<div class="upload-btn">
<el-button size="mini" type="success" @click="uploadImg" :disabled="btnDisabled">上传封面 <i class="el-icon-upload"></i></el-button>
</div>
</div>
</div>
<!--右侧预览效果图-->
<div class="show-preview">
<div :style="previews.div" class="preview">
<img :src="previews.url" :style="previews.img">
</div>
</div>
</div>
</template>
<script>
import { VueCropper } from 'vue-cropper'
import { getUploadToken } from '@/api/user';
import axios from 'axios';
export default {
name: "CropperImage",
components: {
VueCropper
},
props: ['Name'],
mounted(){
this.getQiniuToken();
},
data() {
return {
name: this.Name,
qiniuToken:'',
fileName: '',
previews: {},
option: {
img: '', //裁剪图片的地址(url 地址, base64, blob)
outputSize: 1, //裁剪生成图片的质量(可选0.1 - 1)
outputType: 'jpeg', //裁剪生成图片的格式(jpeg || png || webp)
info: true, //图片大小信息
canScale: true, //图片是否允许滚轮缩放
autoCrop: true, //是否默认生成截图框
autoCropWidth: 200, //默认生成截图框宽度(800改200)
autoCropHeight: 150, //默认生成截图框高度(600改150)
fixed: true, //是否开启截图框宽高固定比例
fixedNumber: [4, 3], //截图框的宽高比例
full: false, //false按原比例裁切图片,不失真
fixedBox: false, //固定截图框大小,不允许改变
canMove: true, //上传图片是否可以移动(false改true)
canMoveBox: true, //截图框能否拖动
original: false, //上传图片按照原始比例渲染
centerBox: true, //截图框是否被限制在图片里面
height: true, //是否按照设备的dpr 输出等比例图片
infoTrue: true, //true为展示真实输出图片宽高,false展示看到的截图框宽高(false改true)
maxImgSize: 3000, //限制图片最大宽度和高度
enlarge: 4, //图片根据截图框输出比例倍数(1改4)
// mode: '800px 600px' //图片默认渲染方式
},
resolutionRatio: '', // 图片分辨率
errorMessage: '', // 图片上传过程的错误信息
};
},
methods: {
// 调用接口获取七牛token
getQiniuToken() {
// this.qiniuToken = ...
},
// 图片加载的回调, 返回结果 success, error
imgLoad(msg) {},
//图片缩放
changeScale(num) {
num = num || 1
this.$refs.cropper.changeScale(num)
},
//向左旋转
rotateLeft() {
this.$refs.cropper.rotateLeft()
},
//向右旋转
rotateRight() {
this.$refs.cropper.rotateRight()
},
//实时预览函数
realTime(data) {
this.previews = data
},
// 通过base64编码字符流计算文件流大小
fileSize(str){
var fileSize;
if (str.indexOf('=') > 0) {
var indexOf = str.indexOf('=');
str = str.substring(0, indexOf); //把末尾的'='号去掉
}
fileSize = parseInt(str.length - (str.length / 8) * 2);
return fileSize;
},
// 上传图片之前的钩子
async beforeAvatarUpload(file){
let formatArr = ['png','jpg','jpeg'];
const isPic = ( formatArr.indexOf(file.name.split('.')[1].toLowerCase()) != -1 );
if ( isPic ) {
const isLt2M = file.size / 1024 / 1024 <= 10;
if ( isLt2M ) {
this.resolutionRatio = `${imgPx.width}*${imgPx.height}`;
// 创建blob图片路径,赋值给裁剪cropper的option.img显示,用于图片裁剪
this.option.img = URL.createObjectURL(file);
} else {
setTimeout(()=>{
this.errorMessage = '上传图片大小不能超过 10MB';
},300)
}
} else {
setTimeout(()=>{
this.errorMessage = '只能上传后缀为.jpg、.jpeg、.png的图片噢~';
},300)
}
},
//上传图片
uploadImg() {
let _this = this;
let pic;
this.$refs.cropper.getCropData( data => { // 获取截图的 base64 数据
pic = data.substring(23); // 是23!!!!! 去掉头部的 “data:image/png;base64,”(包括base64后面的逗号)
var url = "http://upload-z2.qiniup.com/putb64/" + this.fileSize(pic);
// 方法1:axios上传
axios.post(url,pic,{
headers: {
'Content-Type': 'application/octet-stream',
'Authorization': "UpToken " + this.qiniuToken
},
signature: 'yes'
}).then(res => {
let imgInfo = {
data: res.data // 上传的截图在七牛云中保存的hash和key值
};
}).catch(err => { })
// 方法2:原生xhr上传
// var xhr = new XMLHttpRequest();
// xhr.open("POST", url, false); // 最后一个参数用false
// xhr.setRequestHeader("Content-Type", "application/octet-stream");
// xhr.setRequestHeader("Authorization", "UpToken " + this.qiniuToken);
// xhr.send(pic);
});
},
},
}
</script>
<style scoped lang="less">
.cropper-content {
display: flex;
display: -webkit-flex;
justify-content: flex-end;
.cropper-box {
flex: 1;
width: 100%;
.cropper {
width: auto;
height: 300px;
}
}
.show-preview {
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
.preview {
overflow: hidden;
border: 1px solid #67c23a;
background: #cccccc;
}
}
}
.footer-btn {
margin-top: 18px;
display: flex;
display: -webkit-flex;
justify-content: flex-end;
.scope-btn {
display: flex;
display: -webkit-flex;
justify-content: space-between;
padding-right: 10px;
}
.upload-btn {
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
}
.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;
-webkit-transition: .1s;
transition: .1s;
font-weight: 500;
padding: 8px 15px;
font-size: 12px;
border-radius: 3px;
color: #fff;
background-color: #409EFF;
border-color: #409EFF;
margin-right: 10px;
}
}
</style>
拓展:img标签展示base64图片
<img src="data:image/png;base64,base64码" alt="" /> // 静态数据
<img :src={`data:image/png;base64,${doctorDis}`} alt="" /> // 动态数据