Skip to content

feat(website): Hero 截图改为轮播,新增回到顶部 - #24

Merged
Leaderxin merged 3 commits into
masterfrom
feat/hero-carousel
Oct 10, 2026
Merged

Leaderxin merged 3 commits into
masterfrom
feat/hero-carousel

Conversation

@Leaderxin

Copy link
Copy Markdown
Owner

做了什么

Hero 的截图从一张改成五张的产品导览轮播,首张按你说的用日间主题(深色站点上先给一张亮色截图,应用有两套主题这件事才在第一眼说清楚)。默认不跟站点主题联动,纯手动。

轮播内容:主界面(日间)→ 主界面(夜间)→ 市场概览 → 分时 + 五档 → 指数 K 线。五张都是 2057×1466,宽高比一致,切换时轨道高度不变。

右下角新增回到顶部按钮,滚过 3/4 屏后淡入。

轮播的几个决定

  • 不自动播放。 会动的 Hero 抢走正文的注意力,而且正是 prefers-reduced-motion 想拦掉的那类动效。
  • 左右按钮常显,不做成 hover 才出现。 触摸设备没有 hover,而「看不出可以点」是轮播最常见的失败。按钮是深色玻璃底、不跟主题走 —— 它压的是截图而不是页面底色,截图本身有亮有暗,只有「深底 + 浅图标」两边都成立。
  • 非当前页设 aria-hidden。 其余几页只是被 transform 移出视野,仍在无障碍树里,不标记的话读屏会把五张截图一口气全念出来。
  • 方向键只在焦点进入轮播时才接管(监听挂在 .carousel 上而不是 document 上),否则会劫持页面本身的滚动。已测:焦点在 body 上按右键,轮播不动。
  • 触摸滑动只是加分项(按钮和圆点始终可见),判定卡严 —— 横向位移 >45px 且大于纵向 3 倍,且不调 preventDefault,竖向拖动仍然是滚动页面。
  • 圆点命中区 44×44、点与点间隔 8px,但视觉上只是 8px 的点;选中态拉成胶囊,不靠颜色一个维度表意。

回到顶部

做成 <a href="#top"> 而不是 <button>:滚动交给片段导航与 html{scroll-behavior:smooth},禁用 JS 时它照样能用,JS 只决定「滚过 3/4 屏才显示」。用锚点还顺手避开一个坑 —— 按钮版本在「滚到顶就隐藏」时若正持有焦点,会把焦点丢给 body。

顺带修掉两个布局缺陷

  1. 图片被纵向拉伸。 为防 CLS 给轮播图加了 width/height 属性,但 CSS 里只覆盖了 width,height 属性就作为定值生效了 —— 实测渲染成 1070×1466 而不是 1070×763。补上 height: auto。这个是从渲染图里看不出来的,靠量 getBoundingClientRect() 才发现。
  2. 功能图没预留宽高比,lazy 加载完会把下方内容顶下去一次。用 aspect-ratio: 2057/1466 预留,行情条那两张 344×59 的用 auto 关掉继承。

验证

  • 用 Chrome 无头实际渲染:五页逐一截图核对(含点圆点跳转、连点两次切换)、深浅两套主题、500px 移动端
  • 写了个状态测试跑 --dump-dom 抓结果,确认环绕(5→1、1→5)、aria-hidden 同步、计数器与文案更新、方向键不劫持页面
  • 对比度审计扩到 58 组全过(新增箭头图标压亮色截图 9.37:1、未选中圆点 3.08:1 等)
  • 500/620/860/1024/1440 五个宽度下 scrollWidth === clientWidth,无横向溢出
  • HTML 标签闭合、24 张图 alt 齐全、vue-tsc 与 149 个测试全绿

Hero 的截图从一张改为五张的产品导览轮播,首张是**日间主题** —— 深色站点上
先给一张亮色截图,应用有两套主题这件事才在第一眼说清楚。

轮播(无构建依赖,全部收在 app.js 的既有 IIFE 里):

- 不自动播放:会动的 Hero 抢走正文注意力,也正是 prefers-reduced-motion
  想拦掉的那类动效
- 左右按钮常显、深色玻璃底、不跟主题走 —— 触摸设备没有 hover,而「看不出
  可以点」是轮播最常见的失败;玻璃底压的是截图而非页面底色,截图本身有亮
  有暗,只有「深底 + 浅图标」两边都成立
- 非当前页设 aria-hidden:其余几页只是被 transform 移出视野,仍在无障碍树里
- 方向键监听挂在 .carousel 上而不是 document 上,否则会劫持页面本身的滚动
- 触摸滑动只作加分项,判定卡严(横向 >45px 且大于纵向 3 倍)且不 preventDefault
- 第 2–5 页 loading=lazy,加载后按空闲时机预热,否则首次切换会闪一帧空白

回到顶部做成 <a href="#top"> 而不是 <button>:滚动交给片段导航与
html{scroll-behavior:smooth},禁用 JS 时照样能用。用锚点还避开一个坑 ——
按钮版本滚到顶就隐藏,若正持有焦点会把焦点丢给 body。

顺带修掉两个布局缺陷:

