mcpField
S
svg-stroke-reveal

svg-stroke-reveal

github.com/rheinmir设计与 UI1075 次安装2 周前更新
代码仓库

关于 svg-stroke-reveal

svg-stroke-reveal 是用于网页项目的 SVG 描边显现技能,面向需要绘制动画的标志、签名、图表和路线。它提供进入视口播放一次或与滚动进度同步两种模式,并支持减少动态效果设置。

主要功能

  1. 01SVG 描边逐步显现
  2. 02进入视口时播放一次
  3. 03按滚动进度连续绘制
  4. 04支持减少动态效果设置
  5. 05使用原生 HTML、CSS 和 JS

适用场景

  1. 01标志进入视口时逐笔绘出
  2. 02签名或图标播放一次绘制动画
  3. 03路线图随页面滚动逐步显现

安装

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

$npx skills add https://github.com/rheinmir/setup --skill svg-stroke-reveal

安装后在 Claude Code 中输入/svg-stroke-reveal确认已加载。

包含的文件

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

assets/
demo.html
svg-stroke-reveal.css
svg-stroke-reveal.js

详细介绍

技能:svg-stroke-reveal

原生 HTML/CSS/JS 组件——SVG 中的 <path> 线条会像被手绘一样逐渐显现,可根据滚动经过视口的百分比绘制,也可在进入视口时绘制一次。不使用外部库(不使用 Anime.js、GSAP)。

内容

用途与背景
  • 用途: SVG 中的 <path> 线条根据滚动百分比逐渐显现,或在进入视口时绘制一次(stroke-dasharray/dashoffset),使用原生代码,不依赖外部库;默认使用 Rheinmir/uiux-asset 中未经修改的原始版本。
  • 触发条件(何时使用):
    • Logo/签名/图标需要在进入视口时呈现“逐渐绘制”的效果(只运行一次)。
    • 折线图、旅程图、路线需要随着滚动进度持续“绘制”(与实际滚动位置关联,而非只运行一次)。
    • 用户提到“滚动时绘制 SVG”“svg stroke draw”“logo 逐渐绘制”“path animation reveal”“stroke-dashoffset”或 /svg-stroke-reveal。
  • 非目标: 不要用于 7 种常见滚动效果(opacity/translate reveal、文字交错、highlight、nav 收缩、回到顶部、scrollspy、视差)——这些属于 skills/scroll-effects。不要用于尚未转换为轮廓的 <text>(见 Rules)。
思维模型

[data-svgr] > <path>×N → getTotalLength() → dasharray = dashoffset = length (隐藏) → mode "once"(IO 触发一次 + CSS transition)或 mode "scroll"(IO 开启标记 + 一个 listener 通过 rAF 根据 progress 写入 dashoffset)→ reduce-motion:立即将 dashoffset 设为 0。

输入和输出约定
字段必填?含义
输入项目实际使用的 SVG(包含带描边的 <path>)是必须先将 <text> 转换为轮廓
输入mode once 或 scroll是Logo/签名 → once;图表/旅程图 → scroll
输入项目的 design.md否如果存在,则按其修改颜色 token
输出添加了 [data-svgr] 的 SVG + 项目中的 CSS/JS是原样复制原始文件,或改造 assets/
输出playwright-verify 验证证据是滚动模式需提供滚动前/中/后的截图;once 模式需验证只触发一次
规则与能力
  • RULE-01(必须):getTotalLength() 根据 path 的内部坐标测量,不受 CSS transform 影响——但是,如果在设置 dasharray 后,通过 transform: scale(sx, sy) 缩放包含 path 的元素,且 sx != sy(两个轴缩放比例不一致),那么绘制速度在像素层面会因两个轴而产生失真,因为动画仍按原始长度运行,而显示效果已被非等比拉伸。始终通过 viewBox + width/height 设置尺寸,并保持比例一致;避免对包含 path 的元素使用非等比 CSS 缩放。
  • RULE-02(必须):<text> 无法进行描边绘制——必须先将文字/字体转换为实际的轮廓 <path>(Illustrator“Create Outlines”、Figma“Flatten”或 font-to-path 转换工具),然后才能应用 [data-svgr]。直接应用于 <text> 不会产生任何效果,因为 <text> 没有 getTotalLength()。
  • RULE-03(必须):once 模式使用 CSS transition(流畅且 CPU 开销低);scroll 模式每帧通过 JS 直接设置 dashoffset(必须如此才能与滚动位置精确同步)——不要颠倒这两种方式。
  • RULE-04(必须):每种模式各使用一个独立的 IntersectionObserver(不要把 once/scroll 的逻辑合并到同一个 observer 中,因为两者行为不同:取消观察一次 vs 持续切换标记);页面上所有 scroll 模式的 SVG 共用唯一一个经 rAF 节流的 scroll listener——不要为每个 SVG 分别添加多个 scroll listener。
  • RULE-05(必须):使用 playwright-verify 验证:滚动经过 scroll 模式的 SVG 时,截取滚动前/中/后的画面,以确认 dashoffset 逐渐减小;并断言无论多次滚入滚出视口,once 模式的 SVG 都只触发一次。
  • 能力:读取原始版本(web/git)、asset skill 和 design.md;将 HTML/CSS/JS 写入目标项目;运行无头浏览器进行验证。
失败边界
  • 应用于尚未转换为轮廓的 <text> → 不会产生任何效果:阻止执行,要求先转换为 <path>(RULE-02)。
  • 包含 path 的元素被 CSS 非等比缩放 → 绘制速度失真:失败,通过 viewBox + width/height 调整尺寸(RULE-01)。
  • 验证断言失败(dashoffset 未逐渐减小、once 再次触发)→ 失败,修复后重新验证。

操作方式

主要工作流
步骤类型输入操作输出/退出失败/后续
W01判断SVG + 要求选择 once 或 scroll 模式;检查 SVG 是否已转换为 <path>(没有 <text>)mode<text> → 转换前阻塞
W02操作原始 Pen 表格打开运行链接,将整个 .html 文件(以及 _assets/)复制到项目中,保留署名注释项目中的原始文件不允许拉取外部库 → B01
W03操作文件 + 实际 SVG + design.md只修改内容/图片/颜色(替换路径 d=)已适配的 SVG—
W04确定性通过 HTTP 运行的页面使用 playwright-verify 验证(RULE-05)截图 + 断言红色 → 修复,重复 W04
分支
ID类型条件行为跳过/失败汇合
B01必需条件分支项目不允许拉取外部库(原始版本)使用精简版 vanilla assets/(见 Reference — Assets),阅读后再适配—W04
B02必需条件分支prefers-reduced-motion: reduce初始化时立即设置 strokeDashoffset = 0,移除 observer/listener—W04
验证与停止

在 W04 中进行确定性断言(scroll 模式:经过前/中/后三张截图时,dashoffset 逐渐减小;once 模式:即使滚出再滚入,也只触发一次)。需要人工检查:流畅度、笔画顺序。断言通过后停止。

示例
  • 正向:“logo 进入屏幕时逐渐绘制” → 在 4 个 path 的 logo 上设置 data-svgr="once" → 进入视口 30% 时按顺序依次绘制(按 DOM 顺序,stagger 160ms),滚出再滚入时不重新绘制。
  • **边界/失败:**签名是使用 script 字体的 <text> → 没有 getTotalLength(),不会绘制任何内容 → 停止,要求将其转换为轮廓(Figma“Flatten”)并生成 <path>,然后再应用 [data-svgr]。
参考 — 原始版本 — 优先使用(复制整个文件,不要重写)

作者的原始完整代码(公开的 CodePen = MIT)位于外部仓库 Rheinmir/uiux-asset — 可实际运行的图库:https://rheinmir.github.io/uiux-asset/scroll-effects/ 。 流程:打开运行链接查看正确效果 → 将整个 .html 文件(以及文件引用到的 _assets/ 文件夹)复制到项目中 → 保留首行署名注释 → 只修改内容/图片/颜色。通过 HTTP 在本地运行,不要使用 file://。 如需获取完整离线版本,可运行 git clone --depth 1 https://github.com/Rheinmir/uiux-asset。

原始 Pen — 作者链接
Interactive Cicada Genomics Landing Page — alyona-mysiura运行 · 代码
Scroll-Driven SVG Map Editorial Gallery — knyttneve运行 · 代码
Scroll-Driven Godzilla Walk-and-Destroy Animation — creativeocean运行 · 代码

此技能中的 assets/ 只是手写的精简版 vanilla 实现 — 仅在项目不允许拉取外部库时使用;默认使用上述原始版本。

参考 — Assets

assets/demo.html + assets/svg-stroke-reveal.css + assets/svg-stroke-reveal.js — 阅读后适配到项目的实际 SVG 中(替换路径 d=;如有 design.md,则按其调整颜色 token),不要机械照搬。

参考 — 工作机制
  • 对 [data-svgr] 中的每个 <path>:JS 调用 path.getTotalLength(),并在初始化时将 style.strokeDasharray = length 和 style.strokeDashoffset = length 设为内联样式 → 笔画完全隐藏(虚线长度正好等于 path 长度,偏移量将整段虚线推到视野之外)。
  • data-svgr="once" 模式(仅触发一次 — Logo/签名):IntersectionObserver 的 threshold 为 0.3,进入视口时 → 将所有子 path 的 strokeDashoffset = 0 → CSS transition: stroke-dashoffset 播放一次 → 触发后立即 unobserve,即使滚动离开后再滚回来也不会重复播放。
  • data-svgr="scroll" 模式(持续进度 — 图表/旅程):IntersectionObserver 仅用于切换“位于视口内”标记;标记开启时,由经 rAF 限流的滚动监听器(共用一个监听器,不创建多个)计算 progress = (innerHeight - rect.top) / (innerHeight + rect.height),并将其限制在 0..1,然后每帧直接写入 strokeDashoffset = length * (1 - progress) — 此模式下不要使用 CSS transition(transition 会导致笔画相对于实际滚动位置滞后)。
  • 对于包含多个子 <path> 的复杂 path(多笔画 Logo、签名)— “once” 模式使用 transition-delay: calc(var(--svgr-i) * 160ms) 实现错开播放,JS 按 DOM 中 path 的顺序设置 --svgr-i(先绘制第一个 path)。
  • prefers-reduced-motion: reduce → JS 在初始化时立即将所有 path 的 strokeDashoffset = 0,并跳过两个 observer/listener — 立即显示完整笔画,不播放动画。

来源

评论

支持 Markdown