本文將介紹再Vue項目中經過js對圖片進行壓縮後使用。(純前端實現,不依賴後臺)前端
主要使用Canvas.toDataURL(type, encoderOptions)對圖片大小進行調整vue
參數 | 描述 |
---|---|
type | 圖片格式 |
encoderOptions | 在指定圖片格式爲 image/jpeg 或 image/webp的狀況下,能夠從 0 到 1 的區間內選擇圖片的質量。 |
使用 FileReader.readAsDataURL(file):該方法會讀取指定的 File 對象。讀取操做完成的時候,readyState 會變成已完成(DONE),並觸發 loadend 事件,同時 result 屬性將包含一個data:URL格式的字符串(base64編碼)以表示所讀取文件的內容。
reader.readAsDataURL 把圖片能轉換成 base64, 出發 reader.onload 事件對 image.src 賦值完成,觸發 image.onload 事件生成canvas,調用回調函數。web
/** * 將圖片轉化爲base64 */ imgBase64(file, callback) { // 看支持不支持FileReader if (!file || !window.FileReader) return; // 建立一個 Image 對象 let image = new Image(); // 綁定 load 事件處理器,加載完成後執行 image.onload = function () { // 建立 canvas DOM 對象 let canvas = document.createElement('canvas'); // 返回一個用於在畫布上繪圖的環境, '2d' 指定了您想要在畫布上繪製的類型 let ctx = canvas.getContext('2d'); // 若是高度超標 // 參數,最大高度 let MAX_HEIGHT = 3000; if (image.height > MAX_HEIGHT) { // 寬度等比例縮放 *= image.width *= MAX_HEIGHT / image.height; image.height = MAX_HEIGHT; } // 獲取 canvas的 2d 環境對象, ctx.clearRect(0, 0, canvas.width, canvas.height); // 重置canvas寬高 canvas.width = image.width; canvas.height = image.height; // 將圖像繪製到canvas上 ctx.drawImage(image, 0, 0, image.width, image.height); callback(image, canvas); }; if (/^image/.test(file.type)) { // 建立一個reader let reader = new FileReader(); // 讀取成功後的回調 reader.onload = function () { // 設置src屬性,瀏覽器會自動加載。 // 記住必須先綁定事件,才能設置src屬性,不然會出同步問題。 image.src = this.result; }; // 將圖片將轉成 base64 格式 reader.readAsDataURL(file); } }
/** * 把base64轉換成file文件 */ convertBase64UrlToFile(dataurl, filename) { let arr = dataurl.split(','), mime = 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: mime}); }
function checkAndHandleCompression() { //當異步代碼執行成功時,咱們纔會調用resolve(...), 當異步代碼失敗時就會調用reject(...) return new Promise((resolve, reject) => { resolve('成功!') // 代碼正常執行! }) } checkAndHandleCompression().then((data)=>{ console.log(data) // print 成功! });
若是圖片過大就使用Canvas.toDataURL(type, encoderOptions)對圖片進行壓縮,並將結果異步返回
/** * 檢查並壓縮圖片大小 */ checkAndHandleCompression(file) { return new Promise((resolve, reject) => { this.imgBase64(file, (image, canvas) => { let maxSize = 2 * 1024; // 壓縮到2M如下 (單位KB) let fileSize = file.size / 1024; // 圖片大小 (單位KB) let uploadSrc, uploadFile; // 若是圖片大小大於maxSize,進行壓縮 if (fileSize > maxSize) { uploadSrc = canvas.toDataURL(file.type, maxSize / fileSize); uploadFile = this.convertBase64UrlToFile(uploadSrc, file.name); // 轉成file文件 } else { uploadSrc = image.src; uploadFile = file; } let compressedSize = uploadFile.size / 1024;// 壓縮後圖片大小 (單位KB) // 判斷圖片大小是否小於maxSize,若是大於則繼續壓縮至小於爲止 if (compressedSize.toFixed(2) > maxSize) { this.checkAndHandleCompression(uploadFile); } else { let fileOptions = {uploadSrc, uploadFile}; resolve(fileOptions); } }); }); }
建立mixins/image-compress.jscanvas
export default { methods: { /** * 檢查並壓縮圖片大小 */ checkAndHandleCompression(file) { return new Promise((resolve, reject) => { this.imgBase64(file, (image, canvas) => { let maxSize = 2 * 1024; // 2M (單位KB) let fileSize = file.size / 1024; // 圖片大小 (單位KB) let uploadSrc, uploadFile; // 若是圖片大小大於maxSize,進行壓縮 if (fileSize > maxSize) { uploadSrc = canvas.toDataURL(file.type, maxSize / fileSize); // 轉換成DataURL uploadFile = this.convertBase64UrlToFile(uploadSrc, file.name); // 轉成file文件 } else { uploadSrc = image.src; uploadFile = file; } let compressedSize = uploadFile.size / 1024;// 壓縮後圖片大小 (單位KB) // 判斷圖片大小是否小於maxSize,若是大於則繼續壓縮至小於爲止 if (compressedSize.toFixed(2) > maxSize) { this.checkAndHandleUpload(uploadFile); } else { let fileOptions = {uploadSrc, uploadFile}; resolve(fileOptions); } }); }); }, /** * 將圖片轉化爲base64 */ imgBase64(file, callback) { // 看支持不支持FileReader if (!file || !window.FileReader) return; // 建立一個 Image 對象 let image = new Image(); // 綁定 load 事件處理器,加載完成後執行 image.onload = function () { // 建立 canvas DOM 對象 let canvas = document.createElement('canvas'); // 返回一個用於在畫布上繪圖的環境, '2d' 指定了您想要在畫布上繪製的類型 let ctx = canvas.getContext('2d'); // 若是高度超標 // 參數,最大高度 let MAX_HEIGHT = 3000; if (image.height > MAX_HEIGHT) { // 寬度等比例縮放 *= image.width *= MAX_HEIGHT / image.height; image.height = MAX_HEIGHT; } // 獲取 canvas的 2d 環境對象, // 能夠理解Context是管理員,canvas是房子 ctx.clearRect(0, 0, canvas.width, canvas.height); // 重置canvas寬高 canvas.width = image.width; canvas.height = image.height; // 將圖像繪製到canvas上 ctx.drawImage(image, 0, 0, image.width, image.height); callback(image, canvas); }; if (/^image/.test(file.type)) { // 建立一個reader let reader = new FileReader(); // 讀取成功後的回調 reader.onload = function () { // 設置src屬性,瀏覽器會自動加載。 // 記住必須先綁定事件,才能設置src屬性,不然會出同步問題。 image.src = this.result; }; // 將圖片將轉成 base64 格式 reader.readAsDataURL(file); } }, /** * 把Base64轉換成file文件 */ convertBase64UrlToFile(dataurl, filename) { let arr = dataurl.split(','), mime = 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: mime}); } } };
<template> ... <input type="file" @change="handleUploadImage"/> ... </template> <script> import imageUploadMixins from '@/mixins/image-compress'; export default { mixins: [imageUploadMixins], ... methods:{ handleUploadImage(e){ let file = e.target.files[0]; this.checkAndHandleCompression(file).then( fileOptions => { // let {uploadSrc, uploadFile} = fileOptions; // 壓縮完成使用 uploadSrc, uploadFile ... }); } } ... } </script> <style> ... </style>