前端的圖片壓縮image-compressor(可在圖片上傳前實現圖片壓縮)

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前端。如有意見可以進行評論,每一條評論我都會認真對待。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,881評論 18 139
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數據革命閱讀 12,218評論 2 33
  • HTML 5 HTML5概述 因特網上的信息是以網頁的形式展示給用戶的,因此網頁是網絡信息傳遞的載體。網頁文件是用...
    阿啊阿吖丁閱讀 4,060評論 0 0
  • (10)繪憶真體驗 “你喜歡聽什么歌?”毛不易問余暖。 “心動”余暖想了一會兒還是說了出來,這確實是自己最喜歡的歌...
    小魚稚閱讀 251評論 0 1
  • 歷史,是勝利者書寫的。 但是,在司馬遷的史記里,依然把項羽寫在本紀里邊。 要知道,本紀是專屬于帝王的傳記。司馬遷是...
    成成日志閱讀 405評論 0 0