- **图片被纵向拉伸。** 为防 CLS 给轮播图加了 width/height 属性,但 CSS 里
  只覆盖了 width,height 属性作为定值生效,实测渲染成 1070×1466 而不是
  1070×763。补上 height: auto
- 功能图没预留宽高比,lazy 加载完会把下方内容顶下去一次;用
  aspect-ratio: 2057/1466 预留,行情条那两张 344×59 的用 auto 关掉继承

页脚底部多留 48px:回到顶部是 fixed 的,滚到页尾会压住版权行。
轮播的左右按钮之前是写死的深色实心圆,理由写的是「它压的是截图、不是页面
底色」—— 那个理由在浅色主题下不成立,一颗黑圆钉在白页面上。改用
--surface-1 + --text-1 并保持 92% 不透明度,于是它既属于当前主题、又压得住
任何一张截图。形状同时从圆形改成圆角矩形:全站控件语言是圆角矩形,圆形
箭头是唯一的例外,也正是它显得突兀的原因。

回到顶部按钮:

- 外圈加滚动进度环,它把「离页尾还有多远」一并表达了
- 加 hover / focus-visible 的等宽气泡提示。用 ::after 读 aria-label 而不是
  title 属性 —— title 有约 1 秒延迟、样式不可控、触摸设备上根本不出现;
  这样可见文案与无障碍名称还是同一个字符串
- 位移与按压缩放合成在同一条 transform 上、靠 CSS 变量切换。分开写的话
  .is-visible 的 (0,3,0) 特异性会盖掉 :active 的 (0,2,0),按下去没有反馈
- 进度环的分母只在 load/resize 时量一次,不在 scroll 里读 scrollHeight
  (那是会触发 layout 的属性)。敢这么缓存的前提是页面高度稳定 —— 页脚
  二维码因此补上了 aspect-ratio
结构化数据(GEO 的主要抓手):一个 @graph 装 SoftwareApplication、FAQPage、
WebSite 三个节点。两条纪律 —— 字段只写事实不写形容词;FAQ 的答案与页面上
看得见的正文逐条对得上(结构化数据描述页面没有的内容属于违规,校验脚本会
同时检查 JSON 能否解析与答案是否真的出现在正文里)。

有意不写 softwareVersion:页面上没有任何静态版本号(顶栏那枚徽章是运行时
拉 shields.io 的),写死一个数字只会在下次发版后变成假信息。

head 补全:

- robots: index, follow, max-image-preview:large —— 没有最后那项,搜索结果
  只给缩略图
- og:site_name / og:locale / og:image:width|height|alt
- twitter:title / description / image
- og:image 从 main-dark 换成 main-light:缩略图尺寸下深色截图会糊成一团

robots.txt 显式放行 AI 检索类爬虫(GPTBot / ClaudeBot / PerplexityBot /
Google-Extended / Applebot-Extended)。不写也不会被默认拦(* 已放行),显式
列出的价值是这份文件同时是一份意图声明,将来要收紧只改这一处。privacy.html
带 noindex,因此刻意不写进 sitemap。

新增 llms.txt:给 AI 检索用的精简事实页(平台、体积、价格、许可、数据来源、
功能清单、常见问答)。「商业使用需获授权」写清楚了 —— PolyForm
Noncommercial 不是 MIT,答案引擎漏掉这条会误导人。
@Leaderxin
Leaderxin merged commit 41d8f25 into master Oct 10, 2026
4 checks passed
Leaderxin added a commit that referenced this pull request Oct 12, 2026
补 #24 合并时漏掉的两笔提交(合并时分支头停在 `5fc1d59`,之后推的两笔既没进主干也没跑过 CI)。

**桌面安装包瘦 1.9MB。** `public/` 是 Vite 的静态目录,会被整份复制进 `dist/`,而 `tauri.conf.json` 的 `frontendDist` 就是 `../dist` —— 那 1.9MB 营销截图一直在被打进安装包,而应用代码里一处都没引用。搬到仓库根后 `dist/` 从约 3.3MB 降到 1.4MB。`public/qrcode.png` 留在原地:`StatusBar.vue` 里写死了它的 raw.githubusercontent 地址作为二维码的远程源,本地那份是兜底。

**图片管线。** 截图出 WebP 三档(600/1100/2057)配 `<picture>` + `srcset`,落地 44–68KB(原 PNG 200–330KB,降约 75–80%);favicon 从 203KB 降到 2.3KB;og:image 换成专用 1200×630 卡片。产物提交进仓库,CI 不需要浏览器 —— 只有换截图时才手动跑 `npm run site:images`。

**SEO/GEO 收尾。** `robots.txt` 与 `llms.txt` 移到新建的 Leaderxin/leaderxin.github.io(协议规定两者只在域名根被读取);`sitemap.xml` 改由脚本按实际页面生成;引用校验扩展到所有页面并覆盖 `srcset`;H1 带上品类词、description 99→75 字、JSON-LD 补 `sameAs`;新增 `404.html`。

三个实测踩出来的坑记在脚本注释里:`file://` 下 canvas 会被 taint(要 `--allow-file-access-from-files`);目标宽 > 源宽时必须整个跳过而不是按目标宽命名(`settings-index.png` 只有 1298px,否则 srcset 描述符会撒谎);`background-clip: text` 会静默吃掉溢出元素框的字形。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant