morphicons架构深度解析核心永不触碰DOM的冻结契约设计与7KB零依赖图标动画库是怎么炼成的【免费下载链接】morphiconsAny icon morphs into any other — universal morphing for stroke-based icons with spring physics. Zero dependencies, ~7 KB gzip.项目地址: https://gitcode.com/gh_mirrors/mo/morphiconsmorphicons是一个零依赖、约 7 KBgzip的图标变形动画库任意一个描边风格图标Lucide、Tabler、Heroicons、Iconoir 或你自己的路径都能平滑变形为任意另一个图标旋转角度无需手工声明——它从数学中自然涌现。对新手来说理解它最有价值的不是 API而是它如何用一套「核心永不触碰 DOM 的冻结契约」把同一份纯函数核心驱动 React、Vue、Svelte、React Native、Web Component 和 Canvas 六种环境。一、图标变形动画库的常见痛点为什么 morphicons 值得看大多数图标动画库要么直接对坐标做插值形状在飞行途中收缩、剪切看起来「软塌塌」要么要求你为每对图标手工声明「旋转分组」。morphicons 的做法是先用闭式解求出两个形状之间的最优相似变换旋转、缩放、平移再在其自然空间里插值。import { MorphIcon } from morphicons/react; import { Menu, X } from lucide; // 数据不是组件 button onClick{() setOpen(o !o)} aria-expanded{open} MorphIcon icon{open ? X : Menu} / /button就是全部用法没有包装器、没有AnimatePresence、没有 from/to 配对、没有配置。状态留在外面动画只是 prop 变化时组件顺带接管的实现细节。二、三层架构核心 → 驱动 → 绑定morphicons 的代码分三层这是理解「冻结契约」设计的前提┌─────────────────────────────────────────────┐ │ bindings react · vue · svelte · rn │ 薄ref createMorph │ · element ( astro SSR shell) │ ├─────────────────────────────────────────────┤ │ drivers dom (setAttribute rAF) │ 单例调度器 ├─────────────────────────────────────────────┤ │ core parse → normalize → resample │ 纯函数 │ → match → align → plan │ 无 DOM产出 │ → interpolate → serialize │ d 字符串和数字 │ spring │ └─────────────────────────────────────────────┘硬规则核心src/core/从不触碰 DOM。它是一组纯函数消费图标数据产出d字符串和数字。这条规则的直接红利React Native 绑定不是重写而是把 dom 驱动原样复用只加一个setNativeProps垫片——整个平台的差异被压缩到几行 shim。核心内部的流水线是一条单向管道图标先被归一化为三次贝塞尔曲线src/core/normalize.ts再按弧长等距重采样成固定 64 个点src/core/resample.ts之后做子路径匹配、2D Procrustes 对齐src/core/plan.ts最后按时间 t 插值并序列化为dsrc/core/interpolate.ts、src/core/serialize.ts。三、冻结契约设计整个架构的地基「冻结契约」是 docs/adr/0001-frozen-core-contracts-adapters-entry.md 记录的架构决策值得每个想写前端库的开发者细读核心只有两个结构契约进来的IconInput一个IconNode或原始d字符串出去的PathEl任何带setAttribute的东西。其他一切表现形式都不许进核心。为什么冻结决策时做过测算如果把 SVG 解析这类能力塞进核心核心会膨胀约 0.6 KB gzip每一个绑定要多付约 1.15 KB且所有消费者无论用不用都得买单。于是规则变成付费单位是 import能力放在可选的morphicons/adapters子路径后面核心、驱动和绑定永不因你没要的能力而变大契约只冻结、不生长新表现形式必须「适配」到两个契约上而不是让契约向它妥协按格式、永不经供应商没有/iconify入口永远不会有——适配器面向构造模型SVG 标记、CSS mask、canvas而非某个图标库品牌。这两个契约的精妙之处在于PathEl的结构化类型只要对象有setAttribute就能当写入目标。这就是为什么同一套驱动能写path、能写setNativeProps、能通过 adapter 写到 canvas 上。四、格式适配器三个入口三种世界所有「外来格式」都收进 src/adapters/index.ts 这一个 opt-in 入口每个 adapter 是独立模块具名 import 可被 tree-shake 到只剩自己适配器解决什么问题体积gzipsvgToIconSVG 标记 → 核心输入契约Iconify body、整段svg、shadcn 的path3.34 KBmaskTarget驱动 CSS mask 元素UnoCSS / Tailwind icons 场景DOM 里没有path0.70 KBcanvasTarget图标直接画进 2D canvas成为你拥有的像素0.48 KB几个设计细节很能说明「契约优先」的工程品味maskTarget的双缓冲机制docs/adr/0002-mask-adapter-referenced-double-buffer.md每帧把d写到隐藏的后缓冲maskpath并翻转mask-image指向。因为逐帧换 contenteditable="false">【免费下载链接】morphiconsAny icon morphs into any other — universal morphing for stroke-based icons with spring physics. Zero dependencies, ~7 KB gzip.项目地址: https://gitcode.com/gh_mirrors/mo/morphicons创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考