涉及到 JS 的圖片壓縮,需要用到 Canvas 的繪圖能力,通過調整圖片的分辨率或者繪圖質量來達到圖片壓縮的效果,實現思路如下:
- 獲取上傳 Input 中的圖片對象 File
- 將圖片轉換成 base64 格式
- base64 編碼的圖片通過 Canvas 轉換壓縮,這里會用到的 Canvas 的 drawImage 以及 toDataURL 這兩個 Api,一個調節圖片的分辨率的,一個是調節圖片壓縮質量並且輸出的,后續會有詳細介紹
- 轉換后的圖片生成對應的新圖片,然后輸出
優缺點介紹
Canvas 壓縮的方式也有着自己的優缺點:
- 優點:實現簡單,參數可以配置化,自定義圖片的尺寸,指定區域裁剪等等。
- 缺點:只有 jpeg 、webp 支持原圖尺寸下圖片質量的調整來達到壓縮圖片的效果,其他圖片格式,僅能通過調節尺寸來實現
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input id="upload" type="file"/> <script> const FILETYPES = ["image/png", "image/jpg", "image/jpeg"]; // 受支持的文件類型 const MAX_FILESIZE = 1024 * 1024 * 3; // 1024 * 1024 為1M const MAX_FILESIZESTRING = "3M"; // 文件大小字符 const COMPRESSRATIO = .5; // 壓縮比例 0 - 1 const upload = document.querySelector("#upload"); const imageToBase64 = (file, callback) => { const reader = new FileReader(); reader.readAsDataURL(file); // 文件轉base64 reader.addEventListener("load", (e) => { callback && callback(e.target.result); }); }; const compress = (originalImage, compressRatio = 1, callback) => { const image = new Image(); image.src = originalImage; // document.body.appendChild(image); // 原圖預覽 /* 監聽圖片的load事件 */ image.addEventListener("load", function () { let [sizeRatio, maxWidth, maxHeight] = [0, 1024, 1024]; // 圖片壓縮寬高比例和最大寬高 let [imageWidth, imageHeight] = [this.naturalWidth, this.naturalHeight]; // 圖片實際寬高 let compressFlag = false; // 圖片是否需要壓縮 // 如果圖片寬度大於最大寬度就等比壓縮圖片的高度 if (imageWidth > maxWidth) { compressFlag = true; sizeRatio = imageWidth / maxWidth; maxHeight = imageHeight / sizeRatio; } // 如果圖片高度大於最大高度就等比壓縮圖片的寬度 if (imageHeight > maxHeight) { compressFlag = true; sizeRatio = imageHeight / maxHeight; maxWidth = imageWidth / sizeRatio; } // 如果不需要壓縮 if (!compressFlag) { maxWidth = imageWidth; maxHeight = imageHeight; } // 使用canvas壓縮圖片 const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); canvas.setAttribute("id", "canvas"); canvas.width = maxWidth; canvas.height = maxHeight; // document.body.appendChild(canvas); // canvas預覽 ctx.clearRect(0, 0, maxWidth, maxHeight); // 清除畫布內所有像素 ctx.drawImage(image, 0, 0, maxWidth, maxHeight); // canvas繪制當前圖片 const compressImage = canvas.toDataURL("image/jpeg", compressRatio); // 設置壓縮類型和壓縮比例獲取壓縮后的文件 callback && callback(compressImage); }); } upload.addEventListener("change", function (e) { const [file] = e.target.files; if (!file) this.value = ""; // file為空就阻止向下執行 const {type: fileType, size: fileSize} = file; // 獲取文件類型和大小 // 檢查是否支持的文件類型 if (!FILETYPES.includes(fileType)) { this.value = ""; alert(`不支持${fileType}類型文件`); return; } // 檢查文件大小 if (fileSize > MAX_FILESIZE) { this.value = ""; alert(`文件不能超過${MAX_FILESIZESTRING}`); return; } imageToBase64(file, (originalImage) => { compress(originalImage, COMPRESSRATIO, (compressImage) => { const _img = new Image(); _img.src = compressImage; const download = document.createElement("a"); download.href = compressImage; download.innerText = "點擊保存"; download.setAttribute("download", "demo.jpg"); document.body.appendChild(download); document.body.appendChild(_img); // 壓縮后的圖片預覽 }); }); }) </script> </body> </html>
本文鏈接:https://www.cnblogs.com/coderDemo/p/13663234.html
https://www.jianshu.com/p/78e8d7c1b71e