这篇文章基于我早期那篇《静态个人页面的开发》的写作结构,但内容全部按“现在仓库的真实代码”重新整理了一遍:保留“单页 + 组件化”的思路,同时补全后来迭代出来的天气背景、一言交互、资源本地化等细节。
项目地址:https://www.hxdxw.cn
技术栈:原生 HTML + CSS + JavaScript,无任何框架依赖
更新时间:2026-05-12
? 目录
目录结构
当前仓库是“可直接部署的静态产物”,根目录打开 index.html 就能运行:
www.hxdxw.cn/
├── index.html # 主页面
├── style.css # 全局样式(含暗色变量)
├── weather-bg.js # 天气背景 + 播放器主题联动
├── hitokoto.js # 一言模块(本地随机 + 复制/刷新/搜索)
├── avatar-fallback.svg # QQ 头像加载失败兜底
├── theme.js # 主题切换逻辑(当前未挂载按钮,属于预留)
├── CNAME # GitHub Pages 自定义域名
└── xf-MusicPlayer/ # 悬浮音乐播放器(本地引入)
├── js/
├── css/
├── icon/
├── images/
└── README.mdHTML 结构
页面仍然是“单页 + 组件化”的风格:把模块按功能分块放好,整体结构一眼能读懂。
下面是当前 index.html 的核心结构(做了适当删减,只保留关键模块):
<body>
<!-- 天气背景层(全屏固定) -->
<div id="weather-bg" aria-hidden="true">
<div class="weather-layer weather-gradient"></div>
<div class="weather-layer weather-clouds"></div>
<div class="weather-layer weather-particles"></div>
<div class="weather-layer weather-light"></div>
</div>
<!-- 天气状态胶囊(左上角) -->
<div id="weather-meta" class="weather-meta" aria-live="polite">正在同步天气...</div>
<script src="weather-bg.js"></script>
<!-- 头像卡片 -->
<section class="profile-wrap" aria-label="个人资料">
<div class="avatar-wrap">
<div class="bubble" aria-hidden="true">Hello World!</div>
<img class="avatar"
src="https://q1.qlogo.cn/g?b=qq&nk=915678975&s=640"
onerror="this.onerror=null;this.src='avatar-fallback.svg';"
alt="火芯Ah 的头像" />
</div>
<div class="profile-info">
<p class="profile-name">火芯Ah</p>
<p class="profile-desc">rm -rf ./个人描述</p>
</div>
</section>
<!-- 一言 -->
<div class="hitokoto-wrap" id="hitokoto-wrap">
<span id="hitokoto-text">加载中...</span>
<button class="action-btn" id="copy-btn" title="复制">...</button>
<button class="action-btn" id="refresh-btn" title="换一句">...</button>
<button class="action-btn" id="search-btn" title="搜索">...</button>
</div>
<script src="hitokoto.js"></script>
<!-- 导航按钮 -->
<nav class="nav-buttons" aria-label="站点导航">
<a class="nav-btn" href="https://blog.hxdxw.cn" target="_blank" rel="noopener noreferrer">
<span>火芯の博客</span>
</a>
<a class="nav-btn" href="https://blog.hxdxw.cn/index.php/18.html" target="_blank" rel="noopener noreferrer">
<span>火芯の在线工具</span>
</a>
</nav>
<!-- 音乐播放器 -->
<div id="xf-MusicPlayer"
data-fadeOutAutoplay
data-themeColor="xf-wineRed"
data-randomSongList="1"></div>
<script src="./xf-MusicPlayer/js/xf-MusicPlayer.min.js"></script>
</body>设计要点:
- “氛围层”与“内容层”分离:天气背景固定在最底层,内容永远清晰可读
aria-live="polite":天气状态更新时,对无障碍阅读器更友好- 头像
onerror:外链头像失效时,用本地 SVG 兜底,避免页面破相
CSS 架构
1. CSS 变量系统
CSS 依然以变量为核心:一组变量控制全局配色、阴影、动效曲线;暗色主题通过 [data-theme="dark"] 覆盖变量实现。
(下面为简化示例)
:root {
--bg: #f5f5f7;
--card-bg: #ffffff;
--text-primary: #1d1d1f;
--text-secondary: #6e6e73;
--accent: #0071e3;
--shadow-sm: 0 2px 8px rgba(0,0,0,.08);
--shadow-md: 0 8px 32px rgba(0,0,0,.12);
--transition: .3s cubic-bezier(.4,0,.2,1);
/* 天气相关变量(云层透明度可动态改) */
--weather-sky-top: #73b6ff;
--weather-sky-bottom: #d7efff;
--weather-cloud-opacity: .32;
}
[data-theme="dark"] {
--bg: #292929;
--card-bg: #393939;
--text-primary: #f5f5f5;
--text-secondary: #b0b0b0;
--accent: #0a84ff;
--shadow-sm: 0 2px 8px rgba(0,0,0,.28);
--shadow-md: 0 8px 32px rgba(0,0,0,.35);
}2. 头像卡片组件
头像卡片的“气泡 + 悬停动画”是这页最经典的交互点。实现上是纯 CSS:默认隐藏气泡,悬停时做透明度和缩放过渡。
.avatar {
width: 96px;
height: 96px;
border-radius: 50%;
object-fit: cover;
box-shadow: var(--shadow-md);
transition: transform var(--transition), box-shadow var(--transition);
}
.bubble {
opacity: 0;
transform: scale(.7) translateY(4px);
transition: opacity var(--transition), transform var(--transition);
}
.profile-wrap:hover .bubble {
opacity: 1;
transform: scale(1) translateY(0);
}3. 导航按钮
按钮保持“轻拟物”的质感:边框 + 阴影 + 轻微抬升;不做过重的玻璃拟态,保证浅色/深色都不刺眼。
4. 天气背景层
天气背景的核心是两点:
- 天空渐变通过
--weather-sky-top/bottom控制 - 云层透明度通过
--weather-cloud-opacity控制(会跟随实时云量变化)
这使得“天气变化”更多是氛围变化,而不是突兀地换一张图。
5. 一言模块
一言区域是固定在底部的一个小条,交互按钮尽量做小、做轻:不抢主视觉,但需要时能随手用。
JavaScript 功能
1. 天气同步逻辑
对应 weather-bg.js,整体链路如下:
- 尝试使用浏览器定位获取经纬度
- 请求 open-meteo 的天气接口拿到当前天气(天气码/昼夜/云量/温度)
- 把天气码归类成
晴/多云/阴/雾/雨/雪/雷雨 - 写入页面状态(
data-weather/data-daypart)并动态调整云层透明度 - 每 15 分钟刷新一次
容错策略
纯静态站点最怕依赖不稳定,所以这里做了两层兜底:
- 定位失败:回退到固定位置(北京),并在左上角状态提示原因
- 天气接口失败:回退到“默认晴天背景”
2. 一言交互逻辑
对应 hitokoto.js:
- 本地数组随机一条文案
- 复制按钮优先使用
navigator.clipboard,失败降级为选中内容 - 刷新按钮重新随机
- 搜索按钮跳转到搜索引擎查询当前文案
3. 主题切换(预留)
仓库里有 theme.js(逻辑完整,支持系统偏好 + 本地存储),但当前 index.html 还没有挂载切换按钮与脚本,所以这部分属于“预留功能”。
如果后续要启用,最小改动一般是:
- 在页面加一个
#theme-toggle按钮(以及#theme-icon) - 引入
theme.js
音乐播放器组件
播放器使用 xf-MusicPlayer,采用本地引入(仓库自带 xf-MusicPlayer/),减少外链不稳定风险。
当前页面初始化方式:
<div id="xf-MusicPlayer"
data-fadeOutAutoplay
data-themeColor="xf-wineRed"
data-randomSongList="1"></div>
<script src="./xf-MusicPlayer/js/xf-MusicPlayer.min.js"></script>另外我在 weather-bg.js 里做了一个小联动:根据天气场景动态切换播放器主题色,让整体氛围更一致。
文件结构
从“部署”的角度看,这个仓库就是典型的静态站点发布形态:根目录即产物、无需构建、资源尽量本地化。
技术总结
| 技术点 | 应用场景 |
|---|---|
| CSS Custom Properties | 全局主题与配色系统 |
[data-theme="dark"] 覆盖变量 | 暗色主题(当前预留未挂载) |
transform + transition | 头像悬停动画、按钮抬升 |
| 浏览器定位 API | 获取当前位置天气 |
| open-meteo 天气接口 | 天气码/云量/温度数据 |
navigator.clipboard | 一言复制(失败降级) |
data-* 属性 | 音乐播放器配置化 |
个人页面预览:www.hxdxw.cn
个人页面 GitHub 仓库:shihuoxin/hxdxw.github.io
xf-MusicPlayer作者github仓库:https://github.com/cenguigui/xf-MusicPlayer-master
评论区:
还没有评论,快来抢沙发吧!