Skip to content

Repository files navigation

◈ IconFlux · 流畅的 SVG 图标形变引擎

让任意两个描边图标丝滑互变 —— 零依赖、无框架绑定、开箱即用

🌐 语言:简体中文繁體中文English

License: MIT Zero Dependencies Tests: 32 Release Size


🎉 项目介绍

IconFlux 是一个专注于「SVG 描边图标之间平滑形变(Morph)」的轻量引擎。你只需要给它两段任意的 SVG path d 数据——无论它们的点数是否相同、命令类型是否一致、子路径数量是否匹配——它都能自动算出最优对应关系,并在任意时间点吐出一段新的路径数据,从而实现菜单变关闭、播放变暂停、太阳变月亮、星星变爱心这类「一镜到底」的图标动画。

它解决的是前端动画里一个非常具体、又长期被低估的痛点:

  • 🥴 直接对坐标做线性插值会「缩、扭、穿帮」:两个图标的路径点数量不一样时甚至无法逐点对应;
  • 🧮 手工对齐关键帧极其繁琐:每一对图标都要人工数点、调旋转组,无法规模化;
  • 🪶 现有方案往往绑定框架:React/Vue 换一套就要换一套绑定,原生 HTML、小程序、Canvas 场景用不了。

✅ 自研差异化亮点

维度 IconFlux 的做法
算法路线 不走「刚体 Procrustes 对齐 + 极坐标插值」,而是 弧长等比重采样 → 环形最优对应(自动寻找最佳起点偏移与顺/逆时针方向)→ 对齐帧内线性插值,对点数、命令类型完全不敏感
多子路径 内置 形状签名匹配,放大镜(圆环+手柄)、设置(齿轮+辐条)这类多路径图标也能自动配对,多出来的子路径自动淡入/淡出
平滑无自交 采用**向心 Catmull-Rom(α=0.5)**重建三次贝塞尔,锐角五角星也不会打结
框架无关 同一份引擎同时提供 ESM / CJS / IIFE / 自定义元素 <icon-morph> / 命令行 五种用法,React、Vue、Svelte、原生 JS、Node 构建脚本都能直接用
零运行时依赖 整个引擎没有任何 dependencies,gzip 后不到 10 KB,可离线运行
离线烘焙 自带 CLI,可在构建期把形变关键帧烤成 JSON / 表格 / SVG,不占用任何运行时性能

💡 灵感来源:近期社区出现的图标形变方案(如 morphicons、bloub)验证了「任意两图标互变」这一需求的热度。IconFlux 参考了它们验证过的产品目标与使用场景,但全部代码与核心算法均为独立自研,采用了一条不同的技术路线(弧长重采样 + 环形对应),并补齐了多子路径匹配、多状态序列、离线 CLI、无框架自定义元素等能力。


✨ 核心特性

  • 🔀 任意两图标互变:自动归一化 M/L/H/V/C/S/Q/T/A/Z 全部命令,椭圆弧(A)按 SVG 规范展开为三次贝塞尔,点数不一致也能变。
  • 📏 弧长等比重采样:每个子路径统一重采样为 N 个等弧长点,从数学上保证形变过程均匀、不卡顿。
  • 🧭 最优环形对应:穷举环形起点偏移 × 顺/逆时针两种绕向,选取总位移最小的对应方案,旋转「自然涌现」,无需手工声明。
  • 🧩 多子路径自动配对:基于尺度/旋转不敏感的径向形状签名做最优二分匹配,未匹配子路径平滑淡入淡出。
  • 〰️ 两种重建风格smooth(向心 Catmull-Rom,默认,杜绝锐角自交)与 polygon(折线,端点近零误差)。
  • 🎞️ 动画控制器 + 多状态序列animateMorph 支持 7 种内置缓动、延迟、取消;morphSequence 支持 A→B→C 循环、驻留时间。
  • 🧱 <icon-morph> 自定义元素:Shadow DOM 隔离、路径对象池复用,一行标签即可用,不依赖任何框架。
  • 🖥️ 零依赖 CLIiconflux keyframes 烘焙关键帧(json/table/svg),iconflux inspect 体检路径。
  • 🪶 真零依赖 + 全格式产物:ESM、CJS、IIFE 单文件产物 + 完整 TypeScript 类型声明,gzip < 10 KB。
  • 🧪 32 个测试用例全绿:解析、几何、对应算法、形变端点保真、动画时序、CLI 全链路覆盖。
  • 可离线、可 SSR:无 DOM 环境下引擎照常工作,自定义元素仅在浏览器中注册。

