2025年9月10日 星期三

前端影像CSS濾鏡互動應用解析



一、前言:影像濾鏡的現代網頁應用

隨著網頁技術的進步,影像處理不再是專屬於 Photoshop 或專業影像軟體的領域。現代瀏覽器原生支援 CSS filter濾鏡效果,讓開發者能夠直接在網頁上為圖片加上各式各樣的濾鏡效果,並且能夠即時互動、無需後端運算。

本範例將以一個完整的「CSS 影像濾鏡互動應用」為例,深入剖析一個以純 HTML、CSS 與 JavaScript 製作的「影像濾鏡互動範例」。本範例不僅展示了 CSS 濾鏡的多種應用,還結合了現代 UI 設計、無框架的純前端開發技巧,其設計理念為使用HTML 完成資料與結構、CSS 進行排版與美化、JavaScript 負責互動邏輯。以詳細的註解,讓程式碼具備高度可讀性與維護性。進而從需求分析、架構設計、程式細節、互動體驗、維護性與延伸性等多面向,完整剖析這份程式碼,並提供實戰經驗與最佳實踐建議。本範例適合前端工程師、設計師實務參考。


二、本範例架構與設計理念

2.1 設計目標

本範例旨在打造一個純前端、無框架依賴的影像濾鏡互動平台,讓使用者能夠:

  • 上傳自訂圖片或載入預設圖片。
  • 能夠套用多種 CSS 濾鏡(灰階、復古、反轉、亮度、對比、模糊、飽和、色相旋轉)。
  • 即時預覽濾鏡效果,並可隨時重設,提供簡潔且高效能的方式來實現視覺效果。
  • 擁有現代化、馬卡龍色系的美觀 UI。
  • 每一行 HTML、CSS、JavaScript 皆有精確中文註解,便於學習與維護。

2.2 設計原則

  • 語意化結構:HTML 採用語意化標籤與 class 命名,提升可讀性。
  • 純 CSS 美化:不依賴任何 CSS 框架,所有樣式皆以CSS自訂,並以馬卡龍色系提升視覺吸引力。
  • 互動性強:JavaScript 控制所有互動,包含圖片上傳、濾鏡切換、hover 效果等。
  • 完整註解:每一行程式碼皆有精確中文註解,適合學習與維護。

三、HTML 結構詳解

以下為主要HTML結構說明,分為六個區塊:

  1. 主容器 .container:集中所有內容,負責版面置中與美化。
  2. 1.<div class="container">:主內容容器,負責版面置中與美化。
  3. 標題 .main-title:頁面主題。
  4. 1.<h1 class="main-title">:頁面主標題。
  5. 上傳/預設圖片區 .upload-row:檔案載入imageLoader與預設圖片按鈕loadDefaultImage。
  6. 1.<div class="upload-row">:上傳與預設圖按鈕區。
    2.<input type="file" id="imageLoader">:檔案載入元件。
    3.<button id="loadDefaultImage">:載入預設圖片按鈕。
  7. 圖片顯示區 .image-row:顯示目前圖片。
  8. 1.<div class="image-row">:圖片顯示外框。
    2.<img id="filteredImage">:主圖片,所有濾鏡效果皆套用於此。
  9. 濾鏡按鈕區 .filter-grid:所有濾鏡與重設按鈕。
  10. 1.<div class="filter-grid">:濾鏡按鈕區,以Grid方式排列。
    2.<button class="filter-btn">:各種濾鏡按鈕。
    3.<button id="resetFiltersBtn">:重設濾鏡按鈕。
  11. 訊息提示 .message-box:顯示操作結果。
  12. 1.<div id="messageBox">:訊息提示框。
  13. 底部說明 .desc-text:操作提示。
  14. 1.<div class="desc-text">:底部說明文字。

四、CSS 美化與馬卡龍色系設計

4.1 主要CSS樣式說明

本範例所有樣式皆以純 CSS 撰寫,並針對每個區塊、按鈕、圖片等進行細緻設計。馬卡龍色系(Macaron Colors)以柔和、明亮、低飽和度為特色,能讓 UI 更加親切、現代。每個濾鏡按鈕都對應一種馬卡龍色,並搭配深色文字,確保可讀性。這樣的配色不僅美觀,也有助於不同濾鏡功能的辨識。

