1.安裝
npm install vue-cropper
2.在任意地方創(chuàng)建一個(gè)cropper.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"?:centerBox="option.centerBox"?: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>
????????<!--?<vueCropper?ref="cropper"?:img="option.img"?:outputSize="option.size"?:outputType="option.outputType"></vueCropper>?-->
??????</div>
??????<!--?預(yù)覽框?-->
??????<div?class="show-preview"?:style="{'width':?'500px',?'height':?'400px',??'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">
??????<!--?縮放旋轉(zhuǎn)按鈕?-->
??????<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="rotateRight">順時(shí)針旋轉(zhuǎn)</el-button>
????????<el-button?type="primary"?@click="rotateLeft">逆時(shí)針旋轉(zhuǎn)</el-button>
??????</div>
??????<!--?確認(rèn)上傳按鈕?-->
??????<div?class="upload-btn">
????????<!--?<el-button?type="primary"?@click="uploadImg('blob')">上傳</el-button>?-->
????????<el-button?type="primary"?:disabled="isDisabled"?@click="uploadImg('base64')">上傳</el-button>
??????</div>
????</div>
??</div>
</template>
<script>
import?{?VueCropper?}?from?'vue-cropper';
//?console.log(VueCropper);
export?default?{
??data?()?{
????return?{
??????previews:?{},?//?預(yù)覽數(shù)據(jù)
??????option:?{
????????img:?'',?//?裁剪圖片的地址??(默認(rèn):空)
????????outputSize:?1,?//?裁剪生成圖片的質(zhì)量??(默認(rèn):1)
????????full:?false,?//?是否輸出原圖比例的截圖?選true生成的圖片會(huì)非常大??(默認(rèn):false)
????????outputType:?'jpg',?//?裁剪生成圖片的格式??(默認(rèn):jpg)
????????canMove:?true,?//?上傳圖片是否可以移動(dòng)??(默認(rèn):true)
????????original:?false,?//?上傳圖片按照原始比例渲染??(默認(rèn):false)
????????canMoveBox:?true,?//?截圖框能否拖動(dòng)??(默認(rèn):true)
?????????centerBox:?true,?//?截圖框是否被限制在圖片里面
????????autoCrop:?true,?//?是否默認(rèn)生成截圖框??(默認(rèn):false)
????????autoCropWidth:?500,?//?默認(rèn)生成截圖框?qū)挾??(默認(rèn):80%)
????????autoCropHeight:?400,?//?默認(rèn)生成截圖框高度??(默認(rèn):80%)
????????fixedBox:?false,?//?固定截圖框大小?不允許改變??(默認(rèn):false)
????????fixed:?false,?//?是否開啟截圖框?qū)捀吖潭ū壤??(默認(rèn):true)
????????fixedNumber:?[1.5,?1],?//?截圖框比例??(默認(rèn):[1:1])
????????enlarge:?1
??????},
??????isDisabled:?false,
??????downImg:?'#'
????};
??},
??props:?['imgFile',?'fixedNumber','autoCropWH',],
??methods:?{
????changeScale?(num)?{
??????//?圖片縮放
??????num?=?num?||?1;
??????this.$refs.cropper.changeScale(num);
????},
????rotateLeft?()?{
??????//?向左旋轉(zhuǎn)
??????this.$refs.cropper.rotateLeft();
????},
????rotateRight?()?{
??????//?向右旋轉(zhuǎn)
??????this.$refs.cropper.rotateRight();
????},
????Update?()?{
???????this.option.autoCropWidth??=?this.autoCropWH.w???this.autoCropWH.w?:?500
????????this.option.autoCropHeight??=?this.autoCropWH.h???this.autoCropWH.h?:?400
??????this.option.img?=?this.imgFile.url;
????},
????realTime?(data)?{
??????//?實(shí)時(shí)預(yù)覽
??????this.previews?=?data;
????},
????uploadImg?(type)?{
??????//?將剪裁好的圖片回傳給父組件
??????event.preventDefault();
??????this.isDisabled?=?true;
??????let?that?=?this;
??????if?(type?===?'blob')?{
????????this.$refs.cropper.getCropBlob(data?=>?{
??????????that.$emit('upload',?data);
????????});
??????}?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:?500px;
??height:?400px;
}
.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?#cccccc;
??background:?#cccccc;
}
.footer-btn?{
??margin-top:?30px;
??display:?flex;
??display:?-webkit-flex;
??justify-content:?flex-end;
??-webkit-justify-content:?flex-end;
}
.footer-btn?.scope-btn?{
??width:?412px;
??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.結(jié)合elemnt ui 使用組件
<template>
??<div>
???????<el-upload
????????????:action="uploadUrl()"
????????????accept="image/png,image/jpg,image/jpeg"
????????????list-type="picture-card"
????????????:limit='1'
????????????:auto-upload="false"
????????????:on-preview="handlePictureCardPreview"
????????????:http-request="upload"
????????????:on-change="consoleFL"
????????????:file-list="uploadList"
????????????>
????????????<i?class="el-icon-plus"></i>
????????????</el-upload>
????????????<el-dialog?:visible.sync="dialogVisible">
????????????<img?width="100%"?:src="dialogImageUrl"?alt="">
????????????</el-dialog>
????????????<!--?剪裁組件彈窗?-->
????????????<el-dialog?:visible.sync="cropperModel"?width="1100px"?:before-close="beforeClose">
????????????<Cropper?:img-file="upfile"?:autoCropWH='autoCropWH'?ref="vueCropper"?:fixedNumber="fixedNumber"?@upload="upload">
????????????</Cropper>
????????????</el-dialog>
??</div>
</template>
<script>
import?Cropper?from?'../../common/cropper';
import?{?showLoading,?hideLoading,regular,Rodmo}?from?'../../../utils/loading.js'
??export?default?{
????data()?{
??????return?{
????????upfile:?'',?//?當(dāng)前被選擇的圖片文件
????????autoCropWH:{w:89,h:89},//裁剪的寬高
????????uploadList:[],?//圖片顯示列表
????????fixedNumber:?[1.5,?1],//?剪裁框比例設(shè)置
????????dialogImageUrl:?'',?
????????dialogVisible:?false,
????????cropperModel:?false,?//?剪裁組件彈窗開關(guān)
??????}
????},
?????updated?()?{
????????if?(this.$refs.vueCropper)?{
????????this.$refs.vueCropper.Update();
????????}
?????},
????components:?{?//注冊(cè)組件
????????Cropper
????},?
????methods:?{?
????????uploadUrl(){??//上傳路徑
?????????return '這里寫自己的路徑'
???????},
?????????beforeClose?()?{?//關(guān)閉彈窗
????????????this.cropperModel?=?false;
????????????},
???????consoleFL?(file,?fileList)?{//?彈出剪裁框哟楷,將當(dāng)前文件設(shè)置為文件
????????this.cropperModel?=?true;
????????this.upfile?=?file;
????????},
??????async?upload?(data)?{??//?自定義upload事件
????????let?fileimg?=?''
????????fileimg?=?await?this.base64ToFile(data,this.upfile.name)??//將base64圖片轉(zhuǎn)成文件類型
?????????if(fileimg?!=?''){
?????????????let?param?=?new?FormData()?
?????????????let?imgurl?=?window.URL.createObjectURL(fileimg)?//拿到截取的圖片數(shù)據(jù)路徑
??????????param.append('file',fileimg)??//添加FormData對(duì)象
??????????this.imgUpload(param,imgurl);
?????????}
????},
????handlePictureCardPreview(file)?{??//點(diǎn)擊文件列表中已上傳的文件時(shí)
??????????this.dialogImageUrl?=?file.url;
??????????this.dialogVisible?=?true;
????????},
????async?imgUpload(formData,imgurl)?{?//自定義圖片上傳
??????????let?url?=?this.uploadUrl()
????????this.$axios.post(url,formData,{?headers:?{?'Content-Type':?'multipart/form-data'?}?}).then(res?=>?{
????????????setTimeout(function()?{
????????????????hideLoading()
????????????},?200)
????????????if(!res.data.Code)?{
??????????????????let?p?=?{}
??????????????????p.url?=?imgurl?
??????????????????this.uploadList?=?[p]??//將截取的圖片數(shù)據(jù)路徑賦值給顯示數(shù)組
???????????????????this.$refs.vueCropper.isDisabled?=?false;
???????????????????this.$message({?message:?res.data.Msg,?type:?'success'?});?//elemnt?ui成功提示
????????????}?else?{
????????????????this.$alert(res.data.Msg,?'錯(cuò)誤提醒',?{
????????????????????confirmButtonText:?'確定',
????????????????????callback:?action?=>?{
????????????????????????}
????????????????????});
????????????????}
????????????})???
?????????????this.cropperModel?=?false;??//關(guān)掉彈窗
????????},
??base64ToFile(urlData,?fileName)?{?//將base64轉(zhuǎn)換為file
????????let?arr?=?urlData.split(',');
????????let?mime?=?arr[0].match(/:(.*?);/)[1];
????????let?bytes?=?atob(arr[1]);?//?解碼base64
????????let?n?=?bytes.length
????????let?ia?=?new?Uint8Array(n);
????????while?(n--)?{
????????????ia[n]?=?bytes.charCodeAt(n);
????????}
????????return?new?File([ia],?fileName,?{?type:?mime?});
????},
????},?
??}
</script>
<style>
</style>