image-compressor
一個簡單的JavaScript圖像壓縮器。使用瀏覽器的原生canvas.toBlob API做的壓縮工作。一般使用此壓縮是在客戶端圖像文件上傳之前。
實例模板:Website
github:image-compressor
Getting started(新手入門)
Install(npm 安裝)
npm install image-compressor.js // 注意是image-compressor.js 不是 image-compressor那是另一個包
Usage(使用)
Syntax語法
new ImageCompressor([file[, options]])
參數說明
file:(可選)壓縮的目標圖像文件,類型是 File 或者 Blob
options:(可選)壓縮選項,類型是 Object
案例
<input type="file" id="file" accept="image/*">
import axios from 'axios'
import ImageCompressor from 'image-compressor.js' // 引入
document.getElementById('file').addEventListener('change', (e) => {
const file = e.target.files[0]; // file對象
if (!file) { return } // 為空處理
new ImageCompressor(file, {
quality: .6,
success(result) {
const formData = new FormData(); // FormData學習地址 https://developer.mozilla.org/zh-CN/docs/Web/API/FormData
formData.append('file', result, result.name);
// 通過XMLHttpRequest服務發送壓縮的圖像文件-Send the compressed image file to server with XMLHttpRequest.
axios.post('/path/to/upload', formData).then(() => {
console.log('Upload success');
});
},
error(e) {
console.log(e.message);
},
});
});
Options參數
checkOrientation
是否檢查圖片的 orientation 屬性,類型是 boolean。默認值是 true。
提示:如果讀取圖像的EXIF的 orientation 屬性(JPEG圖像),有可能根據 orientation 屬性自動翻轉或旋轉圖像。
注意:不要一直相信這一點,因為一些JPEG圖像有不正確的(不是標準的) orientation 屬性
maxWidth
輸出圖像的最大寬度,類型是 number。默認值是 Infinity。值應該大于0。
因為一個canvas元素的大小限制,所以為了避免得到一個空白的輸出圖像,你可能需要給最大寬度和最大高度選項設置有限的數字。
maxHeight
輸出圖像的最大高度,類型是 number。默認值是 Infinity。值應該大于0。
minWidth
輸出圖像的最小寬度,類型是 number。默認值是 0。該值應大于0且不應大于maxWidth
minHeight
輸出圖像的最小寬度,類型是 number。默認值是 0。該值應大于0且不應大于maxHeight
width
輸出圖像的寬度,類型是 number。默認值是 undefined。值應該大于0。
如果沒有指定,將使用原始圖像的自然寬度,或者如果設置高度選項,則寬度將由自然長寬比自動計算。
height
輸出圖像的高度,類型是 number。默認值是 undefined。值應該大于0。
如果沒有指定,將使用原始圖像的自然高度,或者如果設置寬度選項,則高度將由自然長寬比自動計算。
注意:為了保持與原始圖像相同的寬高比,如果設置寬度選項,將使用它自動計算高度,這意味著高度選項將被忽略。
quality
輸出圖像的畫質,類型是 number。默認值是 undefined。值是0到1之間的數字。
小心使用1,因為它可能使輸出圖像的尺寸變大。
注意:此選項僅適用于 JPEG 和 WebP 格式的圖像。
Examples:
值 | 圖片原來大小 | 圖片壓縮大小 | 壓縮比例 | 描述 |
---|---|---|---|---|
0 | 2.12MB | 114.61 KB | 94.72% | - |
0.2 | 2.12MB | 349.57 KB | 83.90% | - |
0.4 | 2.12MB | 517.10 KB | 76.18% | - |
0.6 | 2.12MB | 694.99 KB | 67.99% | 推薦 |
0.8 | 2.12MB | 1.14 MB | 46.41% | 推薦 |
1 | 2.12MB | 2.12 MB | 0% | 不推薦 |
NaN | 2.12MB | 2.01 MB | 5.02% | - |
mimeType
輸出圖像的文件類型,類型是 string。默認值是 auto。默認情況下,源映像文件的原始MIME類型將被使用。
convertSize
輸出圖像的文件類型,類型是 number。默認值是 5000000 (5MB)。
PNG文件超過此值將被轉換為JPEG格式。若要禁用此功能,只需將值設置為無窮大。
Examples (in Chrome 61):
convertSize | 輸入的文件大小Input size (type) | 輸出的文件大小Output size (type) | 壓縮比 |
---|---|---|---|
5 MB | 1.87 MB (PNG) | 1.87 MB (PNG) | 0% |
5 MB | 5.66 MB (PNG) | 450.24 KB (JPEG) | 92.23% |
5 MB | 9.74 MB (PNG) | 883.89 KB (JPEG) | 91.14% |
beforeDraw(context, canvas)
在將圖像繪制到畫布中進行壓縮之前,要執行的鉤子函數,類型是 Function。默認值是 null。
參數說明:
context: canvas的2D渲染上下文。
canvas: 壓縮畫布
new ImageCompressor(file, {
beforeDraw(context) {
context.fillStyle = '#fff';
},
});
drew(context, canvas)
該鉤子函數執行后,將圖像繪制到畫布中進行壓縮,類型是 Function。默認值是 null。
參數說明:
context: canvas的2D渲染上下文。
canvas: 壓縮畫布
new ImageCompressor(file, {
drew(context) {
context.filter = grayscale(100%);
},
});
success(result)
成功壓縮圖像時執行的鉤子函數,類型是 Function。默認值是 null。
參數說明:
result: 壓縮后的圖像(一個Blob對象)。
error(err)
當圖像壓縮失敗時執行的鉤子函數,類型是 Function。默認值是 null。
參數說明:
err: 壓縮錯誤(一個Error對象)。
方法
compress(file[, options])
file:(必選)壓縮的目標圖像文件,類型是 File 或者 Blob
options:(可選)壓縮選項,類型是 Object
返回值: Promise
使用:
const imageCompressor = new ImageCompressor();
imageCompressor.compress(e.target.files[0], {
quality: 0.8,
maxHeight: 1000,
maxWidth: 1000
}).then((result) => { // 壓縮成功的回調 Handle the compressed image file.
const formData = new FormData()
formData.append('file', result)
// 請求:Send the compressed image file to server with XMLHttpRequest...
// var xhr = new XMLHttpRequest()
// xhr.withCredentials = true...
}).catch((err) => { // 壓縮失敗的回調 Handle the error
console.log(err)
})
瀏覽器支持
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Opera (latest)
- Edge (latest)
- Internet Explorer 10+ (requires a Promise polyfill as es6-promise)
案例
基于vue的element-ui圖片上傳前的壓縮,注意是element-ui的上傳組件。
首先:
npm install image-compressor.js
然后:
import ImageCompressor from 'image-compressor.js' // 引入圖片壓縮
構寫代碼:
html
<el-upload :httpRequest="httpRequest"></el-upload>
httpRequest
httpRequest (options) { // 覆蓋默認的上傳行為,可以自定義上傳的實現,解決壓縮問題
if (this.imageCompress && this.acceptName === 'image/*') { // 如果允許壓縮,并且當前上傳的是圖片
var imageCompressor = new ImageCompressor() // 壓縮成功則使用壓縮的結果,不成功直接上傳
imageCompressor.compress(options.file, {
quality: 0.8,
maxHeight: 1000,
maxWidth: 1000
}).then((result) => { // 壓縮成功的回調
options.file = result
console.log(options)
return ajax(options) // 壓縮成功把壓縮成功的數據傳遞給ajax.js
}).catch((err) => { // 壓縮失敗的回調
console.log(err)
return options.file // 壓縮失敗把原文件傳遞
})
} else {
return ajax(options)
}
}
ajax.js
使用說明:ajax.js可以拿出來單獨使用喲!如果需要封裝成引用型組件,請自行封裝。
function getError (action, option, xhr) {
let msg
if (xhr.response) {
msg = `${xhr.response.error || xhr.response}`
} else if (xhr.responseText) {
msg = `${xhr.responseText}`
} else {
msg = `fail to post ${action} ${xhr.status}`
}
const err = new Error(msg)
err.status = xhr.status
err.method = 'post'
err.url = action
return err
}
function getBody (xhr) {
const text = xhr.responseText || xhr.response
if (!text) {
return text
}
try {
return JSON.parse(text)
} catch (e) {
return text
}
}
export default function upload (option) {
if (typeof XMLHttpRequest === 'undefined') {
return
}
const xhr = new XMLHttpRequest()
const action = option.action
if (xhr.upload) {
xhr.upload.onprogress = function progress (e) {
if (e.total > 0) {
e.percent = e.loaded / e.total * 100
}
option.onProgress(e)
}
}
const formData = new FormData()
if (option.data) {
Object.keys(option.data).forEach(key => {
formData.append(key, option.data[key])
})
}
formData.append(option.filename, option.file)
xhr.onerror = function error (e) {
option.onError(e)
}
xhr.onload = function onload () {
if (xhr.status < 200 || xhr.status >= 300) {
return option.onError(getError(action, option, xhr))
}
option.onSuccess(getBody(xhr))
}
xhr.open('post', action, true)
if (option.withCredentials && 'withCredentials' in xhr) {
xhr.withCredentials = true
}
const headers = option.headers || {}
for (let item in headers) {
if (headers.hasOwnProperty(item) && headers[item] !== null) {
xhr.setRequestHeader(item, headers[item])
}
}
xhr.send(formData)
return xhr
}
結語
到此我們學會了使用image-compressor.js進行圖片壓縮,并且可以根據image-compressor.js在圖片上傳前實現圖片壓縮。
提示:后面還有精彩敬請期待,請大家關注我的專題:web前端。如有意見可以進行評論,每一條評論我都會認真對待。