重點如下:

  • .container:白底、圓角、陰影,提升專業感。
  • .main-title:大字、粗體、置中,強調主題。
  • .upload-row:flex 橫向排列,input 與按鈕並排,維持一致性。
  • .file-input:膠囊圓角、淺灰底,呈現現代感。
  • .default-btn:綠底白字,吸引注意。
  • .filter-grid:CSS Grid 多欄排列,按鈕間距均勻。
  • .filter-btn:白字、圓角、粗體、微透明。
  • .btn-macaron-*:馬卡龍色系,讓每顆按鈕有不同色彩。
  • .reset-btn:灰藍色,與濾鏡按鈕區隔。
  • .message-box:白底、圓角、淺灰邊框。
  • .desc-text:灰色說明文字,置中。

五、JavaScript 互動邏輯解析

5.1 DOM 元素取得與初始化

所有互動皆由 JavaScript 控制,首先取得所有必要的 DOM元素並且設定為全域變數,並於 window.onload 進行初始化。

5.2 圖片上傳與預設圖片載入

使用者可上傳自訂圖片,或點擊按鈕載入預設圖片。每次圖片變更時,濾鏡自動重設。

5.3 濾鏡套用與重設

每個濾鏡按鈕都會套用對應的 CSS filter,並顯示提示訊息。重設按鈕則移除所有濾鏡。

5.4 按鈕 hover 動畫,由JavaScript 控制

所有濾鏡按鈕與重設按鈕皆有滑鼠進入與移出動畫,滑鼠移入時亮度提升10%,移出時恢復原始亮度。

5.5 訊息提示功能

所有操作皆會於訊息框顯示提示。

六、操作介面

6.1下圖為介面預設狀態

6.2下圖為不同寬度的頁面預設狀態,呈現自適應網頁的特性

6.3下圖為套用灰階grayscale效果的狀態

grayscale(amount): 將影像轉換為灰階影像。
amount 可以是百分比 (0% - 100%) 或數字 (0 - 1)。
0% (0) 為預設值,代表原始影像。
100% 則影像完全變為灰色(用於黑白影像)。
注意:不允許使用負值。

6.4下圖為套用復古sepia效果的狀態

sepia(amount): 將影像轉換為復古色調的棕褐色。
0% (0) 為預設值,代表原始影像。
100% 則影像完全變為棕褐色。
注意:不允許使用負值。

6.5下圖為套用反轉invert效果的狀態

反轉影像中的色彩。
0% (0) 為預設值,代表原始影像。
100% 將使影像完全反轉。
注意:不允許使用負值。

6.6下圖為套用亮度brightness效果的狀態

調整影像亮度。
0% 表示影像完全變黑。
100% (1) 為預設值,表示原始影像。
超過 100% 的值將提供更明亮的效果。

6.7下圖為套用對比度contrast效果的狀態

調整影像對比度。
0% 表示影像完全變灰色。
100% (1) 為預設值,表示原始影像。
超過 100% 的值會導致對比度降低。

6.8下圖為套用模糊blur效果的狀態

對影像套用模糊效果。
值越大,模糊程度越強。
如果未指定值,則使用 0。

6.9下圖為套用飽和度saturate效果的狀態

使影像飽和度改變。
0% (0) 則影像完全不飽和。
100% 為預設值,代表原始影像。
超過 100% 的值會產生超飽和效果。
注意:不允許使用負值。

6.10下圖為套用色相旋轉hue-rotate濾鏡效果的狀態

對影像套用色相旋轉。
此值定義影像樣本將圍繞色環調整的度數。
0deg 為預設值,代表原始影像。
注意:最大值為 360deg。

6.11下圖為套用重設濾鏡效果的狀態,也就是移除濾鏡效果

6.12下圖為載入使用者圖片的狀態

6.13下圖為載入使用者圖片並套用模糊blur效果的狀態

七、完整程式碼與註解

