大家好,我是Karin。
因為鐵人賽挑戰也快告一段落了,所以想藉由實作一個簡單的東西來當作是這系列的一個小成果。
還不確定能不能成功完成,總之就先來試試看。
首先我請chatGPT幫我把要做的事情分成三天份,並引導我一步步開始練習。
第一天:準備工作與圖片切割
目標:理解如何將圖片切割並動態顯示在頁面上。
這一天的重點是確保你熟悉如何動態生成HTML元素並操作CSS樣式,成功實現圖片切割和隨機打亂圖片塊的功能。
首先先把檔案開好。
接著要讓讓使用者上傳圖片後,切割圖片,製作成拼圖,之後隨機打亂拼圖塊。
HTML
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>圖片拼圖遊戲</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<input type="file" id="imageUpload" accept="image/*">
<div id="puzzle-container"></div>
<script src="script.js"></script>
</body>
</html>
創建一個名為 puzzle-container 的 div區塊,用來放置拼圖。
input:添加文件上傳的功能,並限制上傳的文件類型只能是圖片(accept="image/*")。
CSS
#puzzle-container {
display: grid;
gap: 2px;
max-width: 80vw; /* 設定容器最大寬度為視窗寬度的80% */
max-height: 80vh; /* 設定容器為視窗高度的80% */
aspect-ratio: 1 / 1; /* 保持容器為正方形 */
margin: 0 auto; /* 讓容器在頁面中央 */
}
.puzzle-tile {
background-size: cover;
background-repeat: no-repeat;
cursor: pointer;
border: 1px solid #ccc;
}
CSS Grid:是一種CSS佈局系統,用來設計網頁中的2D格狀佈局。它可以把網頁內容分割成行(rows)和列(columns),並且可以精確控制每個元素的排列方式和大小。
Javascript
document.addEventListener('DOMContentLoaded', function() { // 等待 DOM 內容加載完成後才執行內部的程式碼
const imageUpload = document.getElementById('imageUpload'); // 取得上傳圖片的 input 元素
const puzzleContainer = document.getElementById('puzzle-container'); // 取得拼圖容器的 div 元素
imageUpload.addEventListener('change', function(event) { // 監測 input 元素的 change 事件,當使用者上傳圖片時觸發
const file = event.target.files[0]; // 取得上傳的圖片檔案
if (file) { // 確認是否有上傳圖片
const reader = new FileReader(); // 建立 FileReader 物件來讀取上傳的檔案
reader.onload = function(e) { // 當 FileReader 成功讀取檔案後,觸發 onload 事件
const img = new Image(); // 建立一個新的 Image 物件,用來保存上傳的圖片
img.src = e.target.result; // 設定 Image 物件的 src 為讀取到的圖片資料(Data URL)
img.onload = function() { // 當圖片成功載入後,執行以下程式碼
const rows = 3; // 固定拼圖的行數為3
const cols = 3; // 固定拼圖的列數為3
const containerWidth = puzzleContainer.clientWidth; // 取得拼圖容器的寬度
const containerHeight = puzzleContainer.clientHeight; // 取得拼圖容器的高度
// 根據容器大小計算每塊拼圖的寬度(容器寬度除以列數)
const tileWidth = containerWidth / cols;
const tileHeight = containerHeight / rows; // 根據容器大小計算每塊拼圖的高度(容器高度除以行數)
puzzleContainer.innerHTML = ''; // 清除之前的拼圖內容,準備生成新的拼圖
// 設置拼圖容器的 CSS 樣式,使其使用 grid 佈局,行數和列數均為 3
puzzleContainer.style.gridTemplateColumns = `repeat(${cols}, 1fr)`; // 設置每列的寬度分配為 1fr,根據列數分佈
puzzleContainer.style.gridTemplateRows = `repeat(${rows}, 1fr)`; // 設置每行的高度分配為 1fr,根據行數分佈
const positions = []; // 建立一個陣列來儲存每塊拼圖的背景圖片位置
for (let i = 0; i < rows * cols; i++) {
positions.push({ // 根據拼圖塊的位置計算其對應的背景位置,儲存到陣列中
backgroundPosition: `${-(i % cols) * tileWidth}px ${-Math.floor(i / cols) * tileHeight}px`
});
}
positions.sort(() => Math.random() - 0.5); // 隨機打亂陣列中的背景圖片位置,讓拼圖呈現隨機順序
// 根據打亂後的背景位置生成拼圖塊
for (let i = 0; i < rows * cols; i++) { // 為每塊拼圖生成對應的 div
const tile = document.createElement('div'); // 建立一個新的 div 元素,代表一塊拼圖
tile.classList.add('puzzle-tile'); // 為拼圖塊添加 CSS 類別,方便樣式控制
tile.style.width = `${tileWidth}px`; // 設置拼圖塊的寬度
tile.style.height = `${tileHeight}px`; // 設置拼圖塊的高度
tile.style.backgroundImage = `url(${img.src})`; // 設定拼圖塊的背景圖片為上傳的圖片
tile.style.backgroundSize = `${containerWidth}px ${containerHeight}px`; // 設置背景圖片大小與拼圖容器匹配
tile.style.backgroundPosition = positions[i].backgroundPosition; // 設定每塊拼圖的背景位置為打亂後的順序
puzzleContainer.appendChild(tile); // 將拼圖塊添加到拼圖容器中
}
};
};
reader.readAsDataURL(file); // 使用 FileReader 讀取圖片檔案,並將其轉換成 Data URL 格式
}
});
});
整理一下我丟給它的指令:
1.開始實作圖片拼圖遊戲
index.html
、style.css
和 script.js
檔案,並讓你動態生成3x3的圖片拼圖。圖片被切割成9塊後,排列在一個網格中。2.讓使用者可以上傳圖片
input
元素,並使用 JavaScript 來處理圖片上傳,動態切割圖片成3x3的拼圖塊。這段過程中,圖片大小會根據容器的寬高進行調整,以適應視窗大小。3.讓拼圖適應螢幕視窗大小
puzzle-container
的CSS樣式,將容器的大小限制為視窗寬度的80%,並使用 aspect-ratio
保持圖片拼圖的比例不變。同時,在JavaScript中根據容器的寬高動態調整拼圖塊的大小,確保拼圖適應螢幕範圍。4.隨機打亂拼圖塊
Array.sort()
來隨機打亂圖片塊的順序,並將打亂後的圖片塊重新排列在網格中,保持遊戲的隨機性。5.修改拼圖塊的排列方式
6.不需要選擇行列數,固定為3x3拼圖
突然看到了一大堆沒看過的func.,要再整理消化一下......還有一些想優化的地方明天繼續(˘・_・˘)