網格版型與互動縮放:手把手教你用 HTML5 Canvas 實作「線上照片拼貼」工具

發布日期: 2026年6月29日
難度: 中級
所需時間: 約 30-40 分鐘


前言

在現代社群媒體與網頁設計中,將多張照片組合成一張精美拼貼(Collage)的需求非常高。市面上有許多拼貼工具,但多數需要下載 App 或是含有滿滿的廣告浮水印。

本篇文章將帶領大家深入前端開發,使用 HTML5 CanvasCSS Grid 以及 Vanilla JavaScript,實作一個兼具「毛玻璃質感 (Glassmorphism)」與「高互動性」的線上照片拼貼工具

我們將挑戰並實作以下三個核心互動技術: 1. 多網格版型切換(採用彈性的 CSS Grid 進行版面切割)。 2. 圖片互動裁剪與縮放(滑鼠拖曳移動位置、滑桿控制圖片縮放)。 3. 高品質 Canvas 畫布輸出(後台以 3 倍高解析度繪製整張網格與圖片)。


技術架構與挑戰

在開發照片拼貼工具時,有兩個主要的技術挑戰:

  • 挑戰一:如何限制圖片的顯示範圍?

在 CSS 中,我們可以簡單地使用 overflow: hidden 讓溢出的圖片隱藏,並透過 transform 讓使用者拖曳調整。然而,在將這些設定繪製到 Canvas 時,必須經過精準的比例計算,才能把網頁上「看到的」裁剪範圍原封不動地「畫出來」。

  • 挑戰二:如何保證下載圖片的清晰度?

如果直接按照網頁上顯示的寬度(例如 500px)去繪製 Canvas,下載下來的圖片在手機上看起來會非常模糊。因此,我們必須在繪製時,將所有的座標和尺寸放大 3 倍進行渲染,以獲得極為銳利的高品質 PNG 圖檔。


第一步:建構網格版型 (HTML5 + CSS Grid)

我們定義一個主容器 .collage-wrapper,並透過切換 CSS 類名(如 .layout-1x2.layout-2x2 等)來動態套用不同的 CSS Grid 屬性。

<div class="collage-wrapper layout-1x2" id="collage-wrapper">
    <!-- 動態生成多個拼貼網格 (Cells) -->
</div>

我們使用 CSS Grid 來做簡潔的面版配置。例如,常見的 四格切分 (2×2)左大右小三格 (asymmetric)

/* 四格切分 layout-2x2 */
.layout-2x2 {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
}

/* 左大右小 layout-asym-1 */
.layout-asym-1 {
    grid-template-columns: 2fr 1.2fr;
    grid-template-rows: 1fr 1fr;
}
/* 左側第一格跨越兩行 */
.layout-asym-1 .cell-0 {
    grid-row: span 2;
}

這比起傳統使用 absolute 定位或 table 佈局,CSS Grid 能在極少代碼下完美適應圓角與邊框。


第二步:實作圖片滑鼠拖曳與縮放 (JS)

我們在每個網格(Cell)內部放置一個絕對定位的 元素。我們建立一個物件 cellStates 來儲存每格照片的狀態:

cellStates[index] = {
    file: fileObject,       // 上傳的圖片檔案
    imgElement: imgTag,     // 顯示在網頁上的 <img> 標籤
    scale: 1.0,             // 縮放倍率
    x: 0,                   // X 軸平移偏移量
    y: 0                    // Y 軸平移偏移量
};

2-1. 滑鼠拖曳位置調整

當使用者在網格內按住滑鼠時,我們會記錄初始滑鼠座標,並在滑鼠移動時計算差值,動態更新該格圖片的 transform 樣式:

cell.addEventListener('mousedown', function(e) {
    if (!cellStates[index]) return;
    isDragging = true;
    startX = e.clientX - cellStates[index].x;
    startY = e.clientY - cellStates[index].y;
});

window.addEventListener('mousemove', function(e) {
    if (!isDragging) return;
    cellStates[index].x = e.clientX - startX;
    cellStates[index].y = e.clientY - startY;
    
    // 更新網頁上的圖片位置
    state.imgElement.style.transform = `translate(${state.x}px, ${state.y}px) scale(${state.scale})`;
});

這項技術能讓使用者直覺地透過拖曳,把相片最精彩的區域(例如人臉)調整到網格中心。


第三步:高品質 Canvas 後台渲染

當使用者點擊「匯出拼貼」按鈕時,是本專案最核心的部分。我們建立一個虛擬的 ,將畫布大小擴大 3 倍,並逐格繪製圖片。

3-1. 處理圓角裁剪 (Clip Rounded Corners)

如果使用者設定了網格圓角,我們必須在繪製圖片前,在 Canvas 上畫出該網格的圓角路徑,並呼叫 ctx.clip() 來做邊界剪裁:

exportCtx.save();
if (borderRadiusVal > 0) {
    exportCtx.beginPath();
    exportCtx.moveTo(cellX + borderRadiusVal, cellY);
    exportCtx.arcTo(cellX + cellW, cellY, cellX + cellW, cellY + cellH, borderRadiusVal);
    exportCtx.arcTo(cellX + cellW, cellY + cellH, cellX, cellY + cellH, borderRadiusVal);
    exportCtx.arcTo(cellX, cellY + cellH, cellX, cellY, borderRadiusVal);
    exportCtx.arcTo(cellX, cellY, cellX + cellW, cellY, borderRadiusVal);
    exportCtx.closePath();
    exportCtx.clip(); // 限制後續繪圖只能在此圓角內顯示
}

3-2. 實作 Cover 縮放比例計算 (維持長寬比)

因為每格網格的寬高比不同,直接拉伸圖片會造成變形。我們必須在 Canvas 繪製時重新計算圖片大小,使其維持比例地填滿網格(如同 CSS 的 object-fit: cover):

// 計算圖片與網格的比例關係
const imgAspect = tempImg.width / tempImg.height;
const cellAspect = cellW / cellH;

let drawW, drawH;
if (imgAspect > cellAspect) {
    drawH = cellH;
    drawW = cellH * imgAspect;
} else {
    drawW = cellW;
    drawH = cellW / imgAspect;
}

// 加入使用者的自訂平移與縮放設定
const finalW = drawW * state.scale;
const finalH = drawH * state.scale;
const finalX = cellX + (cellW - finalW) / 2 + (state.x * exportScale);
const finalY = cellY + (cellH - finalH) / 2 + (state.y * exportScale);

// 繪製至 Canvas
exportCtx.drawImage(tempImg, finalX, finalY, finalW, finalH);
exportCtx.restore(); // 恢復畫布狀態,準備繪製下一格

當所有網格都載入並繪製完畢後,執行 canvas.toDataURL('image/png') 來導出並下載最終的完美拼貼!


第四步:部署

我們將此專案打包為單一 HTML 檔案,並在 Nginx 伺服器網頁根目錄中建立 /collage/ 目錄:

mkdir -p /var/www/wordpress/collage
cp index.html /var/www/wordpress/collage/index.html
chown -R www-data:www-data /var/www/wordpress/collage

透過 Nginx 直配靜態檔案的特性,網頁載入速度達到了極限,而且不需要佔用伺服器的 PHP/MySQL 資源。


結語

本專案結合了 CSS Grid 版面佈局HTML5 Canvas 圖像繪製 兩大實用技術。自己實作線上拼貼工具不僅可以完全掌控代碼、保障隱私,更沒有任何討人厭的廣告與付費門檻限制。

*歡迎點擊我們的線上拼貼工具親自體驗:(https://stillbuilding.life/collage/)*

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

返回頂端