我想要寫一個顯示照片的app,只需要在自己電腦上的瀏覽器能執行即可,不需要靠遠端的伺服器來執行,請幫幫我。
需求如下,我以JavaScript語法在最後附上我的相簿位置,請注意,這僅供參考,我以後會自行增減。
(1) 生成一個單獨而完整的html。
(2) 提供一個下拉選單,可讓我選擇不同的相簿。
(3) 相簿的照片先以縮圖方式呈現,等我進一步點選後才呈現完整的照片。
(4) 除了能讓我能單獨選擇照片外,另外提供一個"播放/暫停"按鍵,可依序自動播放所選相簿內的所有照片,這同一按鍵也可以暫停。
(5) "播放/暫停"按鍵的功能可用鍵盤的空白鍵來取代。
(6) 自動播放時,照片顯示的時間可讓我指定,單位以秒計算。
(7) 注意!當處在暫停狀態時,照片會永遠顯示,也就是說照片顯示時間這個設定會跟著失效。一旦恢復播放模式,照片顯示時間才有作用。
(8) 下拉選單、播放按鍵和控制照片顯示時間的輸入這三項請固定在畫面最上方。縮圖以一條水平列呈現,固定在畫面最下方。中間大部分空白則顯示完整的圖片。注意照片下方的描述文字別被遮掉,也需要安排些空間來正常顯示。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",
]
},
好的,我要寫一個照片展示的網頁應用,這個應用不需要依賴遠端的伺服器,只在本地瀏覽器上運行。我需要生成一個完整的HTML文件,並且這個HTML文件中要包含JavaScript和CSS來實現所需的功能。
首先,我需要理解需求:
- 生成一個單獨而完整的HTML:這意味著我需要將所有代碼(HTML、CSS、JavaScript)都放在一個文件中,或者至少確保它們能夠在本地運行而不需要外部依賴。
- 下拉選單選擇相簿:我需要一個下拉選單,裡面列出所有可用的相簿,比如 "my_hiking_1" 和 "my_hiking_2"。
- 縮圖展示:所選相簿中的照片要以縮圖的形式展示在頁面底部,點擊縮圖後顯示完整照片。
- 播放/暫停按鍵:這個按鍵可以啟動自動播放相簿中的照片,也可以暫停播放。同時,鍵盤的空白鍵也可以控制播放和暫停。
- 自動播放時間設定:我需要一個輸入框來設定自動播放時每張照片顯示的時間,單位是秒。
- 暫停狀態:當處於暫停狀態時,當前照片會一直顯示,直到恢復播放。
- 頁面佈局:下拉選單、播放按鍵和時間輸入框固定在頁面頂部;縮圖水平排列在頁面底部;中間部分顯示完整照片,並確保照片描述文字不被遮擋。
接下來,我需要考慮如何實現這些功能。
HTML結構:
- 頂部:包含下拉選單、播放/暫停按鍵、時間輸入框。
- 中間:顯示完整照片和描述文字。
- 底部:縮圖列表。
CSS:
- 需要設置頂部和底部的元素固定在視窗的頂部和底部。
- 中間部分需要足夠的空間來顯示照片和描述。
- 縮圖需要水平排列,可能需要使用flexbox或grid來實現。
JavaScript:
- 載入相簿數據:我需要從提供的sources對象中獲取相簿路徑和照片列表。
- 下拉選單:當選擇相簿時,載入對應的照片縮圖和描述。
- 縮圖:點擊縮圖時,顯示對應的完整照片和描述。
- 播放/暫停:實現自動播放功能,定時切換照片;暫停時停止切換。
- 鍵盤控制:監聽空白鍵來切換播放/暫停狀態。
- 時間設定:從輸入框獲取時間,設置自動播放的間隔。
現在,我開始構思代碼結構。
首先,我需要一個HTML模板,包含上述元素。
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>
<style>
/* CSS styles here */
</style>
</head>
<body>
<div id="top-bar">
<select id="album-select">
<!-- Options will be populated by JavaScript -->
</select>
<button id="play-pause">播放</button>
<input type="number" id="interval" min="1" value="3"> 秒
</div>
<div id="main-content">
<img id="full-image" src="" alt="照片">
<p id="description"></p>
</div>
<div id="thumbnail-bar">
<!-- Thumbnails will be populated by JavaScript -->
</div>
<script>
// JavaScript code here
</script>
</body>
</html>
接下來,我需要填充CSS和JavaScript。
CSS部分:
- #top-bar 固定在頂部。
- #thumbnail-bar 固定在底部,內部縮圖水平排列。
- #main-content 位於中間,顯示完整照片和描述。
我可以使用position: fixed來固定頂部和底部。
css
body {
margin: 0;
padding: 0;
overflow: hidden;
}
#top-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #f0f0f0;
padding: 10px;
z-index: 10;
}
#main-content {
position: absolute;
top: 50px; /* Adjust based on top-bar height */
bottom: 100px; /* Adjust based on thumbnail-bar height */
left: 0;
right: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: auto;
}
#full-image {
max-width: 90%;
max-height: 80%;
}
#description {
margin-top: 10px;
text-align: center;
}
#thumbnail-bar {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 100px;
background-color: #e0e0e0;
overflow-x: auto;
white-space: nowrap;
z-index: 10;
}
.thumbnail {
display: inline-block;
margin: 5px;
cursor: pointer;
}
.thumbnail img {
width: 80px;
height: 80px;
object-fit: cover;
}
JavaScript部分:
首先,我需要定義sources對象。
javascript
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"]
}
};
然後,我需要初始化下拉選單。
javascript
const albumSelect = document.getElementById('album-select');
for (let album in sources) {
let option = document.createElement('option');
option.value = album;
option.textContent = album;
albumSelect.appendChild(option);
}
接下來,當選擇相簿時,載入縮圖。
javascript
albumSelect.addEventListener('change', function() {
const selectedAlbum = this.value;
loadThumbnails(selectedAlbum);
});
loadThumbnails函數:
javascript
function loadThumbnails(album) {
const thumbnailBar = document.getElementById('thumbnail-bar');
thumbnailBar.innerHTML = '';
const albumData = sources[album];
albumData.data.forEach((photo, index) => {
const thumbDiv = document.createElement('div');
thumbDiv.className = 'thumbnail';
const img = document.createElement('img');
img.src = albumData.path + photo;
img.alt = albumData.description[index];
thumbDiv.appendChild(img);
thumbDiv.addEventListener('click', function() {
displayPhoto(album, index);
});
thumbnailBar.appendChild(thumbDiv);
});
}
displayPhoto函數:
javascript
function displayPhoto(album, index) {
const albumData = sources[album];
const fullImage = document.getElementById('full-image');
fullImage.src = albumData.path + albumData.data[index];
const description = document.getElementById('description');
description.textContent = albumData.description[index];
}
現在,實現播放/暫停功能。
我需要一個變量來追蹤當前狀態(播放或暫停),以及當前顯示的照片索引。
javascript
let isPlaying = false;
let currentAlbum = null;
let currentIndex = 0;
let intervalId = null;
播放/暫停按鍵的事件監聽:
javascript
const playPauseButton = document.getElementById('play-pause');
playPauseButton.addEventListener('click', function() {
togglePlayPause();
});
togglePlayPause函數:
javascript
function togglePlayPause() {
if (isPlaying) {
clearInterval(intervalId);
playPauseButton.textContent = '播放';
isPlaying = false;
} else {
if (currentAlbum) {
const intervalInput = document.getElementById('interval');
const intervalTime = parseInt(intervalInput.value) * 1000;
intervalId = setInterval(function() {
currentIndex = (currentIndex + 1) % sources[currentAlbum].data.length;
displayPhoto(currentAlbum, currentIndex);
}, intervalTime);
playPauseButton.textContent = '暫停';
isPlaying = true;
}
}
}
還需要處理當選擇相簿時,設置currentAlbum和currentIndex。
在loadThumbnails函數中添加:
javascript
currentAlbum = album;
currentIndex = 0;
displayPhoto(album, 0);
這樣,當選擇相簿時,會顯示第一張照片。
另外,為了讓播放從頭開始,可以在切換相簿時停止播放。
在loadThumbnails函數中添加:
javascript
if (isPlaying) {
clearInterval(intervalId);
isPlaying = false;
playPauseButton.textContent = '播放';
}
現在,實現鍵盤空白鍵控制。
javascript
document.addEventListener('keydown', function(event) {
if (event.code === 'Space') {
event.preventDefault(); // 防止頁面滾動
togglePlayPause();
}
});
最後,確保在載入頁面時,選擇第一個相簿並載入縮圖。
javascript
// 載入第一個相簿
if (albumSelect.options.length > 0) {
albumSelect.selectedIndex = 0;
loadThumbnails(albumSelect.value);
}
這樣,整個功能就基本實現了。
我還需要注意一些細節:
- 確保照片和描述的顯示不會被頂部和底部的元素遮擋。
- 縮圖的寬度可能需要調整,以適應不同數量的照片。
- 照片的路徑是相對路徑,確保在本地環境下能夠正確載入。
- 可能需要處理照片載入失敗的情況。
但基本功能已經覆蓋了需求。
現在,我將所有代碼整合到HTML文件中。
最終的HTML文件:
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>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
}
#top-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #f0f0f0;
padding: 10px;
z-index: 10;
}
#main-content {
position: absolute;
top: 50px;
bottom: 100px;
left: 0;
right: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: auto;
}
#full-image {
max-width: 90%;
max-height: 80%;
}
#description {
margin-top: 10px;
text-align: center;
}
#thumbnail-bar {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 100px;
background-color: #e0e0e0;
overflow-x: auto;
white-space: nowrap;
z-index: 10;
}
.thumbnail {
display: inline-block;
margin: 5px;
cursor: pointer;
}
.thumbnail img {
width: 80px;
height: 80px;
object-fit: cover;
}
</style>
</head>
<body>
<div id="top-bar">
<select id="album-select">
<!-- Options will be populated by JavaScript -->
</select>
<button id="play-pause">播放</button>
<input type="number" id="interval" min="1" value="3"> 秒
</div>
<div id="main-content">
<img id="full-image" src="" alt="照片">
<p id="description"></p>
</div>
<div id="thumbnail-bar">
<!-- Thumbnails will be populated by JavaScript -->
</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('album-select');
for (let album in sources) {
let option = document.createElement('option');
option.value = album;
option.textContent = album;
albumSelect.appendChild(option);
}
let isPlaying = false;
let currentAlbum = null;
let currentIndex = 0;
let intervalId = null;
albumSelect.addEventListener('change', function() {
const selectedAlbum = this.value;
loadThumbnails(selectedAlbum);
});
function loadThumbnails(album) {
if (isPlaying) {
clearInterval(intervalId);
isPlaying = false;
document.getElementById('play-pause').textContent = '播放';
}
const thumbnailBar = document.getElementById('thumbnail-bar');
thumbnailBar.innerHTML = '';
const albumData = sources[album];
albumData.data.forEach((photo, index) => {
const thumbDiv = document.createElement('div');
thumbDiv.className = 'thumbnail';
const img = document.createElement('img');
img.src = albumData.path + photo;
img.alt = albumData.description[index];
thumbDiv.appendChild(img);
thumbDiv.addEventListener('click', function() {
displayPhoto(album, index);
});
thumbnail/views.appendChild(thumbDiv);
});
currentAlbum = album;
currentIndex = 0;
displayPhoto(album, 0);
}
function displayPhoto(album, index) {
const albumData = sources[album];
const fullImage = document.getElementById('full-image');
fullImage.src = albumData.path + albumData.data[index];
const description = document.getElementById('description');
description.textContent = albumData.description[index];
currentIndex = index;
}
const playPauseButton = document.getElementById('play-pause');
playPauseButton.addEventListener('click', function() {
togglePlayPause();
});
function togglePlayPause() {
if (isPlaying) {
clearInterval(intervalId);
playPauseButton.textContent = '播放';
isPlaying = false;
} else {
if (currentAlbum) {
const intervalInput = document.getElementById('interval');
const intervalTime = parseInt(intervalInput.value) * 1000;
intervalId = setInterval(function() {
currentIndex = (currentIndex + 1) % sources[currentAlbum].data.length;
displayPhoto(currentAlbum, currentIndex);
}, intervalTime);
playPauseButton.textContent = '暫停';
isPlaying = true;
}
}
}
document.addEventListener('keydown', function(event) {
if (event.code === 'Space') {
event.preventDefault();
togglePlayPause();
}
});
// 載入第一個相簿
if (albumSelect.options.length > 0) {
albumSelect.selectedIndex = 0;
loadThumbnails(albumSelect.value);
}
</script>
</body>
</html>
這個HTML文件包含了所有必要的代碼,可以在本地瀏覽器中運行,實現了所描述的功能。
以下是針對您需求的完整解答,我將提供一個單獨的 HTML 文件,包含 HTML、CSS 和 JavaScript,實現您想要的照片展示應用,並確保它能在本地瀏覽器運行,不依賴遠端伺服器。根據您的要求,我已經設計好代碼,並使用您提供的 sources 結構作為相簿數據範例。
完整 HTML 文件
以下是完整的代碼,您可以直接複製到一個 .html 文件中(例如 photo_gallery.html),然後在瀏覽器中打開即可使用。請確保您的照片文件路徑與 sources 中的 path 相符。
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>
<style>
/* 基本樣式,重置邊距並防止滾動條干擾 */
body {
margin: 0;
padding: 0;
overflow: hidden;
font-family: Arial, sans-serif;
}
/* 頂部控制區域 */
#top-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #f0f0f0;
padding: 10px;
z-index: 10;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
#top-bar select, #top-bar button, #top-bar input {
margin-right: 10px;
padding: 5px;
}
/* 中間照片顯示區域 */
#main-content {
position: absolute;
top: 60px; /* 根據頂部高度調整 */
bottom: 110px; /* 根據底部高度調整 */
left: 0;
right: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: auto;
}
#full-image {
max-width: 90%;
max-height: 80%;
object-fit: contain;
}
#description {
margin-top: 10px;
text-align: center;
font-size: 16px;
color: #333;
}
/* 底部縮圖區域 */
#thumbnail-bar {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 100px;
background-color: #e0e0e0;
overflow-x: auto;
white-space: nowrap;
z-index: 10;
padding: 5px 0;
box-shadow: 0 -2px 5px rgba(0,0,0,0.1);
}
.thumbnail {
display: inline-block;
margin: 5px;
cursor: pointer;
}
.thumbnail img {
width: 80px;
height: 80px;
object-fit: cover;
border: 2px solid transparent;
}
.thumbnail img:hover {
border-color: #007BFF;
}
</style>
</head>
<body>
<!-- 頂部控制區域 -->
<div id="top-bar">
<select id="album-select"></select>
<button id="play-pause">播放</button>
<input type="number" id="interval" min="1" value="3"> 秒
</div>
<!-- 中間照片顯示區域 -->
<div id="main-content">
<img id="full-image" src="" alt="照片">
<p id="description"></p>
</div>
<!-- 底部縮圖區域 -->
<div id="thumbnail-bar"></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"]
}
};
// DOM 元素
const albumSelect = document.getElementById('album-select');
const playPauseButton = document.getElementById('play-pause');
const intervalInput = document.getElementById('interval');
const thumbnailBar = document.getElementById('thumbnail-bar');
const fullImage = document.getElementById('full-image');
const description = document.getElementById('description');
// 狀態變量
let isPlaying = false;
let currentAlbum = null;
let currentIndex = 0;
let intervalId = null;
// 初始化下拉選單
for (let album in sources) {
const option = document.createElement('option');
option.value = album;
option.textContent = album;
albumSelect.appendChild(option);
}
// 載入縮圖並顯示第一張照片
function loadThumbnails(album) {
// 停止當前播放
if (isPlaying) {
clearInterval(intervalId);
isPlaying = false;
playPauseButton.textContent = '播放';
}
// 清空縮圖區域
thumbnailBar.innerHTML = '';
const albumData = sources[album];
// 生成縮圖
albumData.data.forEach((photo, index) => {
const thumbDiv = document.createElement('div');
thumbDiv.className = 'thumbnail';
const img = document.createElement('img');
img.src = albumData.path + photo;
img.alt = albumData.description[index];
thumbDiv.appendChild(img);
thumbDiv.addEventListener('click', () => displayPhoto(album, index));
thumbnailBar.appendChild(thumbDiv);
});
// 設置當前相簿並顯示第一張照片
currentAlbum = album;
currentIndex = 0;
displayPhoto(album, 0);
}
// 顯示完整照片
function displayPhoto(album, index) {
const albumData = sources[album];
fullImage.src = albumData.path + albumData.data[index];
description.textContent = albumData.description[index];
currentIndex = index;
}
// 切換播放/暫停
function togglePlayPause() {
if (isPlaying) {
clearInterval(intervalId);
playPauseButton.textContent = '播放';
isPlaying = false;
} else if (currentAlbum) {
const intervalTime = parseInt(intervalInput.value) * 1000;
intervalId = setInterval(() => {
currentIndex = (currentIndex + 1) % sources[currentAlbum].data.length;
displayPhoto(currentAlbum, currentIndex);
}, intervalTime);
playPauseButton.textContent = '暫停';
isPlaying = true;
}
}
// 事件監聽
albumSelect.addEventListener('change', () => loadThumbnails(albumSelect.value));
playPauseButton.addEventListener('click', togglePlayPause);
document.addEventListener('keydown', (event) => {
if (event.code === 'Space') {
event.preventDefault(); // 防止頁面滾動
togglePlayPause();
}
});
// 初始化:載入第一個相簿
if (albumSelect.options.length > 0) {
albumSelect.selectedIndex = 0;
loadThumbnails(albumSelect.value);
}
</script>
</body>
</html>
功能說明
這個應用滿足您的所有需求,以下是每個需求的實現方式:
- 單獨完整的 HTML
所有代碼(HTML、CSS、JavaScript)都包含在一個文件中,無需外部依賴,可直接在本地瀏覽器運行。 - 下拉選單選擇相簿
頁面頂部的 <select> 元素會列出 sources 中的所有相簿(如 "my_hiking_1"、"my_hiking_2"),選擇後會載入對應縮圖。 - 縮圖展示與點擊顯示完整照片
底部水平排列的縮圖來自所選相簿,點擊縮圖會在中間區域顯示完整照片及其描述。 - 播放/暫停按鍵
"播放/暫停" 按鍵位於頂部,點擊可啟動自動播放或暫停,播放時會依序顯示相簿中的照片。 - 空白鍵控制
鍵盤的空白鍵可以切換播放與暫停狀態,實現與按鍵相同的功能。 - 自動播放時間設定
頂部的輸入框允許您指定播放間隔(單位:秒),預設為 3 秒,輸入後生效於下一次播放。 - 暫停狀態行為
當處於暫停狀態時,當前照片會持續顯示,不受播放時間影響;恢復播放後,時間設定重新生效。 - 頁面佈局
- 頂部:下拉選單、播放/暫停按鍵、時間輸入框,固定顯示。
- 中間:完整照片和描述,佔據主要空間,描述文字不會被遮擋。
- 底部:縮圖水平排列,固定在畫面底部,可左右滾動。
使用方法
- 將上述代碼保存為 photo_gallery.html。
- 確保您的照片文件位於正確的路徑(例如 ../photo_galleries/my_album_1/001.jpg),並與 sources 中的 path 和 data 匹配。
- 在瀏覽器中打開該文件(例如雙擊或拖入瀏覽器)。
- 選擇相簿、點擊縮圖查看照片,或使用播放功能自動瀏覽。
注意事項
- 照片路徑:請根據您的實際文件結構調整 sources 中的 path,目前是相對路徑。
- 相簿增減:您可以直接修改 sources 對象,新增或刪除相簿,應用會自動適應。
- 錯誤處理:如果照片路徑無效,圖片可能無法顯示,建議測試時確認路徑正確。
- 樣式調整:如需更改縮圖大小或佈局,可修改 CSS 中的 .thumbnail img 或其他樣式。
希望這個應用符合您的期待!如果有任何問題或需要進一步調整,請告訴我。