前言
在前幾天,我們陸續把「賽博紓壓診所」的排版、日夜模式、呼吸燈過場以及 SPA 單頁切換架構都搞定了!
但是大家不覺得,如果一進到首頁,每個人看到的畫面都長得一模一樣,好像少了一點「專屬感」嗎?既然這是一個幫大家解碼壓力的心理診所,我希望使用者在踏入診所的第一步,就能夠選擇自己今天的心情頭像(🐱、🐶、🦊、🐼、🦄 分別有這五種可以選擇),順便輸入 Email 來記錄長期分析。
今天我們就要來處理首頁的設定表單,用 JavaScript 把使用者的這些個人化選擇給抓下來並保存到變數裡,準備在後面的測驗結果中派上用場!
核心觀念:如何用 JS 捕捉使用者的選擇與輸入
在前端表單互動中,最常遇到的兩個需求就是:
動手寫 Code(上):頭像網格與設定表單的樣式設定
首先,我們在網頁頭部樣式區域寫好頭像選擇器的 CSS。當使用者點擊某個頭像時,我們要讓它有放大跟框線高亮的互動回饋:
[data-theme="dark"] {
--bg-color: #121212;
--card-bg: #1e1e1e;
--primary-color: #64b5f6;
--text-main: #e0e0e0;
--text-muted: #9e9e9e;
}
body {
font-family: 'Segoe UI', Microsoft JhengHei, sans-serif;
background: var(--bg-color);
color: var(--text-main);
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
transition: background 0.3s, color 0.3s;
}
.container {
width: 100%;
max-width: 600px;
padding: 20px;
}
.card {
background-color: var(--card-bg);
border-radius: var(--border-radius);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
padding: 30px;
text-align: center;
transition: background-color 0.3s;
}
/* 設定表單區塊 */
.config-section {
background: var(--bg-color);
padding: 15px;
border-radius: 12px;
margin-bottom: 20px;
text-align: left;
font-size: 0.85rem;
}
.config-section label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: var(--text-main);
}
.config-section input {
width: 100%;
padding: 8px;
border-radius: 6px;
border: 1px solid #ccc;
margin-bottom: 12px;
font-size: 0.9rem;
background: var(--card-bg);
color: var(--text-main);
box-sizing: border-box;
}
/* 頭像網格排列 */
.avatar-grid {
display: flex;
gap: 10px;
justify-content: center;
margin-bottom: 12px;
}
.avatar-option {
font-size: 1.8rem;
cursor: pointer;
padding: 5px;
border-radius: 50%;
border: 2px solid transparent;
transition: 0.2s;
}
.avatar-option.selected {
border-color: var(--primary-color);
background-color: var(--bg-color);
transform: scale(1.1);
}
.btn {
background-color: var(--primary-color);
color: white;
border: none;
border-radius: 50px;
padding: 12px 30px;
font-size: 1rem;
cursor: pointer;
width: 100%;
margin-top: 10px;
}
.hidden { display: none; }
</style>
動手寫 Code(下):首頁表單結構與資料綁定邏輯
接著在網頁主體中放入首頁的設定表單。我們透過寫好的 JavaScript 函式 selectAvatar 來切換選中狀態,並且在點擊「進入紓壓診所」時,把 Email 欄位的值抓出來存入變數:
<div class="container">
<!-- 1. 首頁區塊(含頭像與 Email 設定) -->
<div id="welcome-screen" class="card">
<h1>🧠 賽博紓壓診所與解碼器</h1>
<p>結合廟宇抽籤、能力雷達圖與惡搞病歷處方籤的頂級心靈小工具。</p>
<div class="config-section">
<label>選擇你的今日心情頭像:</label>
<div class="avatar-grid" id="avatar-container">
<div class="avatar-option selected" onclick="selectAvatar('🐱', this)">🐱</div>
<div class="avatar-option" onclick="selectAvatar('🐶', this)">🐶</div>
<div class="avatar-option" onclick="selectAvatar('🦊', this)">🦊</div>
<div class="avatar-option" onclick="selectAvatar('🐼', this)">🐼</div>
<div class="avatar-option" onclick="selectAvatar('🦄', this)">🦄</div>
</div>
<label for="user-email">📧 輸入 Email 記錄長期分析 (選填):</label>
<input type="email" id="user-email" placeholder="example@email.com (不填則為單次紀錄)">
</div>
<button class="btn" onclick="goToBreathe()">進入紓壓診所</button>
</div>
<!-- 2. 呼吸過場畫面(預設隱藏) -->
<div id="breathe-screen" class="card hidden">
<h2>🧘 調整呼吸,放鬆心情</h2>
<!-- 顯示玩家剛才選的頭像,確認有成功傳遞 -->
<div id="user-avatar-display" style="font-size: 2.5rem; margin: 15px 0;">🐱</div>
<p id="user-email-display" style="color: var(--text-muted);">尚未輸入 Email</p>
<button class="btn" onclick="restartQuiz()">返回首頁</button>
</div>
</div>
<script>
// 宣告全域變數用來儲存使用者的設定狀態
let selectedAvatarSymbol = '🐱';
let userEmailValue = '';
// 處理頭像選擇的邏輯
function selectAvatar(symbol, element) {
// 把所有頭像的 selected 樣式全部拔掉
document.querySelectorAll('.avatar-option').forEach(el => {
el.classList.remove('selected');
});
// 只幫被點擊的那個頭像加上 selected
element.classList.add('selected');
selectedAvatarSymbol = symbol;
// 同步更新結果畫面的頭像顯示
document.getElementById('user-avatar-display').innerText = symbol;
}
// 進入過場前,抓取 Email 輸入框的值並切換畫面
function goToBreathe() {
const emailInput = document.getElementById('user-email').value.trim();
userEmailValue = emailInput;
// 如果有輸入 Email 就顯示出來,沒輸入就顯示預設文字
const emailDisplay = document.getElementById('user-email-display');
if (userEmailValue) {
emailDisplay.innerText = `已綁定帳號:${userEmailValue}`;
} else {
emailDisplay.innerText = "以單次訪客身分進行測驗";
}
// 切換畫面
document.getElementById('welcome-screen').classList.add('hidden');
document.getElementById('breathe-screen').classList.remove('hidden');
}
function restartQuiz() {
document.getElementById('breathe-screen').classList.add('hidden');
document.getElementById('welcome-screen').classList.remove('hidden');
}
</script>
開發心得與架構省思
在處理這種多個選項的點擊切換時(像這次的頭像選擇),一開始常會忘記要先把同輩元素的樣式清掉,導致點到最後每個頭像都處於選中狀態。後來透過 querySelectorAll 搭配 forEach 先全部清空,再精準幫當前元素加上 selected,問題就迎刃而解了。
把使用者的輸入與選擇用變數保存下來,不僅能讓後續的畫面更有互動感,也為後面的診斷報告埋好了個人化的基礎。純前端的世界雖然沒有複雜的資料庫,但只要善用 JavaScript 的全域變數與 DOM 抓取,一樣能玩出很完整的互動體驗!
今日結語與明日預告
今天我們順利完成了首頁的心情頭像選擇與 Email 輸入綁定,讓使用者在進入測驗前就能留下個人化的設定。
明天 Day 07:第一階段總結:打造直覺流暢的溫馨首頁介面,我們要來回顧前六天所打下的基礎架構與互動視覺,為接下來重頭戲的心理測驗題目與計分邏輯做好萬全準備。我們明天見!