最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于JavaScript實(shí)現(xiàn)在線圖片壓縮工具

 更新時(shí)間:2026年03月17日 08:35:15   作者:滕青山  
本文詳細(xì)介紹了基于JavaScript實(shí)現(xiàn)的在線圖片壓縮工具的功能層設(shè)計(jì),包括前端狀態(tài)模型、文件接入、參數(shù)解析、壓縮主流程、重壓縮觸發(fā)、服務(wù)端壓縮、結(jié)果展示與資源回收等關(guān)鍵部分,需要的朋友可以參考下

這篇只講本項(xiàng)目“圖片壓縮”工具的功能層 JavaScript 實(shí)現(xiàn)。整體鏈路是:

選擇圖片 -> 讀取原圖信息 -> 提交壓縮參數(shù) -> 獲取壓縮結(jié)果 -> 更新預(yù)覽與統(tǒng)計(jì) -> 下載

在線工具網(wǎng)址:https://see-tool.com/image-compressor

工具截圖:

1. 前端狀態(tài)模型:圍繞“多圖批處理”設(shè)計(jì)

工具初始化后維護(hù)一個(gè)輕量狀態(tài)對象,核心是 images 數(shù)組和當(dāng)前預(yù)覽索引。

const state = {
  images: [],
  currentIndex: 0,
  recompressTimer: null,
};

每張圖片在內(nèi)存里都是一個(gè)獨(dú)立對象,既保存原圖信息,也保存壓縮結(jié)果信息:

  • 原圖:originalUrloriginalSize、originalWidth、originalHeight、originalType
  • 壓縮圖:compressedUrl、compressedSize、compressedWidth、compressedHeightcompressedMimeType
  • 控制字段:compressController、compressVersion

這種結(jié)構(gòu)的好處是,單圖更新不會影響其他圖片,批量場景下邏輯更穩(wěn)定。

2. 文件接入:先過濾,再補(bǔ)齊元信息

拖拽和文件選擇最終都走同一入口 processFiles,先過濾非圖片文件,再逐個(gè)處理。

const processFiles = async (files) => {
  const imageFiles = files.filter(
    (file) => file.type && file.type.startsWith("image/"),
  );
  if (imageFiles.length === 0) return;

  for (const file of imageFiles) {
    await addImageFile(file);
  }
};

addImageFile 會為文件創(chuàng)建對象 URL,并用 Image 對象讀取像素尺寸,形成完整的圖片對象后立即觸發(fā)一次壓縮。

const addImageFile = async (file) => {
  const url = URL.createObjectURL(file);
  const img = await loadImage(url);

  const imageObj = {
    id: `${Date.now()}-${Math.random()}`,
    name: file.name,
    file,
    originalUrl: url,
    originalIsObjectUrl: true,
    originalSize: file.size,
    originalType: file.type || "image/jpeg",
    originalWidth: img.width,
    originalHeight: img.height,
    compressedUrl: null,
    compressedSize: null,
    compressController: null,
    compressVersion: 0,
  };

  state.images.push(imageObj);
  state.currentIndex = state.images.length - 1;
  compressImage(imageObj);
};

3. 參數(shù)解析:輸出格式和“直出原圖”判定

壓縮前先計(jì)算輸出格式配置。工具支持 original/jpeg/png/webp/avif,并統(tǒng)一映射成 mimeType + extension。

同時(shí)有一個(gè)關(guān)鍵分支:當(dāng)用戶選擇 original 且質(zhì)量 100,并且沒有勾選移除元數(shù)據(jù)時(shí),直接復(fù)用原圖,不發(fā)請求。

const shouldUseOriginal = (imageObj) => {
  const format = elements.outputFormat.value;
  const quality = Number(elements.qualitySlider.value);
  if (format !== "original") return false;
  if (quality < 100) return false;
  if (elements.removeMetadata && elements.removeMetadata.checked) return false;
  return true;
};

這個(gè)分支能保證結(jié)果與用戶設(shè)置一致:既然參數(shù)不要求二次編碼,就直接返回原始文件。

4. 壓縮主流程:可取消請求 + 版本號防亂序

compressImage 是核心函數(shù),負(fù)責(zé)把當(dāng)前圖片和參數(shù)提交到接口并回寫結(jié)果。