🚀 快速开始

环境要求

  • 运行时:任意现代浏览器,或 Node.js ≥ 16(开发测试推荐 18/20/22)
  • 依赖:,不需要 npm install 任何第三方包

方式一:浏览器直接引入(双击 HTML 即可运行)

<svg viewBox="0 0 24 24" width="32" height="32" fill="none" stroke="currentColor" stroke-width="2">
  <path id="icon" d="M3 6h18M3 12h18M3 18h18" />
</svg>
<script src="https://cdn.jsdelivr.net/gh/gitstq/iconflux@v1.0.0/dist/iconflux.iife.js"></script>
<script>
  const close = 'M6 6l12 12M18 6L6 18';
  document.querySelector('#icon').onclick = (e) => {
    const start = e.target.getAttribute('d');
    const { animateMorph } = IconFlux;
    animateMorph(start, close, ({ d }) => e.target.setAttribute('d', d), {
      duration: 420,
      easing: 'easeInOutCubic',
    });
  };
</script>

方式二:自定义元素(最省心)

<script type="module" src="https://cdn.jsdelivr.net/gh/gitstq/iconflux@v1.0.0/dist/iconflux.esm.js"></script>
<icon-morph id="btn" size="28" stroke-width="2" duration="420"></icon-morph>
<script type="module">
  const el = document.querySelector('#btn');
  el.setInstant('M3 6h18M3 12h18M3 18h18');           // 初始:菜单
  el.morphTo('M6 6l12 12M18 6L6 18');                // 点击后:关闭
</script>

方式三:打包器 / 框架工程

# 直接从 Git 安装(无需 npm registry)
npm install git+https://github.com/gitstq/iconflux.git
# 或克隆后本地 link
// ESM(Vite / webpack / Rollup / Node ESM)
import { compileMorph, animateMorph } from 'iconflux';

// CJS
const { compileMorph } = require('iconflux');

方式四:命令行离线烘焙

npx iconflux keyframes menu.svg close.svg --steps 8 --format json
node bin/iconflux.js inspect icon.svg

方式五:最小可运行示例

git clone https://github.com/gitstq/iconflux.git
cd iconflux
npm test                 # 运行 32 个测试
node examples/node-keyframes.mjs   # 终端查看 5 帧关键帧
# 浏览器直接打开 demo/index.html(无需起服务)

📖 详细使用指南

1. 核心 API:compileMorph(srcD, dstD, options)

返回一个函数 t => { d, groups }t ∈ [0,1]

import { compileMorph } from 'iconflux';

const morph = compileMorph(menuD, closeD, {
  samples: 96,       // 每个子路径重采样点数,越大越细腻,默认 96
  output: 'smooth',  // 'smooth'(默认)| 'polygon'
});

morph(0).d;   // 等于菜单
morph(0.5).d; // 中间帧
morph(1).d;   // 等于关闭

groups 是子路径级结果数组 [{ d, opacity, closed }],多子路径淡入淡出时可分别设置透明度。

2. 参数说明

参数 类型 默认值 说明
samples number 96 每子路径弧长采样点数,范围 ≥ 8
output 'smooth' | 'polygon' 'smooth' 路径重建风格;polygon 为折线、端点近零误差
duration number 450 animateMorph 动画时长(毫秒)
delay number 0 动画延迟(毫秒)
easing string | fn 'easeInOutCubic' 线性/三次/回弹/橡皮筋等 7 种,或自定义 t=>number

