h5移動端手機拍照,壓縮(旋轉),上傳 (vue,FileReader,exif-js,canvas,axios)(未完待續)
阿新 • • 發佈:2019-02-08
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
}
}
}