mcpField
P
parallax-landing-page

parallax-landing-page

github.com/hoodini设计与 UI29188 次安装5 天前更新
代码仓库

关于 parallax-landing-page

将短视频转换为单屏落地页的技能,页面通过滚动逐帧播放视频,并呈现五段交叉淡入淡出的文字场景。它指导抽取视频帧、编写页面,以及创建独立页面或集成到现有展示站点。

主要功能

  1. 01使用内置脚本抽取视频帧
  2. 02通过滚动、触控或键盘逐帧播放
  3. 03创建五段定时文字场景和最终 CTA
  4. 04创建独立页面或扩展展示站点
  5. 05使用提供的页面模板和共享资源

适用场景

  1. 01将简短产品视频制作成落地页
  2. 02为个人或野生动物视频制作电影感页面
  3. 03向 parasites 展示站点添加新页面
  4. 04基于 MP4 构建滚动逐帧体验

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/hoodini/ai-agents-skills --skill parallax-landing-page

安装后在 Claude Code 中输入/parallax-landing-page确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
hub-template.html
landing-page-template.html
parallax.js
style.css
references/
copy-guide.md
showcase-integration.md
scripts/
extract_frames.py

详细介绍

视差着陆页

将一段短视频变成一屏式的电影感着陆页:用户滚动时,视频会逐帧播放,同时五个戏剧化文字场景交替淡入淡出。文档本身不会真正滚动——JS 会拦截滚轮、触控和键盘输入,并将其转换为虚拟的帧进度。

此技能总结了随附参考示例 ../../examples/parasites/ 中验证过的模式(github / lion / hope 着陆页——三个使用此技能构建的可运行页面)。如果此处有任何含糊之处,请以该目录为准。

此技能在 YUV.AI 金字塔中的位置

parallax-landing-page 位于 YUV.AI 技能金字塔的中间层,与 yuv-design-system、yuv-decks、yuv-viral-video 和 video-to-landing-page 并列。只要需要将 5–15 秒的视频片段制作成单个主视觉滚动擦动式着陆页,顶层编排器 yuv-pilot 就会将任务路由到此处。

此技能自带视觉语言(Anton + Caveat + Inter、金色/琥珀色/强调色/奶油色点缀配色)——它不会调用 yuv-design-system。这两个系统可以共存:yuv-design-system 负责跨网页/应用/演示文稿界面的品牌配色,parallax-landing-page 则专门负责电影感滚动擦动美学。对于 YUV.AI 视差着陆页,可选择性地在页脚区域添加凤凰水印和规范的 Linktree URL,以贯穿品牌形象——水印文件见 yuv-design-system/assets/。不要将 Anton/Caveat 字体组合替换为设计系统的 Neon 配色,否则会失去标志性外观。

构建内容

每个着陆页都是一个锁定的单屏视口,包含:

  • 填满屏幕的画布,逐帧绘制视频画面(按容器尺寸缩放以覆盖画布,DPR ≤ 2)
  • 5 个绝对定位的文字场景(引导语 + 全大写 Anton 标题 + Caveat 手写风格文案),每个场景都有自己的滚动进度区间
  • 固定导航栏,包含 PARALLAX // showcase 标志和指向同系列其他着陆页的链接
  • 加载器,在允许用户交互前预加载所有帧
  • 暗角 + 胶片颗粒叠加层
  • 底部滚动提示,用户开始滚动后淡出
  • 右下角帧计数器(例如 073 / 145)
  • 最后一个场景本身就是 CTA 区域——下方不再有独立的 .end 区域

q:v 为 2 时,总体积约为每帧 120–220 KB × 帧数。6 秒、24fps 的视频片段 = 145 帧 ≈ 25 MB。10 秒的视频片段 = 241 帧 ≈ 53 MB。

保存位置

默认位置: ~/Documents/yuv-projects/landings/<slug>/——独立着陆页始终保存在此处,方便之后查找。仅当用户明确指定其他位置,或选择模式 B(集成到现有的 examples/parasites/ 展示项目)时,才覆盖此默认位置。

mkdir -p ~/Documents/yuv-projects/landings
cd ~/Documents/yuv-projects/landings
# The skill creates <slug>/ here as it extracts frames and builds the HTML.

最终路径(模式 A——独立项目):~/Documents/yuv-projects/landings/<slug>/。 最终路径(模式 B——集成项目):用户选择的现有展示项目目录。

每次构建结束时,都要告知用户最终路径。


工作流

共有四个阶段。不要跳过任何阶段——每个阶段都是下一阶段的基础。

阶段 1 — 探索