可用缓动:lineareaseInOutCubiceaseOutCubiceaseInOutQuadeaseOutBackeaseInOutSineeaseOutElastic

3. 动画控制

const ctrl = animateMorph(a, b, ({ d, groups, t, eased }) => {
  path.setAttribute('d', d);
}, { duration: 500, easing: 'easeOutBack' });

await ctrl.finished;   // 结束 Promise
ctrl.cancel();         // 随时取消(Promise reject)

4. 多状态循环序列

import { morphSequence } from 'iconflux';

const seq = morphSequence([menu, close, search, heart, star], (frame) => {
  path.setAttribute('d', frame.d);
}, { loop: true, each: 600, hold: 200, easing: 'easeInOutCubic' });

seq.cancel();

5. <icon-morph> 元素 API

成员 说明
el.setInstant(d) 无动画直接设置
el.morphTo(d, opts?) 形变到新图标,返回结束 Promise;中途再次调用会从当前视觉状态续接
el.playSequence(list, opts?) 播放多状态序列,loop:true 循环
el.stopSequence() 停止序列
el.value 当前路径数据
属性 sizestroke-widthcolordurationeasingstates(配合 autoplay 自动循环)
<!-- 纯 HTML 自动循环:states 之间用两个分号 ;; 分隔 -->
<icon-morph states="M3 6h18..;;M6 6l12..;;M12 3l2.6.." autoplay size="32"></icon-morph>

6. CLI 用法

# 输出 12 帧 JSON(含 t、d、子路径数)
iconflux keyframes a.svg b.svg --steps 12 --samples 96 --output smooth --format json

# 表格:step<TAB>t<TAB>d
iconflux keyframes a.svg b.svg --steps 8 --format table

# 直接输出横向排列的 SVG 条带
iconflux keyframes a.svg b.svg --steps 6 --format svg > strip.svg

# 体检:子路径数、闭合数、命令数、包围盒
iconflux inspect icon.svg

输入既可以是 .svg/.txt 文件,也可以直接传 d 字符串,或用 - 从标准输入读取。

7. 典型场景

  • 🎛️ 开关类按钮:菜单/关闭、播放/暂停、展开/收起、锁/解锁
  • 🌗 模式切换:亮色/暗色(太阳/月亮)、列表/网格
  • ❤️ 状态反馈:收藏(星星↔爱心)、点赞、勾选
  • 🎞️ 品牌加载动画:Logo 多状态无缝循环
  • 🛠️ 构建期产物:CLI 烘焙关键帧给设计交付、Lottie/SMIL/CSS 变量使用

8. 运行截图

下图是 10 对原创图标、每对 7 个时间点的真实形变接触表(由引擎直接生成):

IconFlux morph contact sheet

交互式演示页(demo/index.html)实拍:

IconFlux live demo


💡 设计思路与迭代规划

为什么是「弧长重采样 + 环形对应」?

图标形变的本质难点是两条路径的点之间不存在天然一一对应。IconFlux 的流水线:

原始 d
  └─ 解析归一化:全部命令 → 绝对坐标的 M/L/C/Z(椭圆弧按 SVG 规范展开)
      └─ 细分扁平化:曲线按步长细分为稠密折线
          └─ 弧长重采样:每个子路径 → N 个等弧长点(闭合/开放分别处理)
              └─ 最优对应:穷举环形偏移 × 两种绕向,取总位移最小方案
                  └─ 多子路径配对:径向形状签名 + 质心距离的贪心最优匹配
                      └─ 对齐帧插值:逐点线性插值 + 缓动
                          └─ 重建输出:向心 Catmull-Rom 平滑曲线 / 折线
  • 选型理由 1:弧长参数化比「按索引等分」更符合视觉匀速,避免长线段挤点、短线段飞点。
  • 选型理由 2:环形穷举的复杂度仅 O(N²),N=96 时约 9k 次距离运算,毫秒级,却能让「箭头右转下」这类旋转自动发生。
  • 选型理由 3:向心 Catmull-Rom(α=0.5)是唯一能在锐角五角星上不产生自交环的实用选择,且无需引入任何样条库。
  • 零依赖哲学:图标库应当能被任何项目无痛引入,一个依赖都可能成为升级阻力,因此从解析器到 CLI 全部手写。