<!DOCTYPE html>
  <html lang="zh-TW">
  <head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS 影像濾鏡互動應用解析</title>
  <style>
  /* 主要內容容器:置中、白底、圓角、陰影 */
  .container {
      max-width: 800px;
      margin: 0px auto;
      padding: 16px;
      background: #fff;
      border-radius: 20px;
      box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
      border: 3px solid #cccccc;
  }
  
  /* 主標題:大字、粗體、置中 */
  .main-title {
      font-size: 2rem;
      font-weight: bold;
      text-align: center;
  }
  
  /* 上傳區塊:橫向排列、置中 */
  .upload-row {
      display: flex;
      justify-content: center;
  }
  
  /* 檔案上傳 input:膠囊圓角、淺灰底、固定寬度 */
  .file-input {
      padding: 8px 12px;
      border-radius: 20px;
      border: 1px solid #ccc;
      background: #f9f9f9;
      width: 220px;
  }
  
  /* 預設圖片按鈕:綠底、白字、圓角 */
  .default-btn {
      padding: 10px 28px;
      border-radius: 20px;
      background: #22c55e;
      color: #fff;
      border: none;
      cursor: pointer;
  }
  
  /* 圖片顯示區:置中 */
  .image-row {
      display: flex;
      justify-content: center;
  }
  
  /* 圖片外框 */
  .image-container {
      border-radius: 12px;
      background: #fff;
      padding: 1rem;
  }
  
  /* 圖片本體:響應式寬度、圓角、濾鏡動畫 */
  #filteredImage {
      display: block;
      margin: auto;
      max-width: 50%;
      border-radius: 8px;
      transition: filter 0.3s;
  }
  
  /* 濾鏡按鈕區:Grid 多欄、間距 */
  .filter-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
      gap: 16px;
  }
  
  /* 濾鏡按鈕:白字、圓角、粗體、微透明 */
  .filter-btn {
      color: #fff;
      padding: 10px 0;
      border-radius: 12px;
      font-size: 1rem;
      font-weight: 600;
      border: none;
      cursor: pointer;
      opacity: 0.9;
  }
  
  /* 馬卡龍色系按鈕:每顆按鈕不同色彩 */
  .btn-macaron-gray {
      background: #bdbdbd;
      color: #333333;
  }
  
  .btn-macaron-orange {
      background: #ffd6a5;
      color: #a15c00;
  }
  
  .btn-macaron-pink {
      background: #ffb7b2;
      color: #a13a3a;
  }
  
  .btn-macaron-yellow {
      background: #fff5ba;
      color: #a18f00;
  }
  
  .btn-macaron-green {
      background: #caffbf;
      color: #2e7d32;
  }
  
  .btn-macaron-blue {
      background: #a0c4ff;
      color: #1e3a8a;
  }
  
  .btn-macaron-purple {
      background: #bdb2ff;
      color: #5f3dc4;
  }
  
  .btn-macaron-mint {
      background: #9bf6ff;
      color: #007a7a;
  }
  
  .reset-btn {
      background: #6b7280;
      color: #fff;
  }
  
  /* 訊息提示框:白底、圓角、淺灰邊框、置中 */
  .message-box {
      background: #fff;
      border: 1px solid #e2e8f0;
      border-radius: 8px;
      padding: 0.5em;
      margin-top: 1em;
      text-align: center;
  }
  
  /* 底部說明文字:置中、灰色 */
  .desc-text {
      text-align: center;
      color: #64748b;
      margin-top: 16px;
  }
  </style>
  <script>
  // ===== 主要互動腳本 =====
  // DOM 元素取得變數設定為全域變數
  let imageLoader;
  let filteredImage;
  let messageBox;
  let filterButtons;
  let resetFiltersBtn;
  let loadDefaultImageBtn;
  
  // 訊息提示功能(顯示訊息於 messageBox)
  function showMessage(message) {
      messageBox.textContent = message;
  }
  
  // 濾鏡應用:套用單一濾鏡
  function applyFilter(filterValue) {
      filteredImage.style.filter = filterValue;
      showMessage(`已應用濾鏡: ${filterValue}`);
  }
  
  // 重設所有濾鏡
  function resetFilters() {
      filteredImage.style.filter = 'none';
      showMessage('所有濾鏡已重設。');
  }
  
  // 頁面載入自動載入預設圖片
  window.onload = () => {
      imageLoader = document.getElementById('imageLoader');
      filteredImage = document.getElementById('filteredImage');
      messageBox = document.getElementById('messageBox');
      filterButtons = document.querySelectorAll('.filter-btn[data-filter]');
      resetFiltersBtn = document.getElementById('resetFiltersBtn');
      loadDefaultImageBtn = document.getElementById('loadDefaultImage');
      loadDefaultImageBtn.click();
  
      // 圖片上傳:讀取並顯示圖片
      imageLoader.addEventListener('change', (e) => {
          const reader = new FileReader();
          reader.onload = (event) => {
              filteredImage.onload = () => {
                  resetFilters();
              };
              filteredImage.src = event.target.result;
          };
          if (e.target.files[0]) {
              reader.readAsDataURL(e.target.files[0]);
          }
      });
  
      // 載入預設圖片:顯示預設圖並重設濾鏡
      loadDefaultImageBtn.addEventListener('click', () => {
          filteredImage.onload = () => {
              showMessage('已載入預設圖片。');
              resetFilters();
          };
          filteredImage.src = "flower.jpg";
      });
  
      // 濾鏡按鈕事件:點擊套用濾鏡
      filterButtons.forEach(button => {
          button.addEventListener('click', () => {
              const filterValue = button.dataset.filter;
              applyFilter(filterValue);
          });
      });
  
      // 重設濾鏡按鈕事件
      resetFiltersBtn.addEventListener('click', resetFilters);
  };
  
  // 按鈕 hover 特效(JS 控制,亮度提高 10%)
  document.addEventListener('DOMContentLoaded', function () {
      const hoverBtns = document.querySelectorAll('.filter-btn, .reset-btn');
      hoverBtns.forEach(btn => {
          btn.addEventListener('mouseenter', function () {
              btn.style.filter = 'brightness(1.1)';
          });
          btn.addEventListener('mouseleave', function () {
              btn.style.filter = '';
          });
      });
  });
  </script>
  </head>
  <body class="flex">
  <div class="container">
      <h1 class="main-title">CSS 影像濾鏡應用</h1>
      <div class="upload-row">
          <input type="file" id="imageLoader" accept="image/*" class="file-input">
          <button id="loadDefaultImage" class="default-btn">載入預設圖片</button>
      </div>
      <div id="messageBox" class="message-box hidden"></div>
      <div class="image-row">
          <div class="image-container">
              <img id="filteredImage" src="flower.jpg" alt="濾鏡圖片">
          </div>
      </div>
    <div class="filter-grid">
        <button data-filter="grayscale(100%)" class="filter-btn btn-macaron-gray">灰階</button>
        <button data-filter="sepia(100%)" class="filter-btn btn-macaron-orange">復古色</button>
        <button data-filter="invert(100%)" class="filter-btn btn-macaron-pink">反轉色</button>
        <button data-filter="brightness(150%)" class="filter-btn btn-macaron-yellow">亮度 (+50%)</button>
        <button data-filter="contrast(150%)" class="filter-btn btn-macaron-green">對比度 (+50%)</button>
        <button data-filter="blur(5px)" class="filter-btn btn-macaron-blue">模糊</button>
        <button data-filter="saturate(200%)" class="filter-btn btn-macaron-purple">飽和度 (+100%)</button>
        <button data-filter="hue-rotate(90deg)" class="filter-btn btn-macaron-mint">色相旋轉 (90°)</button>
        <button id="resetFiltersBtn" class="filter-btn reset-btn">重設濾鏡</button>
    </div>
    <div class="desc-text">
        <p>上傳您的圖片,或點擊「載入預設圖片」來體驗不同的 CSS 濾鏡效果。</p>
    </div>
</div>
</body>
</html>
      
  

八、結語

本範例完整展現了CSS濾鏡的強大威力與現代前端技術的靈活性。從UI設計、互動邏輯到極致註解,皆以教學與實用為核心。希望本範例能幫助您深入理解 CSS 濾鏡的應用,並能將這些技巧運用於實際工作中。


您可在下列課程中了解更多技巧喔!

0 意見:

張貼留言