實(shí)現(xiàn)思路
- 使用input獲取本地文件
- 使用FileReader把圖片轉(zhuǎn)為base64格式
- 使用html5的canvas壓縮圖片(canvas只能處理base64格式的圖片)
- 將壓縮后的base64 數(shù)據(jù)放到input中提交
demo
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>壓縮圖片demo</title>
</head>
<body>
<img id="img" src="">
<input id="file" type="file" onchange="compress()">
</body>
<script>
// 對(duì)圖片進(jìn)行壓縮
function compress() {
let fileObj = document.getElementById('file').files[0] //上傳文件的對(duì)象
let reader = new FileReader()
reader.readAsDataURL(fileObj)
reader.onload = function(e) {
let image = new Image() //新建一個(gè)img標(biāo)簽(還沒(méi)嵌入DOM節(jié)點(diǎn))
image.src = e.target.result
image.onload = function() {
let canvas = document.createElement('canvas'),
context = canvas.getContext('2d'),
imageWidth = image.width / 2, //壓縮后圖片的大小
imageHeight = image.height / 2,
data = ''
canvas.width = imageWidth
canvas.height = imageHeight
context.drawImage(image, 0, 0, imageWidth, imageHeight)
data = canvas.toDataURL('image/jpeg')
//壓縮完成 這里的data就是我們需要壓縮圖片數(shù)據(jù)
document.getElementById('img').src = data
}
}
}
</script>
</html>
等比壓縮判斷
var MAX_HEIGHT = 1000;
if (image.height > MAX_HEIGHT && image.height >= image.width) {
// 寬度等比例縮放 *=
image.width *= MAX_HEIGHT / image.height;
image.height = MAX_HEIGHT;
}
//考錄到用戶(hù)上傳的有可能是橫屏圖片同樣過(guò)濾下寬度的圖片峭状。
if (image.width > MAX_HEIGHT && image.width > image.height) {
// 寬度等比例縮放 *=
image.height *= MAX_HEIGHT / image.width;
image.width = MAX_HEIGHT;
}
如果要寫(xiě)兼容判斷
//第一種方法判斷
if(window.FileReader) {
var fr = new FileReader();
// add your code here
} else {
alert("Not supported by your browser!");
}
//第二種方法判斷
if(typeof FileReader==='undefined'){
alert('您的瀏覽器不支持圖片上傳,請(qǐng)升級(jí)您的瀏覽器');
return false;
}
- 測(cè)試結(jié)果說(shuō)明:Google逼争,F(xiàn)F优床,IE都支持FileReader
- 但是IE9及以下瀏覽器不支持FileReader
為什么要使用到 image.onload(onload:等待圖片加載完成會(huì)自動(dòng)觸發(fā)的方法),因?yàn)楫?dāng)image的src發(fā)生改變誓焦,瀏覽器就會(huì)跑去加載這個(gè)src里的資源胆敞。這個(gè)操作是異步的,就是說(shuō)杂伟,js不會(huì)傻傻地在原地等待圖片的加載移层,而是繼續(xù)讀代碼,直到圖片加載完成赫粥,觸發(fā)onload事件观话,js才會(huì)回來(lái)執(zhí)行onload里面的內(nèi)容。
FileReader API
FileReader實(shí)例擁有五種個(gè)方法越平,其中三個(gè)是用來(lái)讀取文件频蛔,另一個(gè)是用來(lái)中斷讀取的。需要注意的是喧笔,無(wú)論讀取成功或是失敗帽驯,方法并不會(huì)返回讀取結(jié)果,這一結(jié)果(儲(chǔ)存在result屬性中)要用FileReader處理事件去獲仁檎ⅰ尼变;
abort,中斷讀取
readAsBinaryString,將文件轉(zhuǎn)化為二進(jìn)制碼(可以讀取任何類(lèi)型文件)
readAsDataURL,讀取文件內(nèi)容,結(jié)果用data:url的字符串形式表示
readAsText,將文件讀取為文本
readAsArrayBuffer浆劲,方法將讀取一個(gè)Blob對(duì)象或者File對(duì)象嫌术,并產(chǎn)生一個(gè)ArrayBuffer對(duì)象。ArrayBuffer對(duì)象是一個(gè)固定長(zhǎng)度的二進(jìn)制數(shù)據(jù)緩沖牌借。它們?cè)谔幚砦募梢耘缮嫌脠?chǎng)(如將JPEG轉(zhuǎn)換為PNG)度气。
readAsText:該方法有兩個(gè)參數(shù),其中第二個(gè)參數(shù)是文本的編碼方式膨报,默認(rèn)值為 UTF-8磷籍。這個(gè)方法非常容易理解适荣,將文件以文本方式讀取,讀取的結(jié)果即是這個(gè)文本文件中的內(nèi)容院领。
readAsText(file,encoding)可按指定編碼方式讀取文件弛矛,但讀取文件的單位是字符,故對(duì)于文本文件比然,只要按規(guī)定的編碼方式讀取即可丈氓;而對(duì)于媒體文件(圖片、音頻强法、視頻)万俗,其內(nèi)部組成并不是按字符排列,故采用readAsText讀取饮怯,會(huì)產(chǎn)生亂碼闰歪,因此不是最理想的讀取文件的方式。
readAsBinaryString:該方法將文件讀取為二進(jìn)制字符串硕淑,通常我們將它傳送到后端课竣,后端可以通過(guò)這段字符串存儲(chǔ)文件。
readAsDataURL:這是例子程序中用到的方法置媳,該方法將文件讀取為一段以 data: 開(kāi)頭的字符串,這段字符串的實(shí)質(zhì)就是 Data URL公条,Data URL是一種將小文件直接嵌入文檔的方案拇囊。這里的小文件通常是指圖像與 html 等格式的文件。
控制臺(tái)為當(dāng)前所傳文件的base64編碼表示靶橱。由于媒體文件的src屬性寥袭,可以通過(guò)采用網(wǎng)絡(luò)地址或base64的方式顯示,因此我們可以利用readAsDataURL實(shí)現(xiàn)對(duì)圖片的預(yù)覽(即img src=data,這個(gè)data就是readAsDataURL處理后的結(jié)果关霸,直接可以用來(lái)顯示)传黄。
FileReader 事件
FileReader.onabort,處理abort事件队寇。該事件在讀取操作被中斷時(shí)觸發(fā)膘掰。
FileReader.onerror,處理error事件佳遣。該事件在讀取操作發(fā)生錯(cuò)誤時(shí)觸發(fā)识埋。
FileReader.onload,處理load事件零渐。該事件在讀取操作完成時(shí)觸發(fā)窒舟。
FileReader.onloadstart,處理loadstart事件诵盼。該事件在讀取操作開(kāi)始時(shí)觸發(fā)惠豺。
FileReader.onloadend银还,處理loadend事件。該事件在讀取操作結(jié)束時(shí)(要么成功洁墙,要么失斢挤琛)觸發(fā)。
FileReader.onprogress扫俺,處理progress事件苍苞。該事件在讀取Blob時(shí)觸發(fā)。