1 篇文章带有标签 “icon-tool”

图标工具开发最佳实践与经验总结

项目:icon-tool/(Next.js 16 + React 19 + Tailwind v4) 面向设计师的公开图标工具:浏览 + 检索 + 一键导出(SVG / Sprite / 多尺寸 PNG)

一、项目背景与目标

一个给设计师用的图标工具,要解决的核心痛点是:跨库统一搜索 + 一键导出多格式。首版定位为「游客可用的公开原型」——聚合精选开源库、强搜索、一键导出,账号/云端与 AI 生成推迟到后续阶段。

首版交付范围(Phase 0–3):

  • 内置 Lucide、Tabler、Phosphor 三库共 10134 个图标(构建时抽成 public/icons.json,约 7MB)
  • 关键词搜索 + 按图标集 / 风格筛选(客户端)
  • 悬停快操作、多选、批量导出 SVG 压缩包与 SVG Sprite
  • 图标详情页 + 多尺寸 PNG 导出与复制
  • 上传 SVG、收藏(均存 localStorage

二、开发过程时间线

timeline
    title 图标工具开发时间线
    需求沟通 : 4 轮结构化提问收敛方向<br/>核心=浏览+检索+导出,技术栈/库/视觉/范围敲定
    Phase 0-1 : 脚手架 + 三库索引脚本<br/>10134 图标入仓,网格渲染 + 悬停快操作
    Phase 2-3 : 客户端搜索筛选 + 上传 + 多选批量导出
    设计升级 : 用 /前端开发 技能重做 UI<br/>暖中性画廊色 + 玻璃态 + Framer Motion
    体验迭代 : 放大图标 + 操作条移底 + 详情页 + 多尺寸 PNG
    沉淀 : 流程固化为 icon-library-bundler 技能 + 本文档

三、系统架构

graph TB
    subgraph 构建时["构建时 (CI / npm run build:icons)"]
        L["lucide-static"]
        T["@tabler/icons (outline)"]
        P["@phosphor-icons/core<br/>(regular + duotone)"]
        S["scripts/build-icons.mjs<br/>读 SVG→压缩→分类 style→索引"]
        L --> S
        T --> S
        P --> S
        S --> JSON[("public/icons.json<br/>10134 图标 · 7MB")]
    end

    subgraph 运行时["运行时 (Next.js App Router · 纯客户端)"]
        PG["app/page.tsx<br/>状态编排"]
        TB["TopBar<br/>批量操作条"]
        SB["Sidebar<br/>搜索/筛选/上传"]
        IG["IconGrid<br/>网格+骨架+空态"]
        IC["IconCard<br/>图标卡+底部操作条"]
        DP["app/icon/page.tsx<br/>详情页"]
        LD["lib/iconData.ts<br/>loadIcons / findIconById (缓存)"]
        EX["lib/export.ts<br/>SVG / Sprite / PNG"]
        LS[("localStorage<br/>收藏 / 上传")]
    end

    JSON -. "fetch 一次" .-> LD
    LD --> PG
    PG --> TB
    PG --> SB
    PG --> IG
    IG --> IC
    IC -. "双击 / 打开详情" .-> DP
    DP --> EX
    TB --> EX
    PG <--> LS

    style JSON fill:#faf9f5,stroke:#d97757,color:#141413
    style LS fill:#faf9f5,stroke:#a8a29e,color:#141413

关键架构决策:索引前置 + 纯客户端。

三库的 SVG 在构建时被抽成一份统一 JSON,前端加载后做客户端搜索与渲染,无需后端查询、无数据库、可静态部署。几千~上万个图标的规模下,fetch 一次 JSON + 内存过滤足够快。

四、关键技术流程

4.1 图标索引构建

flowchart LR
    A[扫描 node_modules<br/>各库 SVG 目录] --> B[读取每个 .svg 文本]
    B --> C[SVG 压缩<br/>去注释/多余空格/统一 currentColor]
    C --> D[归类 style<br/>line / filled / duotone]
    D --> E[组装统一记录<br/>id, set, name, style, tags, license, svg]
    E --> F[写入 public/icons.json]

统一记录结构(lib/types.ts):