好的,這是一個符合您需求的完整 HTML 文件,其中包含了 JavaScript 程式碼,可以直接在瀏覽器中開啟使用:
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的相簿</title>
<style>
body {
font-family: sans-serif;
margin: 0;
padding: 0;
background-color: #f0f0f0;
display: flex;
flex-direction: column;
height: 100vh; /* 使 body 佔滿整個視窗高度 */
}
#controls {
position: sticky;
top: 0;
background-color: #fff;
padding: 10px;
z-index: 10; /* 確保控制項在最上層 */
display: flex;
align-items: center;
gap: 10px;
}
#mainImageContainer {
flex-grow: 1; /* 讓圖片容器佔滿剩餘空間 */
display: flex;
justify-content: center;
align-items: center;
overflow: hidden; /* 隱藏超出範圍的部分 */
}
#mainImage {
max-width: 90%; /* 控制圖片最大寬度 */
max-height: 90%; /* 控制圖片最大高度 */
display: block; /* 移除圖片下方的空隙 */
}
#mainImageCaption{
text-align: center;
}
#thumbnailContainer {
position: sticky;
bottom: 0;
background-color: #ddd;
padding: 10px;
overflow-x: auto; /* 允許水平滾動 */
white-space: nowrap; /* 防止縮圖換行 */
z-index: 10;
}
.thumbnail {
width: 100px;
height: 100px;
margin: 5px;
cursor: pointer;
border: 2px solid transparent;
}
.thumbnail.active {
border-color: blue;
}
</style>
</head>
<body>
<div id="controls">
<label for="albumSelect">選擇相簿:</label>
<select id="albumSelect"></select>
<button id="playPauseBtn">播放</button>
<label for="intervalInput">間隔 (秒):</label>
<input type="number" id="intervalInput" value="3" min="1">
</div>
<div id="mainImageContainer">
<img id="mainImage" src="" alt="">
<div id="mainImageCaption"></div>
</div>
<div id="thumbnailContainer">
</div>
<script>
const sources = {
"my_hiking_1": {
path: "../photo_galleries/my_album_1/",
data: [
"001.jpg",
"002.jpg",
"003.jpg",
],
description: [
"001_comment",
"002_comment",
"003_comment",
]
},
"my_hiking_2": {
path: "../photo_galleries/my_album_2/",
data: [
"001.jpg",
"002.jpg",
],
description: [
"001_comment",
"002_comment",
]
},
};
const albumSelect = document.getElementById('albumSelect');
const playPauseBtn = document.getElementById('playPauseBtn');
const intervalInput = document.getElementById('intervalInput');
const mainImage = document.getElementById('mainImage');
const mainImageCaption = document.getElementById('mainImageCaption');
const thumbnailContainer = document.getElementById('thumbnailContainer');
const mainImageContainer = document.getElementById('mainImageContainer');
let currentAlbum = null;
let currentIndex = 0;
let timer = null;
let isPlaying = false;
let interval = 3000; // 預設間隔 3 秒
// 初始化相簿選項
function initAlbums() {
for (const albumName in sources) {
const option = document.createElement('option');
option.value = albumName;
option.textContent = albumName;
albumSelect.appendChild(option);
}
albumSelect.addEventListener('change', loadAlbum);
}
// 載入相簿
function loadAlbum() {
currentAlbum = albumSelect.value;
currentIndex = 0;
stopPlayback();
createThumbnails();
showImage(0); // 顯示第一張圖片
// 顯示可視範圍內的縮圖
showVisibleThumbnails();
}
// 建立縮圖
function createThumbnails() {
thumbnailContainer.innerHTML = ''; // 清空現有縮圖
if (!sources[currentAlbum]) return;
sources[currentAlbum].data.forEach((filename, index) => {
const thumbnail = document.createElement('img');
thumbnail.src = sources[currentAlbum].path + filename;
thumbnail.classList.add('thumbnail');
thumbnail.addEventListener('click', () => {
stopPlayback(); //點擊縮圖時停止播放
showImage(index);
});
thumbnailContainer.appendChild(thumbnail);
});
}
// 顯示指定索引的圖片
function showImage(index) {
if (!sources[currentAlbum] || index < 0 || index >= sources[currentAlbum].data.length) {
return; // 索引超出範圍
}
currentIndex = index;
mainImage.src = sources[currentAlbum].path + sources[currentAlbum].data[index];
mainImageCaption.textContent = sources[currentAlbum].description[index] || '';
// 更新縮圖的 active 狀態
document.querySelectorAll('.thumbnail').forEach((thumb, i) => {
thumb.classList.toggle('active', i === index);
});
// 捲動到目前圖片的縮圖
scrollToThumbnail(index);
}
//捲動到指定縮圖的可視範圍內
function scrollToThumbnail(index) {
const thumbnail = document.querySelectorAll('.thumbnail')[index];
if(thumbnail){
thumbnail.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
}
}
// 開始/繼續 播放
function startPlayback() {
if (!sources[currentAlbum]) return;
if (isPlaying) return; // 已經在播放
isPlaying = true;
playPauseBtn.textContent = '暫停';
if (currentIndex >= sources[currentAlbum].data.length)
{ currentIndex = 0; //如果已到最後一張, 從頭播放
}
showImage(currentIndex); // 顯示目前圖片
timer = setInterval(() => {
currentIndex = (currentIndex + 1) % sources[currentAlbum].data.length; // 循環播放
showImage(currentIndex);
}, interval);
}
// 暫停播放
function pausePlayback() {
isPlaying = false;
playPauseBtn.textContent = '播放';
clearInterval(timer);
}
function stopPlayback() {
pausePlayback(); // 停止計時器
}
// 控制播放/暫停
function togglePlayback() {
if (isPlaying) {
pausePlayback();
} else {
startPlayback();
}
}
// 鍵盤事件處理
function handleKeyPress(event) {
switch (event.key) {
case ' ': // 空白鍵
togglePlayback();
event.preventDefault();
break;
case 'ArrowLeft': // 左方向鍵
stopPlayback(); //先停止播放
showImage(currentIndex - 1);
break;
case 'ArrowRight': // 右方向鍵
stopPlayback(); //先停止播放
showImage(currentIndex + 1);
break;
}
}
// 更新間隔時間
function updateInterval() {
const newInterval = parseInt(intervalInput.value, 10) * 1000;
if (!isNaN(newInterval) && newInterval >= 1000) {
interval = newInterval;
// 如果正在播放,重新啟動計時器以應用新的間隔
if (isPlaying) {
pausePlayback();
startPlayback();
}
}
}
// 監聽縮圖容器的滾動事件
thumbnailContainer.addEventListener('scroll', () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(showVisibleThumbnails, 100); // 設定延遲
});
// 顯示可視範圍內的縮圖
function showVisibleThumbnails() {
const thumbnails = document.querySelectorAll('.thumbnail');
const containerRect = thumbnailContainer.getBoundingClientRect();
thumbnails.forEach((thumbnail) => {
const thumbnailRect = thumbnail.getBoundingClientRect();
const isVisible = (
thumbnailRect.left >= containerRect.left &&
thumbnailRect.right <= containerRect.right
);
// 根據可視性來延遲載入或隱藏縮圖
if (isVisible) {
thumbnail.style.visibility = 'visible'; // 顯示
} else {
thumbnail.style.visibility = 'hidden'; // 隱藏, 但仍占空間
}
});
}
// 初始化
initAlbums();
playPauseBtn.addEventListener('click', togglePlayback);
intervalInput.addEventListener('change', updateInterval);
document.addEventListener('keydown', handleKeyPress);
// 初始載入第一個相簿 (如果存在)
if (albumSelect.options.length > 0) {
albumSelect.value = albumSelect.options[0].value;
loadAlbum();
}
</script>
</body>
</html>
程式碼說明與重要功能解釋:
HTML 結構:
controls: 包含下拉選單、播放/暫停按鈕、間隔時間輸入框。mainImageContainer: 用於顯示完整大小的圖片。mainImage: img 標籤,顯示實際的圖片。mainImageCaption: 顯示圖片描述文字。thumbnailContainer: 包含所有縮圖的容器,設定為水平滾動。.thumbnail: 每個縮圖的樣式。.thumbnail.active: 當前選中圖片的縮圖樣式。CSS 樣式:
position: sticky 將 #controls 和 #thumbnailContainer 固定在頂部和底部。#mainImageContainer 使用 flex-grow: 1 佔滿剩餘空間,並置中顯示圖片。#mainImage 設置最大寬度和高度以適應容器。.thumbnail 設定基本樣式,cursor: pointer 表示可點擊。.thumbnail.active 為選中的縮圖加上邊框。JavaScript 功能:
sources: 定義相簿資料,包含路徑、圖片檔名、描述。
變數宣告: 取得 HTML 元素,並初始化變數。
initAlbums(): 動態產生下拉選單的選項。
loadAlbum():
currentAlbum。currentIndex 為 0。createThumbnails() 建立縮圖。showImage(0) 顯示第一張圖片。showVisibleThumbnails()顯示可視範圍內的縮圖。createThumbnails():
#thumbnailContainer。sources 資料動態產生縮圖 img 元素。showImage()。showImage(index):
mainImage 的 src 屬性為指定圖片。mainImageCaption..active 類別。scrollToThumbnail(index) 將對應的縮圖捲動到可視範圍。scrollToThumbnail(index): 將對應的縮圖捲動到可視範圍。
startPlayback():
isPlaying 為 true。setInterval() 定時切換圖片,並呼叫 showImage()。pausePlayback():
isPlaying 為 false。clearInterval() 清除計時器。stopPlayback(): 完全停止播放 (清除計時器)。
togglePlayback(): 切換播放/暫停狀態。
handleKeyPress(event): 處理鍵盤事件 (空白鍵、左右方向鍵)。
updateInterval(): 更新間隔時間,並在播放時重新啟動計時器。
showVisibleThumbnails():
visibility屬性。初始化:
initAlbums()。如何使用:
.html 檔案 (例如 my_album.html)。photo_galleries 的資料夾。photo_galleries 資料夾中,建立 my_album_1 和 my_album_2 資料夾,並放入對應的圖片。.html 檔案。重要注意事項:
sources 中的 path 正確指向您的圖片資料夾。 此範例使用相對路徑 (例如 ../photo_galleries/my_album_1/)。 如果您的 HTML 檔案和 photo_galleries 資料夾位於同一層級,則可以使用 ./photo_galleries/my_album_1/。 如果它們在不同的位置,您需要調整路徑。sources 中的 data (圖片檔名) 和 description (描述文字) 與您的實際檔案和內容相符。file:///,圖片在 http:// 開頭的網址),可能會遇到跨域問題。 最簡單的解決方法是將它們放在同一個資料夾中,並使用相對路徑。showVisibleThumbnails()來優化縮圖的載入,但如果您要處理非常大量的圖片 (數千張),可能需要進一步的優化,例如使用 Web Workers 或更進階的圖片載入技術。const, let, 箭頭函式),在較舊的瀏覽器中可能無法正常運作。 如果您需要支援較舊的瀏覽器,您可能需要使用 Babel 或類似的工具將程式碼轉換為更相容的版本。希望這個程式碼對您有幫助!