Hero 扩展手册
Hero 相关能力必须从契约层开始,再向下流向运行时与渲染层。
Hero 关键扩展点
.vitepress/utils/vitepress/api/frontmatter/hero/HeroFrontmatterApi.ts.vitepress/utils/vitepress/api/frontmatter/hero/HeroTypographyRegistryApi.ts.vitepress/utils/vitepress/api/frontmatter/hero/FloatingElementRegistryApi.ts.vitepress/utils/vitepress/runtime/hero/navAdaptiveState.ts.vitepress/theme/components/hero/background/BackgroundLayer.vue.vitepress/config/shaders/index.ts.vitepress/config/shaders/templates/base-shader.ts
新增排版风格
不要在 Hero 组件里直接新增 if styleType === ... 这样的分支。
应通过 typography registry 注册新样式,让运行时统一解析。
有两种注册方式:
- 共享内建样式
直接把定义加入
.vitepress/utils/vitepress/api/frontmatter/hero/HeroTypographyRegistryApi.ts里的DEFAULT_TYPOGRAPHY_STYLE_DEFINITIONS。 - 项目级启动注册
在一个被
.vitepress/theme/index.ts引入的启动模块里调用heroTypographyRegistry.registerStyle(...)。
canonical type 与 aliases 都要保持小写,因为 registry 会按小写规则解析。
import { heroTypographyRegistry } from "@utils/vitepress/api/frontmatter/hero";
heroTypographyRegistry.registerStyle({
type: "editorial-soft",
aliases: ["soft-editorial"],
motion: {
intensity: 0.9,
title: { x: 6, y: -4, scale: 1.03 },
text: { x: 8, y: 3, scale: 1.02 },
tagline: { x: 4, y: 6, scale: 1.01 },
image: { x: 5, y: -2, scale: 1.015 },
transitionDuration: 520,
transitionDelayStep: 36,
transitionEasing: "cubic-bezier(0.2, 0.9, 0.2, 1)",
},
});注册检查清单:
- 在
HeroTypographyRegistryApi.ts里定义 motion defaults。 - 保持 canonical type 与 aliases 为小写。
- 如果新样式需要不同的结构或 class hook,同步更新 Hero 内容组件或共享 Hero 排版 CSS。
- 通过
.vitepress/utils/vitepress/runtime/hero/typographyState.ts验证运行时解析,不要把 motion 逻辑复制到多个组件里。 - 补真实 frontmatter 示例,并更新文档。
创建新的 Hero 页面
当页面本身是入口页或落地页时,使用 Hero 页面:
---
layout: home
hero:
name: Developer Docs
text: Extend Hero, Runtime, and Nav
tagline: Contract-first configuration with shared runtime behavior
typography:
type: floating-tilt
actions:
- theme: brand
text: Hero Extension
link: /zh/doc/heroExtension
---检查清单:
- 以
layout: home开始。 - 把 Hero 配置保持在 frontmatter 中,避免页面局部组件 hack。
- 如果该页面成为主入口,同步更新文档入口页与 locale nav。
新增浮动元素类型
import { floatingElementRegistry } from "@utils/vitepress/api/frontmatter/hero";
floatingElementRegistry.registerType({
type: "keyword-chip",
renderAs: "badge",
className: "floating-keyword-chip",
});新增 Hero 特性
如果这是一个作者可配置且可复用的 Hero 特性:
- 先在
.vitepress/utils/vitepress/api/frontmatter/hero/HeroFrontmatterApi.ts中新增字段并做规范化。 - 如果它需要共享状态、定时、observer 或 viewport 逻辑,在
.vitepress/utils/vitepress/runtime/hero/**中新增或扩展运行时模块。 - 契约形状稳定后,再在对应 Hero 组件中渲染它。
- 在中英文文档树中补真实示例。
- 如果它会影响首页 Hero actions 或命名链接,也要同步更新相关导航/首页文档。
新增 Shader 预设
- 在
.vitepress/config/shaders/**下创建或扩展预设。 - 尽量复用
.vitepress/config/shaders/templates/base-shader.ts的工具函数。 - 在
.vitepress/config/shaders/index.ts中统一导出。 - 通过规范化后的 frontmatter 引用预设,而不是在页面里直接 import。
新增背景渲染器类型
- 先在
HeroFrontmatterApi.ts中加入新类型并完成规范化。 - 在
.vitepress/theme/components/hero/background/BackgroundLayer.vue中增加对应分发分支。 - 在
.vitepress/theme/components/hero/background/下创建专用渲染组件。 - 若依赖主题同步或 observer,请放入共享运行时。
- 在中英文文档树中补充真实示例。
扩展导航与搜索视觉
- 自适应计算放入
.vitepress/utils/vitepress/runtime/hero/navAdaptiveState.ts。 - 主题安全取值逻辑放入共享主题运行时。
- 若视觉需要按页面配置,优先通过 frontmatter 驱动 CSS 变量暴露给作者。
- 禁止在导航、搜索或 Hero 子组件中直接读取 DOM 主题类名。
Hero 扩展完成前检查
- 新字段或新类型已经在 API 层规范化。
- 渲染组件只消费规范化后的值。
- 主题与尺寸逻辑复用了共享运行时。
- 英中两套文档已同步。
yarn build通过后再同步到其他仓库。
注册表详解:HeroTypographyRegistry
源文件:.vitepress/utils/vitepress/api/frontmatter/hero/HeroTypographyRegistryApi.ts 单例导入:import { heroTypographyRegistry } from "@utils/vitepress/api/frontmatter/hero";
HeroTypographyRegistryApi 类管理 Hero 排版样式 —— 每种样式定义了 Hero 文字元素(title、text、tagline、image)如何响应鼠标/视窗交互产生视差运动。样式统一注册在这里,运行时通过单一查找解析,避免在各 Hero 组件里散落 if styleType === ... 分支。
内置样式
| 规范类型 | 别名 | 说明 |
|---|---|---|
"floating-tilt" | ["default"] | 默认视差效果,所有 Hero 文字节点带有倾斜运动。未指定类型或类型无法识别时自动回退到此样式。 |
"grouped-float" | — | 所有文字节点作为整体统一浮动。 |
"slanted-wrap" | — | 对角线运动模式,文字带有换行对齐。 |
"none" | ["static"] | 禁用所有运动。页面需要完全静态 Hero 时使用。 |
如果 frontmatter 指定了无法识别的类型(如 type: banana),registry 会静默回退到 "floating-tilt"。
Motion 字段说明
每种样式为四个节点目标和四个全局控制定义运动默认值:
节点级 motion(分别针对 title、text、tagline、image):
| 字段 | 类型 | 含义 |
|---|---|---|
x | number | 水平像素偏移量。正值 = 鼠标移动时元素向右偏移。 |
y | number | 垂直像素偏移量。正值 = 鼠标移动时元素向下偏移。 |
scale | number | 缩放因子。1.0 = 不缩放,1.03 = 悬停时放大 3%。 |
全局 motion 控制:
| 字段 | 类型 | 含义 |
|---|---|---|
intensity | number | 所有运动值的乘数。1.0 = 完整强度,0.5 = 半强度。 |
transitionDuration | number | 运动过渡持续时间(毫秒)。 |
transitionDelayStep | number | 各节点过渡启动之间的交错延迟(毫秒),产生级联效果。 |
transitionEasing | string | 过渡使用的 CSS 缓动函数。 |
API 方法
import { heroTypographyRegistry } from "@utils/vitepress/api/frontmatter/hero";
// 注册单个样式及其 motion 默认值
heroTypographyRegistry.registerStyle({
type: "editorial-soft",
aliases: ["soft-editorial"],
motion: {
intensity: 0.9,
title: { x: 6, y: -4, scale: 1.03 },
text: { x: 8, y: 3, scale: 1.02 },
tagline: { x: 4, y: 6, scale: 1.01 },
image: { x: 5, y: -2, scale: 1.015 },
transitionDuration: 520,
transitionDelayStep: 36,
transitionEasing: "cubic-bezier(0.2, 0.9, 0.2, 1)",
},
});
// 批量注册多个样式
heroTypographyRegistry.registerStyles([
{ type: "cinematic", motion: { /* ... */ } },
{ type: "minimal-slide", aliases: ["slide"], motion: { /* ... */ } },
]);
// 检查样式是否存在
heroTypographyRegistry.hasStyle("editorial-soft"); // true
heroTypographyRegistry.hasStyle("default"); // true(floating-tilt 的别名)
// 解析类型名称为规范形式(跟随别名,应用回退)
heroTypographyRegistry.resolveStyleType("default"); // "floating-tilt"
heroTypographyRegistry.resolveStyleType("static"); // "none"
heroTypographyRegistry.resolveStyleType("banana"); // "floating-tilt"(回退)
// 获取 motion 默认值的深拷贝副本(可安全修改)
const motion = heroTypographyRegistry.resolveMotionDefaults("floating-tilt");
motion.intensity = 0.5; // 安全 —— 这是深拷贝,不影响原始数据
// 列出所有已注册的样式类型名称
heroTypographyRegistry.listStyleTypes(); // ["floating-tilt", "grouped-float", "slanted-wrap", "none", ...]解析流程
- 读取 frontmatter
hero.typography.type(如"default")。 resolveStyleType("default")查找别名 → 得到"floating-tilt"。resolveMotionDefaults("floating-tilt")返回该样式 motion 配置的深拷贝。- 运行时将这些值应用到 Hero 文字节点,用于视差渲染。
- 如果步骤 2 中类型未知,registry 静默回退到
"floating-tilt"。
拷贝安全性:
resolveMotionDefaults始终返回新对象。组件可以自由修改返回的 motion 配置,不会影响 registry 存储的默认值。
注册表详解:FloatingElementRegistry
源文件:.vitepress/utils/vitepress/api/frontmatter/hero/FloatingElementRegistryApi.ts 单例导入:import { floatingElementRegistry } from "@utils/vitepress/api/frontmatter/hero";
FloatingElementRegistryApi 类管理浮动元素类型 —— 可出现在 Hero 区域周围的装饰性元素(徽章、图标、图片、代码片段等)。每个类型定义控制元素的渲染方式。
内置类型
| 类型 | 说明 |
|---|---|
"text" | 纯文本元素。未知类型时的默认回退。 |
"card" | 卡片式容器,可带阴影和边框。 |
"image" | 图片元素,用于 Hero 装饰。 |
"lottie" | Lottie 动画播放器。 |
"badge" | 小型标签式元素(标签、关键词)。 |
"icon" | 使用项目图标系统的图标元素。 |
"stat" | 统计数据展示(数字 + 标签)。 |
"code" | 代码片段块。 |
"shape" | 几何 SVG 形状。 |
如果 frontmatter 指定了无法识别的类型,registry 会回退到 "text"。
类型定义结构
interface FloatingElementTypeDefinition {
type: string; // 规范类型名称(小写)
renderAs?: string; // 映射到另一个类型的渲染器(如 renderAs: "badge" 使用 badge 渲染)
component?: Component; // 用于完全自定义渲染的 Vue 组件
className?: string; // 附加到浮动包装器的 CSS 类名
}renderAs:复用另一个类型的渲染器。示例:{ type: "keyword-chip", renderAs: "badge" }—— keyword-chip 元素使用 badge 渲染器渲染。component:完全覆盖渲染逻辑,使用自定义 Vue 组件。当renderAs不够用时使用。className:注入一个 CSS 类,无需自定义渲染器即可实现类型特定样式。
API 方法
import { floatingElementRegistry } from "@utils/vitepress/api/frontmatter/hero";
// 注册单个类型
floatingElementRegistry.registerType({
type: "keyword-chip",
renderAs: "badge",
className: "floating-keyword-chip",
});
// 批量注册多个类型
floatingElementRegistry.registerTypes([
{ type: "author-avatar", renderAs: "image", className: "floating-avatar" },
{ type: "live-metric", component: LiveMetricWidget },
]);
// 解析类型到其定义(未知类型返回 "text" 的定义作为回退)
const def = floatingElementRegistry.resolveType("keyword-chip");
// { type: "keyword-chip", renderAs: "badge", className: "floating-keyword-chip" }
const unknown = floatingElementRegistry.resolveType("banana");
// 返回 "text" 类型定义(回退)
// 列出所有已注册的类型名称
floatingElementRegistry.listRegisteredTypes();
// ["text", "card", "image", "lottie", "badge", "icon", "stat", "code", "shape", "keyword-chip", ...]解析流程
- 读取 frontmatter
hero.floating.items[].type(如"keyword-chip")。 resolveType("keyword-chip")查找 registry → 返回其FloatingElementTypeDefinition。- 如果类型有
renderAs,渲染器代理到该类型的视觉逻辑。 - 如果类型有
component,则挂载自定义 Vue 组件。 - 如果类型未知,registry 静默回退到
"text"定义。
注册表详解:Shader Registry
源文件:.vitepress/config/shaders/index.ts 导入路径:.vitepress/config/ 没有对应的别名。需从你的文件位置使用相对导入(如从 hero 目录下的组件使用 '../../../../config/shaders')。
Shader registry 管理 Hero 背景的 WebGL shader 预设。每个预设定义片段着色器代码和可配置参数(颜色、速度、缩放等)。预设通过名称在 frontmatter 中引用,运行时在渲染时解析。
内置 Shader 预设
| 预设名称 | 说明 |
|---|---|
water | 带波浪变形的水面动画。 |
noise | Perlin/simplex 噪声图案,带动态演化。 |
galaxy | 宇宙星场,带旋转星云效果。 |
plasma | 彩色等离子波与渐变混合。 |
ripple | 从中心向外的同心涟漪效果。 |
silk | 丝绸/织物流动动画。 |
API 函数
// 注意:@config 别名解析到 .vitepress/utils/config/,而非 .vitepress/config/。
// 必须从你的文件位置使用相对导入。
import {
listShaderTemplates,
getShaderTemplate,
getShaderTemplateByType,
registerShaderTemplate,
} from "../../../../config/shaders";
import type { ShaderTemplate } from "../../../../config/shaders";
// 列出所有已注册的 shader 预设名称
const names = listShaderTemplates();
// ["water", "noise", "galaxy", "plasma", "ripple", "silk"]
// 按名称获取 shader 模板
const silk = getShaderTemplate("silk");
// 按 type 字段获取 shader 模板
const waterShader = getShaderTemplateByType("water");
// 注册自定义 shader 预设
registerShaderTemplate({
name: "aurora",
type: "aurora",
// ... shader 配置(片段代码、uniforms、参数)
});Frontmatter 用法
hero:
background:
type: shader
shader:
preset: silk运行时读取 hero.background.shader.preset,调用 getShaderTemplate("silk") 加载 shader 配置,然后传递给 BackgroundLayer.vue 中的 WebGL 渲染器。
扩展步骤
- 创建新的 shader 文件(如
.vitepress/config/shaders/aurora.ts)。 - 复用
.vitepress/config/shaders/templates/base-shader.ts的工具函数处理通用 uniforms 和初始化。 - 通过
registerShaderTemplate(...)从.vitepress/config/shaders/index.ts导出预设。 - 在 frontmatter 中引用:
shader.preset: aurora。 - 在明暗两种主题下测试渲染 —— shader 颜色通常需要按主题调整。
导入路径警告:
@config别名解析到.vitepress/utils/config/,而不是.vitepress/config/。Shader 文件位于.vitepress/config/shaders/,因此必须使用相对路径。详见中的导入别名参考。
相关页面
- — 主题同步规范、尺寸监听规范与完整扩展 API 参考。
- — 文件职责规则、导入别名参考与分层放置指南。
- — 改动顺序、校验命令与上游同步规则。
- — 所有可用 Markdown 插件,包括 shader-effect 容器。