const formData = new FormData();
formData.append("image", imageObj.file, imageObj.name);
formData.append("format", elements.outputFormat.value);
formData.append("quality", String(Number(elements.qualitySlider.value)));
formData.append(
  "removeMetadata",
  String(Boolean(elements.removeMetadata?.checked)),
);
formData.append("progressive", String(Boolean(elements.progressive?.checked)));

const controller = new AbortController();
const compressVersion = Number(imageObj.compressVersion || 0) + 1;
imageObj.compressVersion = compressVersion;
imageObj.compressController = controller;

const response = await fetch("/api/image-compress", {
  method: "POST",
  body: formData,
  signal: controller.signal,
});

結(jié)果返回后不會立刻寫入,而是先校驗(yàn)兩件事:

  1. 這張圖還在列表里(沒被刪除)
  2. 當(dāng)前響應(yīng)版本號仍是最新

只有通過校驗(yàn)才更新 compressedUrl、compressedSize、compressedWidth、compressedHeight。

這能避免“用戶連續(xù)拖動質(zhì)量滑塊”時(shí)舊請求覆蓋新結(jié)果。

5. 重壓縮觸發(fā):延遲調(diào)度統(tǒng)一入口

質(zhì)量滑塊、輸出格式、元數(shù)據(jù)開關(guān)變化后,都不會直接逐張同步請求,而是進(jìn)入 scheduleRecompress。

const scheduleRecompress = (delay = 120) => {
  if (state.recompressTimer) {
    clearTimeout(state.recompressTimer);
    state.recompressTimer = null;
  }
  state.recompressTimer = setTimeout(() => {
    state.recompressTimer = null;
    updateCompressedImages();
  }, delay);
};

updateCompressedImages 內(nèi)部遍歷 state.images,逐張調(diào)用 compressImage,讓參數(shù)變化后的行為保持一致。

6. 服務(wù)端壓縮:字段校驗(yàn) + Sharp 編碼