与用户确认:

  1. 视频路径 — 源 MP4 文件所在位置。
  2. Slug — 简短的文件夹/文件名(例如 hope、marcus、desk)。使用一个单词,全小写,不含空格。它将同时作为帧文件夹名(<slug>/)和 HTML 文件名(<slug>.html)。
  3. 主题 / 话题 — 这个落地页的主题是什么?产品发布?个人时刻?野生动物邂逅?你需要了解这些,才能撰写文案。
  4. 项目模式 — 独立(全新文件夹),或整合到现有的 examples/parasites/ 展示项目中(位于此仓库顶层)。如果用户说“把它加到展示项目中”,指的就是下方的模式 B。
  5. 强调色 — 用于手写文案/CTA 高亮:gold(#f5b042)、amber(#ff8a3d)、accent(粉色 #ff4d6d)、cream(#f5e9d4),或其他颜色(将其添加到 style.css 的 :root 中,并编写新的 .script.<name> 规则)。

如果用户没有指定其中某些信息,请提出默认选项并继续操作——不要因为这些他们可以在看到结果后再回答的问题而停滞不前。

阶段 2 — 提取帧

运行随附的提取脚本。脚本使用 ffprobe 检查视频,并以原生分辨率通过 -q:v 2(接近无损的 JPEG)提取每一帧,命名为 frame-001.jpg 至 frame-NNN.jpg(3 位数字,前面补零)。

python <skill>/scripts/extract_frames.py <video_path> <output_folder>

示例:

python C:/Users/User/.claude/skills/parallax-landing-page/scripts/extract_frames.py \
    C:/Users/User/Documents/parasites/hope/hope.mp4 \
    C:/Users/User/Documents/parasites/hope

脚本会向 stdout 输出一个 JSON 元数据块。请保存好它——HTML 需要用到 frame_count 和 suggested_scroll_budget。

为什么使用 -q:v 2:ezgif 等工具会大幅重新压缩(每帧约 55 KB)。原生 ffmpeg 使用 q:v 2,在相同尺寸下每帧约为 120–220 KB,画面明显更清晰。不要缩小尺寸;绝不要放大(这会增加文件体积,却不会增添细节)。

为什么采用此滚动预算公式(每帧约 26 px):这样无论片段时长如何,“每推进一帧所需滚动的像素数”都能保持一致。145 帧 → 约 4200,241 帧 → 约 6300,90 帧 → 约 2500(下限)。脚本会为你计算,并将数值限制在 [2500, 8000] 范围内。

阶段 3 — 编写页面

阅读 <skill>/assets/landing-page-template.html 中的模板。这是一个完整可用的文件,包含 {{PLACEHOLDER}} 标记,创意文案旁还有 `` 注释。将所有内容替换后,写入新文件 <target>/<slug>.html。

替换清单(必须替换每个占位符):

占位符填入内容示例
{{PAGE_TITLE}}HTML <title>Hope — The Fastest Heart in the Negev
{{PAGE_DESCRIPTION}}一句话的 meta description与 Hope 一同度过片刻,认识这只来自 Midbarium 的猎豹。
{{SLUG}}文件夹名(不含路径、不含斜杠)hope
{{FRAME_COUNT}}帧数整数241
{{FRAME_COUNTER_TEXT}}与帧数位数匹配的 001 / NNN001 / 241
{{SCROLL_BUDGET}}提取器 JSON 中的整数6300
{{PREVIEW_FRAME_MID}}补零后的中间帧编号121
{{PREVIEW_FRAME_END}}补零后的最后一帧编号241
{{LOADER_TITLE}}一个大写单词HOPE
{{LOADER_SCRIPT}}以 … 结尾的手写风格文案正在召唤奔跑者…
{{NAV_LINKS_HTML}}用于导航栏的完整 <a> 标签块见下文
{{SCENE_N_*}}5 个场景各自的引导语、标题、手写风格文案见文案指南
{{SCROLL_HINT_TEXT}}2–4 个单词的全大写提示语SCROLL TO RUN
{{CTA_BUTTONS_HTML}}2–4 个 <a class="cta"> 标签见下文
{{ACCENT_CLASS}}.script.X 和 .cta.X 的强调色后缀amber

阅读 references/copy-guide.md,了解电影感文案的写作模式(引导语措辞、标题长度、手写风格文案的语气)。文案是这项技能发挥价值的关键——即使动画再精美,泛泛的文案也会毁掉整体效果。

阶段 4 — 接入资源

如果目标文件夹中已有 style.css 和 parallax.js(展集成),则无需操作——它们是共享的。否则,将这两个文件从 <skill>/assets/ 复制到目标文件夹:

cp <skill>/assets/style.css <target>/style.css
cp <skill>/assets/parallax.js <target>/parallax.js

如果要集成到现有展集中,还需执行 references/showcase-integration.md 中的步骤——在 index.html 中添加卡片,为每个现有落地页的导航栏添加链接,并在前一个落地页的最终场景中添加链式 CTA。

告知用户如何查看:

在父文件夹中运行 python -m http.server 8000,通过此方式打开 <target>/<slug>.html(不要使用 file://——Chromium 可能会因本地图片来源污染画布)。

文件约定

<target>/
├── <slug>/                  # frame folder
│   ├── <slug>.mp4           # the source (preserved)
│   ├── frame-001.jpg
│   ├── frame-002.jpg
│   └── … frame-NNN.jpg
├── <slug>.html              # the landing page
├── style.css                # shared (copy if standalone)
├── parallax.js              # shared (copy if standalone)
└── index.html               # the hub (only if standalone or integration)

帧文件夹名称和 HTML 文件名必须使用相同的 slug——页面的 new ParallaxPage({folder: '<slug>', ...}) 调用中的 folder 选项就是字面文件夹路径。

ParallaxPage API(已在 parallax.js 中定义,不要重新定义)

new ParallaxPage({
  folder:       '<slug>',     // folder containing frame-001.jpg, etc.
  frameCount:   145,          // integer
  prefix:       'frame-',     // always 'frame-' for this skill
  scrollBudget: 4200,         // pixels of accumulated input for full pass
  // optional: padWidth (default 3), ext (default 'jpg')
})

该类会自动为 body 添加 scrub-page(通过 CSS 锁定滚动),预加载所有帧,运行由 RAF 驱动的 lerp(系数为 0.22),向由滚动位置推导出的目标帧推进,并对 data-start/data-end 范围包含当前进度的场景进行交叉淡入淡出。

硬性约束(不可妥协)

这些约束已融入参考实现,违反后会破坏体验:

  • 5 个场景,固定进度区间:0.00–0.20、0.22–0.40、0.42–0.60、0.62–0.80、0.82–1.00。场景之间故意留出 0.02 的间隔——这是每个节拍之间“只有图像、没有文字”的瞬间。首屏(场景 1)和最终场景(场景 5)分别使用 data-fade="0.30" 和 data-fade="0.18",让它们在边缘停留更久;中间场景使用默认值 0.25。
  • scrub 下方不得有 .end 区块。最终场景包含 CTA。整个页面是一个锁定的视口。
  • Anton + Caveat + Inter——所有粗体文字均使用大写 Anton,手写风格点缀(gold/amber/cream)使用 Caveat,正文引导文字使用 Inter。不得替换,也不得添加第四种字体。
  • 使用米白色 #f5f1ea,绝不使用 #fff——CSS 中已定义为 var(--text)。
  • 帧文件名采用 frame-NNN.jpg,根据总帧数补零至相同位数(由于片段少于 1000 帧,标准为 3 位;JS 会根据总数自动计算计数器位数)。
  • slug 同时作为文件夹名称和 HTML 文件名的基本名称——hope/、hope.html。不得例外;集成步骤依赖此约定。

遇到问题时的参考资料

  • 本仓库中随附的参考展集:examples/parasites/ — github.html、lion.html、hope.html、style.css、parallax.js、index.html。如果你的输出与这些示例明显不同,说明实现偏离了;请重新阅读。
  • references/copy-guide.md——如何撰写 5 个场景,让它们真正具有电影感。
  • references/showcase-integration.md——添加到现有中心页时需要进行的具体修改。
  • assets/landing-page-template.html——包含占位符的标准结构。
  • assets/hub-template.html——仅在创建全新展集时使用(从零开始添加 3 张卡片)。

两个实际调用示例

**独立页面:**用户有一个视频片段 desk.mp4,并想制作一个落地页。

  1. 询问 slug 和主题。对 desk.mp4 运行提取器 → ./desk/frame-NNN.jpg。
  2. 将 style.css 和 parallax.js 复制到项目根目录。
  3. 根据模板编写 desk.html。导航栏中只有一个链接:页面自身。
  4. 完成。告知用户使用 python -m http.server 启动服务。

**添加到展集:**用户将 hope.mp4 添加到现有的 parasites 文件夹。

  1. slug = hope。提取帧 → hope/frame-NNN.jpg。(复用现有的 style.css 和 parallax.js。)
  2. 根据模板编写 hope.html。
  3. 执行展集集成:在 index.html 中添加第三张卡片,在 github.html 和 lion.html 的导航栏中追加 Hope 链接,并在前一个落地页的最终场景中添加 Next: Hope → CTA。
  4. 如果引入新的点缀色,则将其添加到 :root,并在 style.css 中添加 .script.X 和 .cta.X 规则。

评论

支持 Markdown