1. 程式人生 > >h5移動端手機拍照,壓縮(旋轉),上傳 (vue,FileReader,exif-js,canvas,axios)(未完待續)

h5移動端手機拍照,壓縮(旋轉),上傳 (vue,FileReader,exif-js,canvas,axios)(未完待續)

import EXIF from 'exif-js' export default { name: '', data () { return { compressFrondImage: '', // 壓縮之前的圖片 compressEndImage: '' // 壓縮之後的圖片 } }, components: {}, created () {}, mounted () {}, methods: { /** * 圖片檔案發生變化 */ imageFileChange (e) { this.file = e.target.files[0
] console.log(this.file) if (this.file) { // FileReader let reader = new FileReader() reader.readAsDataURL(this.file) reader.onload = (e) => { console.log(e.target) this.compressFrondImage = e.target.result this.compressImages(this
.compressFrondImage) } } }, /** * 壓縮圖片 */ compressImages (res) { let defaultImage = { width: 1440, height: 1080, quality: 0.8, // 壓縮圖片的質量 orientation: '' // 獲取照片方向角屬性,使用者旋轉控制 } var img = new Image() img.src = res let
initSize = img.src.length img.onload = () => { // 方便手機測試 alert('壓縮之前寬度: ' + img.width) alert('壓縮之前高度: ' + img.height) // 方便瀏覽器測試 console.log('壓縮之前寬度: ' + img.width) console.log('壓縮之前高度: ' + img.height) var canvas = document.createElement('canvas') var ctx = canvas.getContext('2d') if (img.width > defaultImage.width) { img.height = img.height * (defaultImage.width / img.width) img.width = defaultImage.width } if (img.height > defaultImage.height) { img.width *= defaultImage.height / img.height img.height = defaultImage.height } canvas.width = img.width canvas.height = img.height ctx.clearRect(0, 0, canvas.width, canvas.height) EXIF.getData(this.file, () => { // IMG_FILE為影象資料 // 是否是iPhone手機,iPhone 拍照之後的壓縮是逆時針旋轉90,針對iphone做一下處理 if (navigator.userAgent.match(/iphone/i)) { defaultImage.orientation = EXIF.getTag(this.file, 'Orientation') // translate是平移變換,scale(-1,1)是向左翻轉,rotate是順時針旋轉。 // defaultImage.orientation = 6 // 測試iPhone手機 alert('Orientation:' + defaultImage.orientation) // 拍照方向 switch (Number(defaultImage.orientation)) { case 2: ctx.translate(img.width, 0) ctx.scale(-1, 1) ctx.drawImage(img, 0, 0, img.width, img.height) break case 3: ctx.rotate(180 * Math.PI / 180) ctx.drawImage(img, -img.width, -img.height, img.width, img.height) break case 4: ctx.translate(img.width, 0) ctx.scale(-1, 1) ctx.rotate(180 * Math.PI / 180) ctx.drawImage(img, -img.width, -img.height, img.width, img.height) break case 5: ctx.translate(img.width, 0) ctx.scale(-1, 1) ctx.rotate(90 * Math.PI / 180) ctx.drawImage(img, 0, -img.width, img.height, img.width) break case 6: canvas.width = img.height canvas.height = img.width ctx.rotate(90 * Math.PI / 180) ctx.drawImage(img, 0, 0, img.width, -img.height) break case 7: ctx.translate(img.width, 0) ctx.scale(-1, 1) ctx.rotate(270 * Math.PI / 180) ctx.drawImage(img, -img.height, 0, img.height, img.width) break case 8: ctx.rotate(270 * Math.PI / 180) ctx.drawImage(img, -img.height, 0, img.height, img.width) break default: ctx.drawImage(img, 0, 0, img.width, img.height) } } else { ctx.drawImage(img, 0, 0, img.width, img.height) } var imgUrl = canvas.toDataURL('image/jpeg', defaultImage.quality) // 手機端測試 alert('壓縮率:' + ~~(100 * (initSize - imgUrl.length) / initSize) + '%') alert('壓縮之後寬度: ' + img.width) alert('壓縮之後高度: ' + img.height) // 瀏覽器測試 console.log('壓縮前:' + initSize) console.log('壓縮後:' + imgUrl.length) console.log('壓縮率:' + ~~(100 * (initSize - imgUrl.length) / initSize) + '%') console.log('壓縮之後寬度: ' + img.width) console.log('壓縮之後高度: ' + img.height) console.log('壓縮之後base64地址') console.log(imgUrl) // 壓縮之後的base64 圖片地址 this.compressEndImage = imgUrl // TODO 上傳圖片檔案 this.uploadImage() }) } }, /** * 上傳圖片 */ uploadImage: function () { }, /** * 瓦片壓縮 正在測試 */ imagesCompress: function (img) { // 用於壓縮圖片的canvas var canvas = document.createElement('canvas') var ctx = canvas.getContext('2d') // 瓦片canvas var tCanvas = document.createElement('canvas') var tctx = tCanvas.getContext('2d') var initSize = img.src.length var width = img.width var height = img.height // 如果圖片大於四百萬畫素,計算壓縮比並將大小壓至400萬以下 var ratio if ((ratio = width * height / 4000000)>1) { ratio = Math.sqrt(ratio) width /= ratio height /= ratio } else { ratio = 1 } canvas.width = width canvas.height = height // 鋪底色 ctx.fillStyle = '#fff' ctx.fillRect(0, 0, canvas.width, canvas.height) // 如果圖片畫素大於100萬則使用瓦片繪製 var count if ((count = width * height / 1000000) > 1) { count = ~~(Math.sqrt(count)+1) // 計算要分成多少塊瓦片 // 計算每塊瓦片的寬和高 var nw = ~~(width / count) var nh = ~~(height / count) tCanvas.width = nw tCanvas.height = nh for (var i = 0; i < count; i++) { for (var j = 0; j < count; j++) { tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh) ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh) } } } else { ctx.drawImage(img, 0, 0, width, height) } // 進行最小壓縮 var ndata = canvas.toDataURL('image/jpeg', 0.8) console.log('壓縮前:' + initSize) console.log('壓縮後:' + ndata.length) console.log('壓縮率:' + ~~(100 * (initSize - ndata.length) / initSize) + '%') tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0 return ndata } } }