diff --git a/PLAN.md b/PLAN.md index b2f830f..48f699b 100644 --- a/PLAN.md +++ b/PLAN.md @@ -4,6 +4,59 @@ 基于 Figma 设计实现一个交互式字体转 SVG 工具的 Web 应用。采用纯前端架构,使用 TypeScript + Vue3 + Vite 技术栈,在浏览器中通过 opentype.js 和 harfbuzz.js (WASM) 实现字体到 SVG 的实时转换。 +**设计来源**: [Figma 设计稿](https://www.figma.com/design/S7WVUzg3Z0DMWjYUC6dJzN/font2svg?node-id=3-5&m=dev) + +## 📋 Figma Annotations 功能需求清单 + +以下所有功能需求来自 Figma 设计中各组件的 annotation 标注: + +### 1. 文本输入与预览控制 (节点 8:94, 18:146) +- ✅ **输入框**: "此处输入内容" +- ✅ **触发方式**: 输入内容后,**回车**或者点击**"预览"按钮**生效 +- ✅ **预览按钮** (节点 18:157): 点击预览 + +### 2. 字体大小调整 (节点 7:2720) +- ✅ **滑块控件**: 文字预览大小调整 +- ✅ **实时更新**: 调整时,效果预览窗口文字大小**动态变化** + +### 3. 导出功能 (节点 23:77) +- ✅ **导出按钮**: 导出选中的预览文字的 svg 图 +- ✅ **保存位置**: 弹出保存框,默认保存在 **~/Download** +- ✅ **批量导出**: 选中多个字体时批量导出 + +### 4. 字体选择区 (节点 21:185) +- ✅ **数据源**: 从 `font/` 目录读取所有字体 +- ✅ **树状结构**: 字体按**目录树状分组** +- ✅ **展开/收拢**: 支持展开和收拢 +- ✅ **单选**: 字体支持单个选择 +- ✅ **批量框选**: 支持**鼠标批量框选**(Shift/Ctrl 多选) + +### 5. 收藏功能 +- ✅ **未收藏图标** (节点 21:200): 点击收藏该字体。**无填充**表示当前未收藏 +- ✅ **已收藏图标** (节点 21:206, 21:241): 点击取消收藏该字体。**红色填充**表示当前已收藏 +- ✅ **预览勾选** (节点 21:205, I21:205): 勾选表示在**效果预览窗口中展示** + +### 6. 已收藏字体区 (节点 8:75) +- ✅ **展示方式**: 已收藏字体展示,字体按目录树状分组,支持展开和收拢 +- ✅ **操作方式**: 字体支持单个选择,或者鼠标批量框选 +- ✅ **取消收藏**: 点击可取消收藏 +- ✅ **动态分类** (节点 21:258): 如该分类下没有选中字体,该分类删除 + +### 7. 效果预览区 (节点 8:95) +- ✅ **预览内容**: 预览窗口,内容、大小依据设置 +- ✅ **字体依据**: 字体依据字体选择勾选 +- ✅ **多字体对比**: 如勾选 2 个字体,显示内容的 2 个字体预览 + +### 8. 预览项细节 (节点 8:130-8:135) +- ✅ **字体名称** (节点 8:134): 预览字体名,取**文件名** +- ✅ **预览窗口** (节点 8:135): 某一字体预览窗口 +- ✅ **选中交互**: 点击任意区域选中或取消选中 +- ✅ **导出标记**: 选中的可以导出 +- ✅ **选择框** (节点 I23:55): 选中/未选中 + +### 9. 版权说明 (节点 5:15) +- ✅ 底部显示:@版权说明:所有字体来源互联网分享,仅供效果预览,不做下载传播,如有侵权,请告知douboer@gmail.com + ## ⚠️ 核心技术决策 **字体到 SVG 转换实现方式:TypeScript 重新实现** @@ -415,6 +468,23 @@ export async function downloadMultipleSvgs( **Figma 设计参考**: 节点 3:5 #### 3.1 状态管理 + +**⚠️ 重要性能策略:按需加载字体** + +如果 `font/` 目录有 100+ 个字体文件(总计 1-2GB),**绝对不能**在初始化时全部加载到内存。 + +**正确的加载策略**: +1. ✅ **初始化时**:只加载字体元数据(JSON,~10KB) + - 字体名称、路径、分类 + - 不加载字体文件本身 +2. ✅ **按需加载**:用户选择字体时才加载该字体文件 + - 点击预览 → 加载字体 → 生成 SVG +3. ✅ **内存缓存**:已加载的字体保存在内存中 + - 避免重复加载同一字体 +4. ✅ **可选优化**:LRU 策略限制缓存数量 + - 最多缓存 20 个字体(~200-400MB) + - 超出后清除最久未使用的字体 + ```typescript // src/stores/fontStore.ts import { defineStore } from 'pinia'; @@ -425,7 +495,7 @@ export interface FontInfo { name: string; category: string; path: string; - font?: Font; + font?: Font; // ⚠️ 注意:初始时为 undefined,按需加载 } export const useFontStore = defineStore('font', { @@ -440,7 +510,8 @@ export const useFontStore = defineStore('font', { actions: { async loadFontList() { - // 从 fonts.json 加载字体元数据 + // ⚠️ 只加载元数据 JSON,不加载字体文件 + // 这个 JSON 只有 ~10KB,包含 100+ 字体的基本信息 const response = await fetch('/fonts.json'); this.fontList = await response.json(); }, @@ -449,8 +520,10 @@ export const useFontStore = defineStore('font', { const fontInfo = this.fontList.find(f => f.id === fontId); if (!fontInfo) return; + // ⚠️ 关键:只有当字体未加载时才加载 if (!fontInfo.font) { const { loadFont } = await import('@/utils/font-loader'); + // 这里才真正加载 10-20MB 的字体文件 fontInfo.font = await loadFont(fontInfo.path); } @@ -517,6 +590,9 @@ export function useFavorites() { ``` #### 3.2 主布局组件 + +**参考**: Figma 节点 3:5 主界面布局 + annotations + ```vue