思路: 建立一個canvas,將圖片繪製在畫布上,
經過設置canvas的寬度和質量,去調整圖片大小css
這一步是爲了建立一個image,在image中獲取寬高比html
// 將file轉化爲base64 function changeFileToBaseURL(file, fn) { var flieReader = new FileReader() if(file == undefined) return fn(null) flieReader.readAsDataURL(file); flieReader.onload = function() { var imgBase64Data = this.result; fn(imgBase64Data) } }
在canvas完成圖片壓縮以後,以base64格式導出
這個時候能夠將base64轉換爲file方便回調函數操做canvas
// 將base64轉換爲file function dataURLToFile(dataUrl, fileName) { var arr = dataUrl.split(','), mine = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], fileName, {type: mine}) }
/** * canvas壓縮圖片 * @param {參數obj} param * @param {文件二進制流} param.file 必傳 * @param {目標壓縮大小} param.targetSize 不傳初始賦值-1 * @param {輸出圖片寬度} param.width 不傳初始賦值-1,等比縮放不用傳高度 * @param {輸出圖片名稱} param.fileName 不傳初始賦值image * @param {壓縮圖片程度} param.quality 不傳初始賦值0.92。值範圍0~1 * @param {回調函數} param.succ(file, base64) 必傳 */ function imgCompress(param) { if(!(param && param.succ)) return if(param.file == undefined) return // param.targetSize = param.hasOwnProperty("targetSize") ? param.targetSize : -1 param.width = param.hasOwnProperty("width") ? param.width : -1 param.fileName = param.hasOwnProperty("fileName") ? param.fileName : 'image' param.quality = param.hasOwnProperty("quality") ? param.quality : 0.92 var fileType = param.file.type if(fileType.indexOf('image') == -1) { console.log("請選擇圖片文件") } changeFileToBaseURL(param.file, function(base64) { if(base64) { var image = new Image(); image.src = base64 image.onload = function() { // 圖片的原始寬高比 var scale = this.width / this.height var canvas = document.createElement('canvas') var context = canvas.getContext('2d') canvas.width = param.width == -1 ? this.width : param.width canvas.height = param.width == -1 ? this.height : parseInt(param.width / scale) context.drawImage(image, 0, 0, canvas.width, canvas.height) // 將canvas轉換爲base64和file格式,做爲回調參數 var newImageData = canvas.toDataURL(fileType, param.quality); var resultFile = dataURLToFile(newImageData, param.fileName); param.succ(resultFile, newImageData) } } }) }
這裏雖然有targetSize的參數,可是這個參數並無使用上,
緣由是若是想要精確地將圖片大小轉換在某個數如下的話,須要用到遞歸去處理寬度,
這會對性能形成必定負擔。我沒有想到更好的方法...
能夠經過調整width和quality參數去知足接口大小限制。函數
<div class="preview-box"> <img src="" alt=""> <p class="size"></p> </div> <input type="file" id="uploadBtn">
.preview-box{ width: 300px; min-height: 300px; } img{ width: 300px; }
var ipt = document.querySelector('#uploadBtn') var previewEl = document.querySelector('.preview-box img') var sizeEl = document.querySelector('.size') ipt.onchange = function() { imgCompress({ file: this.files[0], targetSize: 1024 * 1024 * 1, width: 900, // quality: 1, fileName: 'imgCompress', succ: function(file, base64) { previewEl.setAttribute('src', base64) sizeEl.innerHTML = file.size / 1024 / 1024 + 'M' console.log(file) } }) }