vue-cropperjs 外掛的元件化使用
阿新 • • 發佈:2021-07-05
vue-cropperjs 外掛的元件化使用
安裝
npm install --save vue-cropperjs 或者 cnpm install --save vue-cropperjs
區域性引入
import VueCropper from 'vue-cropperjs'
export default {
components: { VueCropper },
元件內容
<div> <div class="crop-demo"> <div class="crop-demo-btn" v-show="false"> 點選更換圖片 <input class="crop-input" type="file" name="image" accept="image/*" @change="setImage" id="change" /> </div> </div> <el-dialog :append-to-body="true" title="圖片剪裁" :visible.sync="dialogVisible" :close-on-click-modal="false" width="40%"> <vue-cropper :aspect-ratio="cropperAspectWH" ref="cropper" :src="imgSrc" :ready="cropImage" :zoom="cropImage" :cropmove="cropImage" style="width: 100%; height: 300px"></vue-cropper> <span slot="footer" class="dialog-footer"> <el-button @click="cancelCrop">取 消</el-button> <el-button type="primary" @click="upladPic">確 定</el-button> </span> </el-dialog> <div v-show="false">{{ thisAspectWH }}</div> </div> </template>
<script> import VueCropper from 'vue-cropperjs' export default { components: { VueCropper }, props: ['label', 'AspectWH'],//label 是父元件傳的識別符號 (用於一個頁面內多處使用裁剪元件,裁剪結果返回值錯亂) AspectWH 是用於限定裁剪框的比例的1為1:1 可傳null則是不限制(注意傳值是否為字串) data() { return { //以下都是截圖外掛的 imgSrc: '', dialogVisible: false, img_size: '', max_fuyuan_defaultSrc: [], cropperAspectWH: 1, //圖片剪裁寬高比例 reader: '', e_photo_file: '', e_photo_filefile: '', http_cropImg: '', //帶http cropImg: '', //預設圖片不帶http } }, methods: { //監聽父元件是否點選上傳的事件 childAction() { $('#change').click() }, //向父元件傳送資料 cropImg 裁剪得到的圖片名稱 http_cropImg 帶域名的圖片名稱 label就是傳進來的識別符號,也帶著傳出去 sendMsg() { this.$emit('getPicNamefile', this.cropImg, this.http_cropImg, this.label) }, /******************************圖片剪下開始****************************************/ setImage(e) { let that = this this.e_photo_file = e let file = e.target.files[0] this.e_photo_filefile = file if (!file.type.includes('image/')) { return } this.reader = '' let canvas = '', ctx = '', img = '' this.imgSrc = '' this.reader = new FileReader() this.reader.onload = (event) => { if (file.size >= 1024 * 1024 * this.GLOBAL.fileSize) { //呼叫自定義方法來處理圖片 var quality = 1 //壓縮圖片的質量 canvas = document.createElement('canvas') //建立畫布 ctx = canvas.getContext('2d') img = new Image() img.src = event.target.result img.onload = function () { const width = img.width const height = img.height canvas.width = 1200 //這裡可以自定義你的圖片大小 canvas.height = 1200 * (img.height / img.width) that.dialogVisible = true setTimeout(() => { ctx.fillRect(0, 0, 0, 0) ctx.drawImage(img, 0, 0, 1200, canvas.height) that.imgSrc = canvas.toDataURL('image/jpeg', quality) //將圖片轉為Base64 之後預覽要用 that.$refs.cropper.replace(that.imgSrc) }, 50) } } else { that.dialogVisible = true that.$nextTick(function () { that.imgSrc = event.target.result that.$refs.cropper.replace(event.target.result) }) } } that.reader.readAsDataURL(file) }, setImage_two(e) { let that = this let file = this.e_photo_filefile let canvas = '', ctx = '',img = ''; this.e_photo_file = e this.e_photo_filefile = file this.reader = '' this.imgSrc = '' this.reader = new FileReader() this.reader.onload = (event) => { //呼叫自定義方法來處理圖片 var quality = 1 //壓縮圖片的質量 canvas = document.createElement('canvas') //建立畫布 ctx = canvas.getContext('2d') img = new Image() img.src = event.target.result img.onload = function () { // 清除畫布 const width = img.width const height = img.height canvas.width = 1200 //這裡可以自定義你的圖片大小 canvas.height = 1200 * (img.height / img.width) setTimeout(() => { ctx.fillRect(0, 0, 0, 0) ctx.drawImage(img, 0, 0, 1200, canvas.height) that.imgSrc = canvas.toDataURL('image/jpeg', quality) //將圖片轉為Base64 之後預覽要用 that.$refs.cropper && that.$refs.cropper.replace(that.imgSrc) }, 50) } } that.reader.readAsDataURL(file) }, cropImage() { this.http_cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL() }, cancelCrop() { this.dialogVisible = false this.http_cropImg = this.max_fuyuan_defaultSrc[this.max_fuyuan_defaultSrc.length - 1] $('#change').val('') //取消change事件 }, upladPic() { this.sumitImageFile(this.http_cropImg) }, sumitImageFile(base64Codes) { let that = this var formData = new FormData() var picName = new Date().getTime() + '.png' //給截圖的檔案命名 formData.append('file', that.convertBase64UrlToBlob(base64Codes), picName) //append函式的第一個引數是後臺獲取資料的引數名,和html標籤的input的name屬性功能相同 if (this.img_size >= 1024 * 1024 * this.GLOBAL.fileSize) { this.$message({ message: '要上傳圖片太大,請再次擷取,本次擷取將進行壓縮處理!', type: 'warning', }) this.setImage_two(that.e_photo_file) return } if (this.img_size / 1024 / 1024 < this.GLOBAL.fileSize) { serviceApi.requestPostUploadFile(formData).then((body) => { that.cropImg = body.file_name //傳遞給父元件 that.sendMsg() }) } else { this.$message({ message: '抱歉,要上傳圖片太大,請重新上傳!', type: 'warning', }) that.cropImg = '' that.http_cropImg = '' //傳給表單 //傳遞給父元件 that.cropper_show = false that.sendMsg() } //關閉彈框 $('#change').val('') //取消change事件 this.dialogVisible = false }, //將以base64的圖片url資料轉換為Blob convertBase64UrlToBlob(urlData) { var bytes = window.atob(urlData.split(',')[1]) //去掉url的頭,並轉換為byte //處理異常,將ascii碼小於0的轉換為大於0 var ab = new ArrayBuffer(bytes.length) var ia = new Uint8Array(ab) for (let i = 0; i < bytes.length; i++) { ia[i] = bytes.charCodeAt(i) } let size = new Blob([ab], { type: 'image/png' }) this.img_size = size.size return new Blob([ab], { type: 'image/png' }) }, /******************************圖片剪下結束****************************************/ }, computed: { thisAspectWH() { if (this.AspectWH) { this.cropperAspectWH = this.AspectWH } }, }, mounted() { //監聽父元件是否點選上傳的事件 this.$on('inputfile', (val) => { if (this.AspectWH) { this.cropperAspectWH = this.AspectWH } this.childAction(val) }) }, watch: {}, created() { if (this.AspectWH) { this.cropperAspectWH = this.AspectWH } }, } </script>
<style scoped> /* 圖片剪裁樣式 */ .crop-demo { display: flex; align-items: flex-end; width: 150px; height: 150px; } .crop-demo-btn { position: absolute; left: auto; top: 50%; transform: translateY(-50%); width: 100px; height: 40px; line-height: 40px; padding: 0; text-align: center; font-size: 12px; margin-left: 25px; color: #fff; background-color: rgba(0, 0, 0, 0.2); border-radius: 4px; box-sizing: border-box; cursor: pointer; } .crop-input { position: absolute; width: 100px; height: 40px; left: 0; top: 0; opacity: 0; font-size: 0; padding: 0; cursor: pointer; } </style>
注意點
這個方法要自己寫 serviceApi.requestPostUploadFile
父元件中使用
<div class="crop-demo">
<div
style="
position: relative;
display: flex;
width: 340px;
height: 170px;
"
>
<span>
<img
:src="XXXXXXX"
style="
width: 340px;
height: 170px;
background: #f8f8f8;
border: 1px solid #eee;
border-radius: 5px;
object-fit: cover;
"
/>
</span>
<div
style="
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 100px;
line-height: 40px;
padding: 0;
text-align: center;
font-size: 12px;
background-color: #9da1a585;
color: #fff;
border-radius: 4px;
box-sizing: border-box;
"
>
點選更換圖片
<div
@click="toSonClick('label')"
style="
position: absolute;
width: 100px;
height: 40px;
left: 0;
top: 0;
opacity: 0;
cursor: pointer;
"
/>
</div>
</div>
</div>
<CropperCut
v-if="CropperCutShow"
:AspectWH="AspectWH"
:label="CropperCutlabel"
@getPicNamefile="getPicNamefile"
ref="CropperCut"
></CropperCut>
data中加入:
//裁剪外掛的label 是誰呼叫的
AspectWH: "1", //裁剪外掛的寬高比
CropperCutlabel: "",
CropperCutShow: false, //控制開關 裁剪外掛
//裁剪外掛的事件
toSonClick(label) {
let that = this;
if (label == "label") {
this.AspectWH = 1;
} else if (label == "XXX") {
this.AspectWH = 2;
}
this.CropperCutShow = true;
this.CropperCutlabel = label;
setTimeout(() => {
that.$refs.CropperCut.$emit("inputfile");
}, 10);
},
//外掛外掛
getPicNamefile(cropImg, http_cropImg, label) {
this.CropperCutShow = false;
this.AspectWH = 1;
if (label == "label") {
this.CropperCutlabel = "";
} else if (label == "XXX") {
this.CropperCutlabel = "";
}
},