迭代路线图

  • v1.1:viewBox 差异自动归一、stroke-width 形变、子路径整体旋转插值选项
  • v1.2:Web Worker 离线程烘焙、SMIL/CSS keyframes 代码导出器
  • v1.3:React/Vue/Svelte 官方薄绑定(核心仍零依赖,绑定作为可选子路径导出)
  • v1.4:与 Lucide/Tabler/Heroicons 图标数据包的适配示例与在线 Playground
  • v2.0:填充图标(fill morph)与描边图标的混合形变

社区贡献方向

性能基准(大点数压力测试)、更多缓动曲线、图标数据集适配、无障碍(prefers-reduced-motion)策略、各框架示例仓库,欢迎在 Issue 区讨论。


📦 打包与部署指南

IconFlux 属于工具库 / 组件类项目,无需安装可执行程序;以下是完整的集成与发布说明。

构建产物

npm run build     # 零依赖构建脚本,产出 dist/:
                  # iconflux.esm.js  — ESM 单文件(打包器/现代浏览器)
                  # iconflux.cjs     — CommonJS(require)
                  # iconflux.iife.js — 浏览器全局 window.IconFlux
                  # iconflux.d.ts    — TypeScript 类型声明

构建过程不依赖 esbuild/rollup/tsc,仅用 Node 标准库拼装,保证可复现。

各环境集成

环境 推荐产物 要点
原生 HTML / CDN iconflux.iife.js 一个 <script> 即用,支持 file:// 直接双击
Vite/webpack/Rollup iconflux.esm.js package.jsonexports.import 已配置 Tree-shaking 友好
Node CJS 脚本 iconflux.cjs const { compileMorph } = require('iconflux')
TypeScript 自动加载 iconflux.d.ts 全部公共 API 均有类型
构建期离线烘焙 bin/iconflux.js 可接入 CI/Gulp/自定义流水线

版本发布

  • 遵循语义化版本(SemVer),当前 v1.0.0
  • 每个 Release 附带三份构建产物与 SHA256SUMS.txt 校验文件。
  • 校验下载产物:
sha256sum -c SHA256SUMS.txt

兼容性

  • 浏览器:支持 Custom Elements v1 / ES2020 的现代浏览器(Chrome/Edge/Firefox/Safari 近年版本均可);引擎核心在更老浏览器中也可通过 IIFE 使用。
  • Node:≥ 16(测试覆盖 18/20/22)。
  • 图标坐标系:建议统一在 24×24 viewBox 下使用;不同尺寸会按坐标直接插值,建议先归一化。

🤝 贡献指南

我们欢迎 Issue、PR 与图标示例!提交前请阅读完整的 CONTRIBUTING.md,核心约定:

  1. 提交信息遵循 Angular 规范feat: / fix: / docs: / test: / refactor: / chore:
  2. 保持零运行时依赖:新增依赖默认不接受。
  3. 新功能必须附带 node --test 测试,并同步更新三语文档与类型声明。
  4. Issue 请附上两段 d 数据、复现步骤、浏览器/Node 版本。

行为准则:保持友善、就事论事,欢迎所有水平的贡献者。


📄 开源协议

本项目基于 MIT License 开源,可自由用于个人与商业项目,保留版权声明即可。

演示目录中的 18 枚示例图标路径数据同样为项目原创、随 MIT 协议发布。

如果这个项目帮你省下了手工对齐关键帧的时间,欢迎点一个 ⭐ 支持!

⬇ 下载最新 Release问题反馈在线演示

About

◈ Fluid morphing engine for any two SVG icons — zero-dependency, framework-agnostic, arc-length resampling with optimal path correspondence. 流畅的 SVG 图标形变引擎

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages