照片App
o1-mini
o1-mini
由 OpenAI 提供支援。 深入了解
- 官方
我想要寫一個顯示照片的app,只需要在自己電腦上的瀏覽器能執行即可,不需要靠遠端的伺服器來執行,請幫幫我。
需求如下,(另外以JavaScript語法在最後附上我的相簿位置,請注意,這僅供參考,我以後會自行增減。)
(1) 生成一個單獨而完整的html。
(2) 提供一個下拉選單,可讓我選擇不同的相簿。
(3) 相簿的照片先以縮圖方式呈現,等我進一步點選後才呈現完整的照片。
(4) 除了能讓我能單獨選擇照片外,另外提供一個"播放/暫停"按鍵,可依序自動播放所選相簿內的所有照片,同一按鍵也可以暫停相片的播放。
(5) "播放/暫停"按鍵的功能可用鍵盤的空白鍵來取代。鍵盤的左和右方向鍵,可以控制播放前一張和下一張照片。
(6) 自動播放時,照片顯示的時間可讓我指定,單位以秒計算。
(7) 注意!當處在暫停狀態時,照片會永遠顯示,也就是說照片顯示時間這個設定會跟著失效。一旦恢復播放模式,照片顯示時間才有作用。
(8) 下拉選單、播放按鍵和控制照片顯示時間的輸入這三項請固定在畫面最上方。縮圖以一條水平列呈現,固定在畫面最下方。中間大部分空白則顯示完整的圖片。注意照片下方的描述文字別被遮掉。
(9) 不要一次顯示所有的縮圖,因為萬一相簿內的照片太多的話,會延遲程式後面的操作。僅在可視畫面內顯示可選的縮圖,更多的縮圖要隨著照片的播放而動態改變。
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",
]
},
};
o1-mini
當然可以!以下是一個完整的 HTML 檔案範本,滿足您所有的需求。您可以將此代碼保存為 .html
檔案,並在您的瀏覽器中打開以運行。
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<title>個人相簿展示</title>
<style>
body {
margin: 0;
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
height: 100vh;
overflow: hidden;
}
/* 上方控制區域 */
#controls {
display: flex;
align-items: center;
padding: 10px;
background-color: #f0f0f0;
flex: 0 0 auto;
gap: 10px;
}
#controls select, #controls input {
padding: 5px;
font-size: 16px;
}
#playPauseBtn {
padding: 5px 10px;
font-size: 16px;
cursor: pointer;
}
/* 中間顯示區域 */
#displayArea {
flex: 1 1 auto;
display: flex;
justify-content: center;
align-items: center;
position: relative;
background-color: #000;
}
#displayArea img {
max-width: 100%;
max-height: 100%;
display: block;
}
#description {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
color: #fff;
background-color: rgba(0,0,0,0.5);
padding: 5px 10px;
border-radius: 5px;
}
/* 下方縮圖區域 */
#thumbnailsContainer {
flex: 0 0 120px;
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
background-color: #f8f8f8;
padding: 10px 0;
}
.thumbnail {
display: inline-block;
margin: 0 5px;
cursor: pointer;
}
.thumbnail img {
height: 100px;
width: auto;
border: 2px solid transparent;
border-radius: 5px;
}
.thumbnail.active img {
border-color: #007BFF;
}
</style>
</head>
<body>
<!-- 控制區域 -->
<div id="controls">
<label for="albumSelect">選擇相簿:</label>
<select id="albumSelect">
<option value="">-- 請選擇 --</option>
</select>
<button id="playPauseBtn">播放</button>
<label for="displayTime">顯示時間 (秒):</label>
<input type="number" id="displayTime" min="1" value="3">
</div>
<!-- 顯示區域 -->
<div id="displayArea">
<img id="fullImage" src="" alt="">
<div id="description"></div>
</div>
<!-- 縮圖區域 -->
<div id="thumbnailsContainer">
<!-- 縮圖會動態生成 -->
</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 displayTimeInput = document.getElementById('displayTime');
const displayArea = document.getElementById('displayArea');
const fullImage = document.getElementById('fullImage');
const description = document.getElementById('description');
const thumbnailsContainer = document.getElementById('thumbnailsContainer');
// 狀態變數
let currentAlbum = null;
let currentIndex = 0;
let isPlaying = false;
let playInterval = null;
// 初始化相簿選單
function initAlbumSelect() {
for (let album in sources) {
const option = document.createElement('option');
option.value = album;
option.textContent = album;
albumSelect.appendChild(option);
}
}
// 載入相簿
function loadAlbum(albumKey) {
if (!sources[albumKey]) return;
currentAlbum = sources[albumKey];
currentIndex = 0;
displayImage(currentIndex);
renderThumbnails();
}
// 顯示指定索引的照片
function displayImage(index) {
if (!currentAlbum || index < 0 || index >= currentAlbum.data.length) return;
const imgSrc = currentAlbum.path + currentAlbum.data[index];
fullImage.src = imgSrc;
fullImage.alt = currentAlbum.data[index];
description.textContent = currentAlbum.description[index] || "";
updateActiveThumbnail();
}
// 渲染縮圖
function renderThumbnails() {
thumbnailsContainer.innerHTML = '';
currentAlbum.data.forEach((img, idx) => {
const thumbDiv = document.createElement('div');
thumbDiv.classList.add('thumbnail');
thumbDiv.dataset.index = idx;
const imgElem = document.createElement('img');
imgElem.src = currentAlbum.path + img;
imgElem.alt = img;
imgElem.loading = 'lazy'; // 延遲加載
thumbDiv.appendChild(imgElem);
thumbnailsContainer.appendChild(thumbDiv);
// 點擊縮圖顯示大圖
thumbDiv.addEventListener('click', () => {
pauseSlideshow();
currentIndex = idx;
displayImage(currentIndex);
});
});
updateActiveThumbnail();
}
// 更新目前活躍的縮圖樣式
function updateActiveThumbnail() {
const thumbnails = document.querySelectorAll('.thumbnail');
thumbnails.forEach(thumb => {
thumb.classList.remove('active');
});
const activeThumb = thumbnailsContainer.querySelector(`.thumbnail[data-index="${currentIndex}"]`);
if (activeThumb) {
activeThumb.classList.add('active');
// 保持縮圖在視窗內
activeThumb.scrollIntoView({ behavior: 'smooth', inline: 'center' });
}
}
// 播放幻燈片
function playSlideshow() {
if (!currentAlbum) return;
isPlaying = true;
playPauseBtn.textContent = '暫停';
const intervalTime = parseInt(displayTimeInput.value) * 1000 || 3000;
playInterval = setInterval(() => {
currentIndex = (currentIndex + 1) % currentAlbum.data.length;
displayImage(currentIndex);
}, intervalTime);
}
// 暫停幻燈片
function pauseSlideshow() {
isPlaying = false;
playPauseBtn.textContent = '播放';
if (playInterval) {
clearInterval(playInterval);
playInterval = null;
}
}
// 切換播放/暫停
function togglePlayPause() {
if (isPlaying) {
pauseSlideshow();
} else {
playSlideshow();
}
}
// 顯示下一張
function showNextImage() {
if (!currentAlbum) return;
currentIndex = (currentIndex + 1) % currentAlbum.data.length;
displayImage(currentIndex);
}
// 顯示上一張
function showPrevImage() {
if (!currentAlbum) return;
currentIndex = (currentIndex - 1 + currentAlbum.data.length) % currentAlbum.data.length;
displayImage(currentIndex);
}
// 處理鍵盤事件
function handleKeyDown(e) {
switch (e.key) {
case ' ':
e.preventDefault(); // 防止頁面滾動
togglePlayPause();
break;
case 'ArrowRight':
pauseSlideshow();
showNextImage();
break;
case 'ArrowLeft':
pauseSlideshow();
showPrevImage();
break;
default:
break;
}
}
// 自動調整顯示時間
function adjustDisplayTime() {
if (isPlaying) {
pauseSlideshow();
playSlideshow();
}
}
// 監聽事件
albumSelect.addEventListener('change', (e) => {
const selectedAlbum = e.target.value;
if (selectedAlbum) {
loadAlbum(selectedAlbum);
pauseSlideshow();
} else {
currentAlbum = null;
displayArea.style.backgroundColor = '#000';
fullImage.src = '';
description.textContent = '';
thumbnailsContainer.innerHTML = '';
pauseSlideshow();
}
});
playPauseBtn.addEventListener('click', togglePlayPause);
displayTimeInput.addEventListener('change', adjustDisplayTime);
document.addEventListener('keydown', handleKeyDown);
// 初始化
initAlbumSelect();
</script>
</body>
</html>
html 1
說明與指引
-
保存與運行:
- 將上面的代碼複製並保存為一個
.html
檔案,例如gallery.html
。 - 確保您的相簿資料夾結構與
sources
物件中的路徑相符。 - 雙擊打開該 HTML 檔案,或在瀏覽器中使用「檔案 > 開啟」來打開它。
- 將上面的代碼複製並保存為一個
-
相簿資料結構:
sources
物件中,每個相簿名稱(如"my_hiking_1"
)是鍵,它們對應的值是包含圖片路徑、圖片檔名及描述的物件。- 路徑 (
path
): 請確保path
指向相對於 HTML 檔案的位置。例如,如果您的 HTML 檔案與相簿在同一目錄下,可能需要調整路徑。 - 圖片資料 (
data
): 為每個相簿內的圖片檔名陣列。 - 描述 (
description
): 對應於每張圖片的描述文字陣列。
-
功能說明:
- 下拉選單: 選擇不同的相簿後,將載入相應的照片和縮圖。
- 縮圖展示: 縮圖會在下方水平滾動條中顯示,並使用延遲加載(
loading="lazy"
)以優化性能。點擊縮圖會顯示大圖並暫停自動播放。 - 顯示大圖與描述: 大圖片區域中央顯示選中的圖片,下方中央顯示對應的描述文字。
- 播放/暫停按鈕: 點擊可開始或暫停自動播放。當播放時,根據您在「顯示時間」輸入框中指定的秒數自動切換到下一張圖片。
- 鍵盤控制:
- 空白鍵: 切換播放/暫停。
- 左右方向鍵: 前往上一張或下一張圖片,並暫停自動播放。
- 顯示時間設定: 您可以在「顯示時間 (秒)」輸入框中指定每張圖片顯示的時間(單位:秒)。修改此值時,如果幻燈片正在播放,將自動重新啟動播放以應用新的時間間隔。
- 縮圖載入優化: 使用
loading="lazy"
屬性來延遲加載縮圖,避免一次性加載所有縮圖導致的性能問題。
-
佈局與樣式:
- 固定控制區域與縮圖區域: 上方的控制區域和下方的縮圖區域使用
flex
佈局固定在畫面頂部和底部,中間的大圖區域佔據剩餘空間。 - 縮圖高亮顯示: 當前顯示的圖片的縮圖會有藍色邊框高亮顯示,以便識別。
- 響應式設計: 該佈局會根據視窗大小自動調整,以確保最佳觀看體驗。
- 固定控制區域與縮圖區域: 上方的控制區域和下方的縮圖區域使用
-
擴充相簿:
- 若要添加更多相簿,只需在
sources
物件中新增相應的鍵值對,格式如下:
javascript"new_album_name": { path: "../photo_galleries/new_album/", data: [ "image1.jpg", "image2.jpg", // 更多圖片 ], description: [ "image1_comment", "image2_comment", // 更多描述 ] }
- 若要添加更多相簿,只需在
-
注意事項:
- 路徑正確性: 確保每個相簿的
path
屬性正確指向存放圖片的資料夾,並且 HTML 檔案與相簿資料夾的相對路徑正確。 - 圖片格式: 上述範例使用
.jpg
格式,您可以根據實際情況使用其他格式(如.png
、.jpeg
等)。 - 安全性限制: 某些瀏覽器在本地打開 HTML 檔案時,可能會對本地文件的存取有安全限制。如果遇到圖片無法顯示的問題,請嘗試使用不同的瀏覽器或調整瀏覽器的安全設置。
- 路徑正確性: 確保每個相簿的
希望這個範本能滿足您的需求!如果有任何問題或需要進一步的自訂化,歡迎隨時詢問。