由於需求因此利用vue的插件vue-cropper進行圖片剪裁。vue
npm install vue-cropper
複製代碼
import VueCropper from vue-cropper
複製代碼
<div> <el-upload :action="''" list-type="picture-card" :file-list="MastergraphPicList" :limit="10" :on-change='changeUpload' :auto-upload="false" :show-file-list="isFlag" :http-request="ServiceUpLoad" :on-success="(response,file,fileList) => handlePostSuccess(response,file,fileList)" :on-remove="(response,file,fileList) => handleDelete(response,file,fileList)" > <i class="el-icon-plus"></i> <div slot="tips" class="el-upload__tip">支持jpg、jpge、png格式,大小不超過2m,限10張</div> </el-upload> </div> 複製代碼
上傳圖片時會觸發changeUpload
此鉤子函數,因爲剪裁圖片是以彈框形式喚起,所以咱們的行爲能夠在此鉤子函數中寫。ios
changeUpload(file, fileList) { <!--限制文件格式、大小--> const isLt2M = file.size / 1024 / 1024 < 2 if (!isLt2M) { this.$message.error('上傳文件大小不能超過 2MB!') return false } <!--寫入回顯列表--> this.MastergraphPicList.push(file); <!--觸發子級方法,喚起剪裁框--> this.$children[0].isShow(); }, 複製代碼
剪裁框模板 cropper.vuenpm
<template> <div> <el-dialog title="圖片剪裁" :visible.sync="dialogVisible" append-to-body> <div class="cropper-content"> <div class="cropper" style="text-align:center"> <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" :fixed="option.fixed" :fixedNumber="option.fixedNumber" :centerBox="option.centerBox" :infoTrue="option.infoTrue" :fixedBox="option.fixedBox" ></vueCropper> </div> </div> <div slot="footer" class="dialog-footer"> <el-button @click="cancel">取 消</el-button> <el-button type="primary" @click="finish" :loading="loading">確認</el-button> </div> </el-dialog> </div> </template> <script> import axios from 'axios' import { VueCropper } from 'vue-cropper' import md5 from 'js-md5'; import { postossImage } from '../../../api/index' export default { name:'cropper', data() { return { // 裁剪組件的基礎配置option option: { img: '', // 裁剪圖片的地址 info: true, // 裁剪框的大小信息 outputSize: 0.8, // 裁剪生成圖片的質量 outputType: 'jpeg', // 裁剪生成圖片的格式 canScale: true, // 圖片是否容許滾輪縮放 autoCrop: true, // 是否默認生成截圖框 autoCropWidth: 600, // 默認生成截圖框寬度 autoCropHeight: 300, // 默認生成截圖框高度 fixedBox: false, // 固定截圖框大小 不容許改變 fixed: false, // 是否開啓截圖框寬高固定比例 fixedNumber: [7, 5], // 截圖框的寬高比例 full: true, // 是否輸出原圖比例的截圖 canMoveBox: true, // 截圖框可否拖動 original: true, // 上傳圖片按照原始比例渲染 high: true, centerBox: true, // 截圖框是否被限制在圖片裏面 infoTrue: true // true 爲展現真實輸出圖片寬高 false 展現看到的截圖框寬高 }, picsList: [], //頁面顯示的數組 // 防止重複提交 loading: false, dialogVisible:false, // 控制彈框的顯示 fileinfo:[], RequestSource:'', // oss直傳源地址 baseurl:'', // 裁剪後的base64地址 isVictory:false, // 識別用戶是點否關閉 } }, components:{VueCropper}, created() { this.$on('is-Show',this.isShow); }, methods:{ isShow(file){ this.fileinfo = file; // 傳遞須要剪裁的地址 以彈框形式打開 this.$nextTick( () => { this.option.img = file.url; this.dialogVisible = true; this.handlePostSuccess(file.url); }) }, // 關閉圖片剪裁 cancel() { this.dialogVisible = false; // 點擊取消時 去除已經回顯的圖片 this.$parent.dislodge(this.fileinfo); }, // 確認剪裁後觸發 finish() { this.$refs.cropper.getCropData((data) => { this.baseurl = data; //將剪裁後base64的圖片轉化爲file格式 let file = this.convertBase64UrlToBlob(data) file.name = this.fileinfo.name <!--let file = URL.createObjectURL(data).match(/[^blob:]+/g).join('');--> this.Directpass(this.RequestSource,file).then( (res) => { if (res.status === 200) { this.$parent.handleSuccess({ uid:this.fileinfo.uid, imgUrl:res.config.url.split('?')[0] }); this.dialogVisible = false; this.isVictory = true; this.loading = true; this.$message('上傳成功!'); // 防止用戶不上傳圖片 點擊關閉時 不能及時刪除回顯的問題 setTimeout(() => { this.isVictory = false; },1000) } }) }) }, // 上傳服務主圖 handlePostSuccess(file) { postossImage({ fileMd5:md5(file) }).then( (res) => { this.RequestSource = res.data; }) }, Directpass(url,file){ return new Promise( (resolve,reject) => { axios.put(url,file,{headers:{"x-oss-meta-author":"deshe","Content-Type":"application/octet-stream"}}).then( (res) => { resolve(res) }) }) }, // 將base64的圖片轉換爲file文件 convertBase64UrlToBlob(urlData) { let bytes = window.atob(urlData.split(',')[1]);//去掉url的頭,並轉換爲byte //處理異常,將ascii碼小於0的轉換爲大於0 let ab = new ArrayBuffer(bytes.length); let ia = new Uint8Array(ab); for (var i = 0; i < bytes.length; i++) { ia[i] = bytes.charCodeAt(i); } return new Blob([ab], { type: 'image/jpeg' }); } }, watch:{ dialogVisible() { if (!this.dialogVisible && !this.isVictory) { this.loading = false // 點擊關閉時 去除已經回顯的圖片 this.$parent.dislodge(this.fileinfo); } else { this.loading = false; } } } } </script> <style scoped lang="less"> .cropper-content { .cropper { width: auto; height: 300px; } } </style> 複製代碼
在cropper.vue中主要起剪裁做用的是finish()
方法以及convertBase64UrlToBlob()
。 須要注意的是:剪切後的圖片返回的是一串沒有意義的字符串,傳遞到服務器沒法識別,在這裏我用了 this.$refs.cropper.getCropData()
把剪切的圖片以base64的形式返回,接着把base64數據作一層處理,轉化爲Blob對象,裏面存儲着剪裁後圖片的數據序列,接着把處理好的地址往服務器丟就搞定了。axios
還有就是:
fixed
設爲false將不限剪裁的寬高api
以上僅我的見解。數組