頭像裁剪壓縮上傳流程:
點擊頭像--判斷是否為IOS端--若是--A,否則--B
A:選擇圖片 --C
B:彈框供用戶選擇從相冊選擇或者調用相機拍照--選擇圖片--C
C:出現cropper裁剪框,裁剪框位於圖片上方,用戶可以拖動或者放大縮小裁剪框--用戶手動調整后--代碼執行壓縮並上傳
1.引入vueCropper組件
地址:https://www.npmjs.com/package/vue-cropper/v/0.4.7
npm install vue-cropper --save-dev <script> import { VueCropper } from 'vue-cropper' export default { name: 'UserProfile', components: { VueCropper }, } </script>
使用vue-cropper組件
<!-- 剪裁圖片組件 --> <van-popup class="bg-tran" v-model="showCropper" closeable position="top" :style="{ height: '100%' }" > <div class="flex-column-center height100"> <vueCropper ref="cropper" :img="option.img" :outputSize="option.outputSize" :outputType="option.outputType" :info="option.info" :full="option.full" :autoCropWidth="option.autoCropWidth" :autoCropHeight="option.autoCropHeight" :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" :high="option.high" :mode="option.mode" ></vueCropper> <van-col span="24" class="font14 col-white"> <van-col span="8" class="p-2"><span @click="cancelCropper">取消</span></van-col> <van-col span="8" class="p-2 text-center"><span @click="rotateImage" class="font18"><van-icon name="replay" /></span></van-col> <van-col span="8" class="p-2 text-right"><span @click="getCropBlob">確定</span></van-col> </van-col> </div> </van-popup>
vue-cropper配置:
<script> export default { data() { return { option: { img: '', outputSize: 0.8, info: false, // 裁剪框的大小信息 outputType: 'jpeg', // 裁剪生成圖片的格式 canScale: false, // 圖片是否允許滾輪縮放 autoCrop: true, // 是否默認生成截圖框 autoCropWidth: window.innerWidth - 100 + 'px', // 默認生成截圖框寬度 autoCropHeight: window.innerWidth - 100 + 'px', // 默認生成截圖框高度 high: true, // 是否按照設備的dpr 輸出等比例圖片 fixedBox: true, // 固定截圖框大小 不允許改變 fixed: true, // 是否開啟截圖框寬高固定比例 fixedNumber: [1, 1], // 截圖框的寬高比例 full: true, // 是否輸出原圖比例的截圖 canMoveBox: false, // 截圖框能否拖動 original: false, // 上傳圖片按照原始比例渲染 centerBox: false, // 截圖框是否被限制在圖片里面 infoTrue: false, // true 為展示真實輸出圖片寬高 false 展示看到的截圖框寬高 mode: '100% auto' // 圖片默認渲染方式 } } } } </script>
2.點擊頭像選擇文件,裁剪壓縮並上傳
這里需要判斷是否為蘋果手機;
蘋果手機點擊上傳頭像會默認彈框顯示拍照還是從文件中選擇,安卓手機點擊上傳頭像則默認從文件中選擇;
這里判斷如果是安卓手機則顯示我們自定義的彈框供用戶選擇是拍照還是從文件中選擇
<!--點擊上傳頭像 --> <van-cell-group> <van-cell title="頭像" is-link @click="checkIsIos" /><!-- 檢測是否為蘋果手機 --> <img v-if="fromWX" :src="wxImgUrl"> <!-- 默認顯示微信頭像(帶http的絕對鏈接) --> <img v-else :src="headImgUrl"> <input type="file" name="fileIOS" @change="changeImgIOS" accept="image/*" ref="inputFileRefIOS" style="display:none;" /> </van-cell> </van-cell-group> <!--安卓上傳頭像彈框,需要注意的是調用相機時,type="file" name="file" capture="camera" 必須寫正確,否則調用相機不成功 --> <van-popup v-model="uploadModal" position="bottom"> <div> <div @click="openFile">從相冊中選擇</div> <input type="file" name="file" @change="changeImg" accept="image/*" ref="inputFileRef" style="display:none;" /> <div @click="openFile">拍照</div> <input type="file" name="file" @change="changeImg" accept="image/*" ref="inputFileRef" capture="camera" style="display:none;" /> <div @click="uploadModal = false">取消</div> </div> </van-popup>
methods:{ checkIsIoS(){//點擊頭像調用的方法 if(!this.isIOS){//非IOS則顯示自定義彈框 this.uploadModal = true this.isCamera = true }else{ this.$refs.inputFIleRefIOS.click()//IOS選擇文件,觸發changeImgIOS方法 } }, //IOS選擇文件 changeImgIOS(){ let file = this.$refs.inputFIleRefIOS.file[0] this.showCropper = true//顯示裁剪框 this.imageFileName = file.name //保存上傳的文件名,方便后續用到 this.imageToBase64(file)//圖片壓縮並轉化為base64,否則cropper組件顯示不出要裁剪的圖片 }, //安卓選擇文件,從相冊中選擇 openFile(){ this.$refs.inputFIleRef.click() }, //安卓選擇文件,調用相機 openFile(){ this.isCamera = true this.$refs.inputFIleRef.click() }, changeImg(){ this.uploadModal = false let file = null if(this.isCamera){ file = this.$refs.inputFIleRefCamera.files[0]//相機拍照的 }else{ file = this.$refs.inputFIleRef.files[0]//相冊選擇的 } this.showCropper = true this.imageFileName = file.name this.imageToBase64(file) }, imageToBase64(file){ this.option.img = ''//清空上一次裁剪的圖片 let reader = new FileReader() reader.readAsDataURL(file) reader.onload = () =>{ if(file.size>(1*1024*1024)){//大於 1M 的圖片壓縮 let scaleSize = 0.9//定義壓縮的比例(程度) let image = new Image() image.src = reader.result; image.onload = () =>{ if(file.size>(1*1024*1024) && file.size<(2*1024*1024+1)){//1-2M scaleSize = 0.9 } if(file.size>(2*1024*1024) && file.size<(3*1024*1024+1)){//2-3M scaleSize = 0.9 } if(file.size>(3*1024*1024) && file.size<(4*1024*1024+1)){//3-4M scaleSize = 0.9 } if(file.size>(4*1024*1024)){//4M+ scaleSize = 0.9 } let img64 = this.compress(image,scaleSize) this.option.img = img64 } }else{ this.option.img = reader.result } } reader.onerror = (rrror) =>{ console.log(error) } }, compress(img,ratio){//圖片壓縮並轉化為base64返回 let canvas,ctx,img64; let width = img.width*0.6//改變上傳的圖片像素,縮放至原來的0.6 let height = img.height*0.6 canvas = document.createElement('canvas') canvas.width = width canvas.height = height ctx = canvas.getContext('2d') ctx.drawImage(img,0,0,width,height) img64 = canvas.toDataURL('image/jpeg',ratio)//參考 https://www.runoob.com/jsref/met-canvas-drawimage.html return img64 }, //綁定在cropper組件上的方法,確認裁剪並上傳圖片到后台 getCropBlob(){ let toast = Toast.loading({ duration:0, forbidClick:true, message:'加載中' }) let formData = new FormData() this.$refs.cropper.getCropBlob(async (data) =>{ formData.append('custId',this.custId) formData.append('multiReq',data,this.imageFileName) let rs = await axios({ method:'post', url:cfg.baseURL.XXX + '', data:formData, headers:{ openId:sessionStorage.getItem('openId') } }) if(rs.data.code=='200'){ Toast.clear() Toase.success('上傳成功') }else{ Toast.clear() Toase.fail('修改異常') } this.showCropper = false //隱藏裁剪遮罩 this.isCamera = false }) }, //旋轉圖片 rotateImage(){ this.$refs.cropper.rotateImage() }, //取消截圖上傳頭像 cancelCropper(){ this.showCropper = false; this.isCamera = false } }, mounted(){ let u = navigator.userAgent this.isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) },