在博客主题的开发中,为了提升首页的视觉冲击力和互动性,我们在 Hero Splash(首屏动画)中加入了一个 “Stats Overlay”(数据统计浮层)。这个浮层用于实时显示马拉松轨迹动画过程中的关键数据(如时间、距离、配速、心率等)。
本文将深入解析这个功能的实现原理,涵盖 HTML 结构、CSS 样式设计以及 JavaScript 的交互逻辑。

1. 核心功能概述
Stats Overlay 的主要功能是在地图轨迹动画播放时,同步显示当前的运动数据。它具备以下特点:
- 动态显隐:配合轨迹动画的进度自动浮现。
- 实时更新:随着动画帧的渲染,实时计算并显示当前位置对应的数据。
- 交互性:支持折叠/展开,适配移动端展示。
2. HTML 结构设计
该功能嵌入在 layout.ejs 中,作为 #hero-splash 的一部分。结构上主要包含两部分:摘要数据区(Always Visible)和详细图表区(Collapsible)。
<div class="stats-overlay" id="stats-overlay"> <div class="stats-main-card"> <div class="stats-header"> <span class="stats-title">2024 桐庐半程马拉松</span> <button class="stats-toggle-btn" id="stats-toggle"> <i class="fas fa-chevron-up"></i> </button> </div> <div class="stats-content-wrapper" id="stats-content"> <div class="stats-summary-section"> </div>
<div class="chart-block hr-block-card"> </div>
<div class="stats-charts-section"> <canvas id="hr-chart"></canvas> <canvas id="pace-chart"></canvas> <canvas id="cadence-chart"></canvas> </div> </div> </div> </div>
|
3. CSS 样式与过渡动画
样式定义在 style.styl 中。为了实现平滑的显示效果,我们使用了 CSS Transition。
关键点在于 .stats-overlay 的初始状态和 .visible 状态的切换:
.stats-overlay position absolute top 40px right 40px background rgba(10, 10, 10, 0.95) backdrop-filter blur(20px) transition opacity 0.5s ease opacity 1 &.visible opacity 1
|
注:在实际应用中,通常会将初始 opacity 设置为 0,然后通过 JS 添加 .visible 类将其设置为 1,从而实现淡入效果。
4. JavaScript 逻辑实现
逻辑主要集中在 layout.ejs 的 <script> 标签中,核心在于 animate 函数和 DOM 的操作。
4.1 触发显示逻辑
在马拉松轨迹动画的渲染循环 animate(timestamp) 中,有一段代码专门用于控制 Overlay 的显示:
function animate(timestamp) {
const statsOverlay = document.getElementById('stats-overlay'); if (statsOverlay && !statsOverlay.classList.contains('visible')) { statsOverlay.classList.add('visible'); }
if (progress < 1) { requestAnimationFrame(animate); } }
|
这段逻辑确保了只有当轨迹动画真正开始播放时,数据浮层才会展示给用户,避免了页面加载初期的突兀感。
4.2 数据实时更新
在每一帧动画中,JS 会根据当前的动画进度(ease 变量),计算出当前应该展示的数据点:
const currentIdx = Math.floor(ease * pathArr.length);
if (currentIdx < stats.length) { const stat = stats[currentIdx]; document.getElementById('stats-time').innerText = formatTime(stat.time); document.getElementById('stats-dist').innerText = (ease * totalDist).toFixed(2); const zone = getHeartRateZone(stat.hr); const elHR = document.getElementById('stats-hr'); elHR.style.color = zone.color; }
|
4.3 整体显隐控制 (SessionStorage)
为了不打扰用户的后续访问,我们利用 sessionStorage 记录用户是否已经看过开屏动画:
const heroSplash = document.getElementById('hero-splash');
if (sessionStorage.getItem('splashVisited')) { if (heroSplash) heroSplash.style.display = 'none'; return; }
|
当用户滚动页面或触发交互时,会调用 hideSplash() 函数,将 splashVisited 标记存入 SessionStorage,并隐藏包含 Stats Overlay 在内的整个 Splash 层。
5. 总结
Stats Overlay 的实现是一个典型的前端可视化案例,它融合了:
- DOM 操作:通过 Class 切换实现样式的动态变更。
- CSS3 动画:利用
transition 实现流畅的视觉过渡。
- 数据驱动视图:基于时间轴(RequestAnimationFrame)实时更新 UI 数据。
- 用户体验优化:通过 SessionStorage 避免重复展示,尊重用户的使用习惯。
这种实现方式既保证了视觉上的酷炫感,又兼顾了性能和用户体验,非常适合用于个人博客的个性化展示。
文章作者:阿文
版权声明:本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0 许可协议。转载请注明来自
阿文的博客!