哪些图标库能和morphicons一起玩?Lucide、Tabler、Heroicons兼容性清单与fitIcon跨网格适配教程
【免费下载链接】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
morphicons 是一个通用图标变形(icon morphing)库:任意描边图标可以平滑变形为另一个图标,自带弹簧物理效果、零运行时依赖、gzip 后约 7 KB。很多新手第一反应是——它支持哪些图标库?本文给出一份 Lucide、Tabler、Heroicons、Carbon 等主流图标库的兼容性清单,并手把手教你用fitIcon完成跨网格适配,让你手里的任何描边图标集都能"一起玩"。
兼容性清单速查表:哪些图标库可以直接用
判断标准很简单:图标是否描边绘制(stroke)、几何是否以数据形式提供、是否画在24×24 网格上。满足三条即可开箱即用:
| 图标库 | 网格 | 能否直接变形 | 备注 |
|---|---|---|---|
| 🎯 Lucide | 24×24 | ✅ 直接可用 | 官方示例主角,数据格式即IconNode |
| Tabler Icons | 24×24 | ✅ 直接可用 | outline 版,节点数据可直接消费 |
| Heroicons(outline) | 24×24 | ✅ 直接可用 | 仅描边版;solid 版见下方 |
| Heroicons(solid) | 20×20 | ⚠️ 需fitIcon | 填充风格,变形过程中读感不佳 |
| Iconoir | 24×24 | ✅ 直接可用 | 1.5px 描边 |
| Feather | 24×24 | ✅ 直接可用 | 官方 playground 已内置 8 个 Feather 图标 |
| Akar Icons / Untitled UI / Hugeicons | 24×24 | ✅ 直接可用 | stroke 风格可用 |
| Carbon | 32×32 | ⚠️ 需fitIcon(…, 32) | 跨网格典型代表 |
| Teenyicons | 15×15 | ⚠️ 需fitIcon(…, 15) | 小网格同样适配 |
| shadcn registry 收录的 200+ 图标库 | 视包而定 | ✅ 传d字符串 | viewBox 不是 24 时补一次fitIcon |
| ❌ Material Symbols / Bootstrap Icons / Remix Icon / Phosphor 填充版 | — | ✖️ 不建议 | 填充剪影无法按描边中心线读取 |
一句话总结:24×24 描边库直接连上;其它网格的描边库用fitIcon重定网格一次即可;填充风格图标暂不适合。
为什么必须"同网格"?理解 fitIcon 的必要性
morphicons 的对齐算法(2D Procrustes)基于"两个端点在同一坐标空间"这一前提。如果拿 24 网格的 Lucide 箭头直接配 32 网格的 Carbon 图标,缩放差会被算法误读为一次不想要的"变焦"(σ ≈ 4/3),目标图标会画出 24×24 画布之外。
这不是猜测,而是被测试钉死的结论,详见 test/viewbox.test.ts:
- 未适配:图标溢出画布、出现假缩放
- 适配后:θ ≈ 0、σ ≈ 1、残差 < 1e-9,完全全等
fitIcon 跨网格适配教程:三步搞定
第一步:确认源图标的 viewBox
打开图标库文档看viewBox:Carbon 是0 0 32 32,Teenyicons 是0 0 15 15,Heroicons solid 是0 0 20 20。
第二步:调用 fitIcon 重定到 24 网格
fitIcon按 SVG 的xMidYMid meet规则缩放 + 居中,保留宽高比,返回一个普通d字符串,可以在任何接受图标的地方使用。核心实现见 src/core/normalize.ts:
import { fitIcon } from "morphicons"; const search = fitIcon(carbonSearch, 32); // 32×32 → 24 网格 const bell = fitIcon(teenySmallBell, 15); // 15×15 → 24 网格第二个参数三种写法都支持:数字32、字符串"0 0 32 32"、数组[0, 0, 32, 32](见 test/viewbox.test.ts)。
第三步:在模块作用域只算一次
⚠️避坑关键:fitIcon放在模块顶层调用,不要放在每次渲染里——变形计划按引用缓存,复用同一引用才能命中缓存。
补充两点:
- 不传
fitIcon也不会报错(算法对相似变换不变),但目标会溢出画布,属于"能跑但不对"。 - React/Vue/Svelte 绑定默认
viewBox="0 0 24 24",可通过 props 覆盖;所以只要适配到 24 网格,一切对齐。
其它"带进来"的图标:d 字符串与 svgToIcon
除了图标包的数据导出,morphicons 还接受两种输入:
- 裸
d字符串——任何描边图标复制d属性即可,这是最通用的"万能接口",shadcn registry 里 200+ 库的<path d>都能直接喂进来。 svgToIcon适配器——Iconify 图标体、从网站复制的完整<svg>、shadcn 注册表的<path>,一次调用即可转成可用输入,且若带 viewBox 会自动调用 fitIcon 重定网格,离格收藏开箱即用。解析细节见 src/adapters/svg.ts。
import { svgToIcon } from "morphicons/adapters"; const MENU = svgToIcon(menuSvgMarkup); // 解析一次,复用引用注意它会主动拒绝"无法诚实变形"的输入:纯填充图标、带transform的元素,都会在解析期抛出清晰报错,而不是渲染出鬼画符。
新手高频问题清单
Q1:项目里已经在用 lucide-react,要换吗?
不用。MorphIcon消费的是图标数据(来自纯数据包lucide的IconNode),不是lucide-react的组件。两个包按设计共存、都能树摇,只需保持版本一致,让变形的图标和静态渲染的图标对得上。
Q2:路径数据格式有要求吗?
节点列表只认 7 种描边图元:path、line、circle、ellipse、rect、polyline、polygon;不支持<g>包裹和transform,坐标必须是字面量,其它标签会抛出明确错误(见 src/core/normalize.ts)。
Q3:描边粗细不一致怎么办?
这是观感问题而非结构问题——统一的线宽、圆头端点让变形中途的形状更"原生",这些属性写在<svg>上,由你的组件控制,morphicons 不代管。
Q4:想本地亲眼看看跨库变形?
clone 仓库(https://gitcode.com/gh_mirrors/mo/morphicons)后运行 playground,里面有 38 个真实图标(Lucide、Feather、Tabler)互相变形,并实时显示每对的 θ/σ/残差读数:
bun install bun run play # → http://localhost:3000Feather/Tabler 数据由 playground/extract-vendor-icons.mjs 从 npm 包中真实提取,生成到 playground/vendor-icons.ts。
小结
- 24×24 描边库(Lucide、Tabler、Heroicons outline、Iconoir、Feather 等):零配置,直接变。
- 其它网格的描边库(Carbon 32、Teenyicons 15、Heroicons solid 20):
fitIcon(icon, viewBox)在模块作用域适配一次即可。 - 任意来源:
d字符串或svgToIcon都能接住,填充风格图标请先换描边版。
只要图标是描边中心线 + 数据可得,morphicons 就能让它和任意其它图标互相变形——图标库的边界,就是 24 网格 +fitIcon的边界。
【免费下载链接】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),仅供参考