昨天我們實作了「凌晨兩點跨日判定」與「自動補上純白光珠」的邏輯,整個系統在基本功能方面已經差不多具備。但也因為瓶子會如實記錄親手採集與留白補發的微光,瓶底的光珠越來越多。
如果想找回上週二記錄的微光,用滑鼠在瓶子裡一顆一顆碰運氣摸索,體驗難免有些不友善。今天我們要讓操作更得心應手:在瓶子上方加上一個「時光篩選器」。選定特定日期,瓶中該日的光珠立刻聚焦亮起,其餘微光則悄然黯淡,可即時重溫那天的美好回憶!
在思考篩選功能時,直覺的做法常是「只渲染符合條件的項目,不符合的直接從 DOM 移除」。
但在這個微光採集瓶中,光珠本來就是自然隨機堆疊在瓶底,有一個具體畫面。如果選了某一天,其他光珠全消失,瓶子看起來就會突然空掉,打破了「時光積累」的視覺感。
因此我們採用「聚焦高亮」的設計:
這項功能的邏輯非常簡單,完全不需要複雜的時間運算,只需透過 Vue 的雙向綁定與動態 Class 就能完成。
<script setup> 新增篩選狀態我們需要一個狀態變數 filterDate 來記錄使用者當前挑選的日期字串,預設為空字串(代表顯示全部):
// 記錄使用者挑選的篩選日期,空字串代表顯示所有微光
const filterDate = ref('')
// 判斷某顆光珠是否應該變暗(當有選取日期,且日期不吻合時)
function isDimmed(gem) {
if (!filterDate.value) return false
return gem.date !== filterDate.value
}
// 判斷某顆光珠是否被選中
function isHighlighted(gem) {
if (!filterDate.value) return false
return gem.date === filterDate.value
}
// 清除篩選條件,重置回所有微光
function resetFilter() {
filterDate.value = ''
}
<template> 加入時光篩選列在瓶子上方放一個簡約俐落的工具列,包含原生日期選取器與重置按鈕:
<!-- 時光篩選列 -->
<div class="filter-bar">
<label for="filterDateInput" class="filter-label">時光檢索:</label>
<input
id="filterDateInput"
type="date"
v-model="filterDate"
class="filter-date-input"
/>
<button
v-if="filterDate"
class="btn-reset-filter"
@click="resetFilter"
>
顯示全部
</button>
</div>
找到瓶子內渲染光珠的 gem-dot,透過物件語法動態掛載剛才的判斷邏輯:
<div
v-for="gem in gems"
:key="gem.id"
class="gem-dot"
:class="{
'is-dimmed': isDimmed(gem),
'is-highlighted': isHighlighted(gem)
}"
:style="{
backgroundColor: gem.color,
'--offset-x': `${gem.offsetX}px`,
'--offset-y': `${gem.offsetY}px`
}"
@click="openGem(gem)"
></div>
在 <style scoped> 加入過渡與視覺變化:
/* 時光篩選列外層 */
.filter-bar {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 12px;
font-size: 0.8rem;
color: #8b949e;
}
/* 日期選擇輸入框 */
.filter-date-input {
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 6px;
color: #f0f6fc;
font-size: 0.8rem;
padding: 4px 8px;
outline: none;
cursor: pointer;
}
/* 清除篩選按鈕 */
.btn-reset-filter {
background: rgba(255, 255, 255, 0.12);
border: none;
border-radius: 6px;
color: #c9d1d9;
font-size: 0.75rem;
padding: 4px 10px;
cursor: pointer;
transition: all 0.2s ease;
}
.btn-reset-filter:hover {
background: rgba(255, 255, 255, 0.25);
color: #ffffff;
}
/* 光珠被淡化狀態 */
.gem-dot.is-dimmed {
opacity: 0.18;
filter: blur(0.5px);
transform: translate(var(--offset-x, 0), var(--offset-y, 0)) scale(0.85);
}
/* 光珠被選中狀態 */
.gem-dot.is-highlighted {
opacity: 1;
transform: translate(var(--offset-x, 0), var(--offset-y, 0)) scale(1.4);
box-shadow: 0 0 16px rgba(255, 255, 255, 0.95), 0 0 8px currentColor;
z-index: 5;
}
打開網頁並在瓶子裡擁有幾天累積的微光後:


有了時光篩選器,找尋某個特定日子的記憶已經變得輕而易舉。
但隨著光珠一顆顆填滿瓶底,我不禁在想:如果能在每個月底,把這整個月採集到的所有微小美好回憶凝聚起來,做出一張專屬於當月的「美好總結卡片」,變成可視化的成果,那一定很有紀念意義吧!
明天(Day 19),我們要為採集瓶打造「月度微光卡片」,把整個月累積的美好記憶打包封存,成為陪伴未來的力量!