接口只接收 POST multipart/form-data。先做參數(shù)清洗:

  • 文件體積上限(30MB)
  • 目標(biāo)格式白名單
  • 質(zhì)量范圍(1~100)
  • 布爾參數(shù)標(biāo)準(zhǔn)化(true/false/1/0/yes/no

隨后讀取輸入元信息,解析目標(biāo)格式,再按格式進(jìn)入不同編碼分支:

switch (targetFormat) {
  case "jpeg":
    transformer = transformer.jpeg({ quality, mozjpeg: true, progressive });
    break;
  case "png":
    transformer = transformer.png({
      quality,
      compressionLevel: 9,
      progressive,
    });
    break;
  case "webp":
    transformer = transformer.webp({ quality, effort: 6 });
    break;
  case "avif":
    transformer = transformer.avif({ quality, effort: 6 });
    break;
}

返回體是壓縮后的二進(jìn)制數(shù)據(jù),同時(shí)附帶輸出信息頭:

  • X-Output-Ext
  • X-Output-Width
  • X-Output-Height
  • X-Output-Size

前端據(jù)此展示壓縮圖信息,不需要再額外解析文件。

7. 結(jié)果展示與資源回收

統(tǒng)計(jì)區(qū)通過聚合 originalSizecompressedSize 計(jì)算總原始體積、總壓縮體積、節(jié)省體積和壓縮率。預(yù)覽區(qū)按 currentIndex 展示當(dāng)前圖的原圖/壓縮圖與像素信息。

批量下載按順序觸發(fā),清空或刪除圖片時(shí)會執(zhí)行兩步清理:

  1. 中斷進(jìn)行中的壓縮請求(AbortController
  2. 釋放對象 URL(URL.revokeObjectURL

這樣整條鏈路能長期穩(wěn)定運(yùn)行:上傳、重壓縮、預(yù)覽切換、刪除、清空都在同一套狀態(tài)模型里閉環(huán)。

以上就是基于JavaScript實(shí)現(xiàn)在線圖片壓縮工具的詳細(xì)內(nèi)容,更多關(guān)于JS在線圖片壓縮工具的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺析JavaScript函數(shù)的調(diào)用模式

    淺析JavaScript函數(shù)的調(diào)用模式

    這篇文章主要為大家詳細(xì)介紹了JavaScript函數(shù)的調(diào)用模式,包括方法調(diào)用模式,構(gòu)造器調(diào)用模式,apply/call調(diào)用模式,感興趣的小伙伴們可以參考一下
    2016-08-08
  • js判斷ie方法集錦(含正則)代碼短小經(jīng)典

    js判斷ie方法集錦(含正則)代碼短小經(jīng)典

    javascript 判斷是否是ie,是否是特定版本 ,方法比較多,正則代碼比較段
    2008-07-07
  • javascript中一些奇葩的日期換算方法總結(jié)

    javascript中一些奇葩的日期換算方法總結(jié)

    這篇文章主要給大家總結(jié)介紹了關(guān)于javascript中的一些奇葩的日期換算方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • uniapp中input聚焦禁止軟鍵盤彈出方法

    uniapp中input聚焦禁止軟鍵盤彈出方法

    在使用uni-app完成掃碼功能時(shí),有時(shí)需要聚焦文本框的同時(shí),需要軟鍵盤消失,下面這篇文章主要給大家介紹了關(guān)于uniapp中input聚焦禁止軟鍵盤彈出的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • 前端html2canvas使用場景的詳細(xì)教程

    前端html2canvas使用場景的詳細(xì)教程

    html2canvas是一個(gè)前端JavaScript庫,能夠?qū)eb頁面中的DOM元素渲染為高保真的圖片,適用于生成頁面截圖或?qū)崿F(xiàn)打印預(yù)覽功能,這篇文章主要介紹了前端html2canvas使用場景的相關(guān)資料,需要的朋友可以參考下
    2025-11-11
  • JS如何獲取瀏覽器聲音、麥克風(fēng)以及通知權(quán)限

    JS如何獲取瀏覽器聲音、麥克風(fēng)以及通知權(quán)限

    在我們開發(fā)網(wǎng)頁的時(shí)候偶爾會有需要用戶錄音的情況,下面這篇文章主要給大家介紹了關(guān)于JS如何獲取瀏覽器聲音、麥克風(fēng)以及通知權(quán)限的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • swiper實(shí)現(xiàn)異形輪播效果

    swiper實(shí)現(xiàn)異形輪播效果

    這篇文章主要為大家詳細(xì)介紹了swiper實(shí)現(xiàn)異形輪播效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • JavaScript樹結(jié)構(gòu)深度優(yōu)先算法

    JavaScript樹結(jié)構(gòu)深度優(yōu)先算法

    這篇文章主要介紹了JavaScript樹結(jié)構(gòu)深度優(yōu)先算法,樹結(jié)構(gòu)可以說是前端中最常見的數(shù)據(jù)結(jié)構(gòu)之一,比如說DOM樹、級聯(lián)選擇、樹形組件,更多相關(guān)內(nèi)容需要的小伙伴可以參考一下
    2022-07-07
  • JavaScript中Cookie的簡介和使用方法詳解

    JavaScript中Cookie的簡介和使用方法詳解

    cookie是瀏覽器提供的一種機(jī)制,它將document對象的cookie屬性提供給JavaScript,這篇文章主要給大家介紹了關(guān)于JavaScript中Cookie的簡介和使用方法,需要的朋友可以參考下
    2025-05-05
  • 小程序從手動埋點(diǎn)到自動埋點(diǎn)的實(shí)現(xiàn)方法

    小程序從手動埋點(diǎn)到自動埋點(diǎn)的實(shí)現(xiàn)方法

    這篇文章主要介紹了小程序從手動埋點(diǎn)到自動埋點(diǎn)的實(shí)現(xiàn)方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-01-01

最新評論

阿鲁科尔沁旗| 莱西市| 蒙自县| 崇阳县| 肥乡县| 蓬莱市| 麻栗坡县| 泌阳县| 个旧市| 宁波市| 临桂县| 轮台县| 含山县| 莒南县| 会东县| 当雄县| 甘德县| 闻喜县| 五常市| 定襄县| 深州市| 松江区| 彭泽县| 宜阳县| 伊川县| 安仁县| 长宁区| 冀州市| 商南县| 长沙县| 武冈市| 呼伦贝尔市| 荔浦县| 漳州市| 肇州县| 酒泉市| 华坪县| 卢氏县| 昌邑市| 巴林左旗| 阳高县|