11 KiB
11 KiB
Icon Manager 图标管理器文档
本文档详细描述 Icon Manager 图标管理工具的实现细节,包括 API、使用方式、图标清单等,供 AI 根据文档重现功能。
1. 工具概述
1.1 基本信息
- 工具名称:
IconManager - 文件路径:
src/utils/icon-manager.ts - 导出函数:
getIcon(name: string): string - 用途: 统一管理所有 SVG 图标资源,提供通过名称获取图标的接口
- 特点: 单一职责,简单易用,支持默认图标回退
1.2 设计目标
- 统一管理: 所有图标集中在一个文件中管理,避免重复和不一致
- 简化使用: 通过简单的函数调用获取图标,无需在各处重复 SVG 代码
- 类型安全: SVG 作为字符串存储,可直接用于 innerHTML 或图标属性
- 容错机制: 当请求的图标不存在时,返回默认图标而不是报错
2. API 文档
2.1 getIcon 函数
function getIcon(name: string): string
参数:
name: string - 图标名称(中文)
返回值:
- string - SVG 图标的完整字符串
行为:
- 从
ICONS对象中查找对应名称的图标 - 如果找到,返回该图标的 SVG 字符串
- 如果未找到,在控制台输出警告并返回默认图标
示例:
import { getIcon } from '../../utils/icon-manager';
// 获取测量图标
const measureIcon = getIcon('测量');
// 获取不存在的图标(会返回默认图标并警告)
const unknownIcon = getIcon('不存在的图标');
// 控制台输出: [IconManager] Icon "不存在的图标" not found, using default icon
3. 图标清单
3.1 来自 assets 的图标 (48x48)
这些图标从 src/assets/ 目录中的 SVG 文件简化而来,用于 toolbar 和主要功能按钮:
| 图标名称 | 用途 | 原始文件 |
|---|---|---|
| 测量 | 测量工具 | 测量.svg |
| 地图 | 地图视图/平面图 | 地图.svg |
| 框选放大 | 框选缩放 | 框选放大.svg |
| 漫游 | 漫游模式 | 漫游.svg |
| 目录树 | 构件树 | 目录树.svg |
| 剖切 | 剖切菜单 | 剖切.svg |
| 剖切盒 | 剖切盒 | 剖切盒.svg |
| 全屏 | 全屏模式 | 全屏.svg |
| 设置 | 设置面板 | 设置.svg |
| 拾曲面剖切 | 拾取曲面剖切 | 拾曲面剖切.svg |
| 轴向剖切 | 轴向剖切 | 轴向剖切.svg |
| 主视角 | 主视角/首页 | 主视角.svg |
| 文档 | 文档/属性 | 地图 – 1.svg |
3.2 测量相关图标 (32x32)
用于测量面板的各种测量方式:
| 图标名称 | 用途 |
|---|---|
| 标高 | 标高测量 |
| 距离 | 距离测量 |
| 最小距离 | 最小距离测量 |
| 激光边距 | 激光边距测量 |
| 角度 | 角度测量 |
| 坡度 | 坡度测量 |
| 体积 | 体积测量 |
| 空间体积 | 空间体积测量 |
3.3 通用图标 (24x24)
常用的 UI 图标:
| 图标名称 | 用途 |
|---|---|
| close | 关闭 |
| check | 勾选/确认 |
| warning | 警告 |
| error | 错误 |
| success | 成功 |
| plus | 加号/新增 |
| minus | 减号/删除 |
| arrowUp | 向上箭头 |
| arrowDown | 向下箭头 |
| arrowLeft | 向左箭头 |
| arrowRight | 向右箭头 |
| search | 搜索 |
| refresh | 刷新 |
| delete | 删除 |
| edit | 编辑 |
| save | 保存 |
| expand | 展开 |
| collapse | 收起 |
3.4 默认图标
| 图标名称 | 用途 |
|---|---|
| default | 当请求的图标不存在时返回 |
4. 使用场景
4.1 在按钮配置中使用
import { getIcon } from '../../../utils/icon-manager';
export const createMeasureButton = (engine: BimEngine): ButtonConfig => {
return {
id: 'measure',
groupId: 'group-1',
type: 'button',
label: 'toolbar.measure',
icon: getIcon('测量'), // 使用图标管理器
onClick: () => {
engine.measure?.show();
}
};
};
4.2 在组件中使用
import { getIcon } from '../../utils/icon-manager';
export class WalkControlPanel implements IBimComponent {
private getIconSVG(type: string): string {
const icons: Record<string, string> = {
'plan-view': getIcon('地图'),
'path': getIcon('地图'),
'walk': getIcon('漫游')
};
return icons[type] || '';
}
private createIconButton(type: string, onClick: () => void): HTMLButtonElement {
const btn = document.createElement('button');
btn.className = `walk-icon-btn walk-icon-btn-${type}`;
btn.innerHTML = this.getIconSVG(type);
btn.addEventListener('click', onClick);
return btn;
}
}
4.3 在树节点中使用
import { getIcon } from '../../utils/icon-manager';
const treeData: TreeNodeConfig[] = [
{
id: 'level-1',
label: '一层',
icon: getIcon('目录树'),
children: [...]
}
];
5. SVG 简化规范
5.1 简化原则
从 assets 目录中的 SVG 文件简化时,遵循以下原则:
- 保留核心路径:只保留
<path>元素及其d属性 - 移除冗余属性:删除
<defs>,<clipPath>,<style>,<g>等非必要元素 - 保持颜色属性:保留
fill="currentColor"以支持主题颜色 - 统一尺寸:根据用途设置合适的
viewBox和width/height - 简化变换:如果有
transform,尽量简化或合并到路径中
5.2 简化示例
原始 SVG (从 assets/测量.svg):
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48" viewBox="0 0 48 48">
<defs>
<clipPath id="clip-path">
<rect width="48" height="48" fill="none"/>
</clipPath>
</defs>
<g id="测量" clip-path="url(#clip-path)">
<path d="M0,28.207H3.429v3.526H44.571V28.207H48v7.052H0ZM0,3.526v14.1a3.478,3.478,0,0,0,3.429,3.526H6.857V17.629h3.429v3.526h3.429V17.629h3.429v3.526h3.429V10.578H24V21.155h3.429V17.629h3.429v3.526h3.429V17.629h3.429v3.526h3.429V10.578h3.429V21.155A3.478,3.478,0,0,0,48,17.629V3.526A3.478,3.478,0,0,0,44.571,0H3.429A3.478,3.478,0,0,0,0,3.526Z" transform="translate(0 5.456)" fill="#000"/>
</g>
</svg>
简化后 (在 icon-manager.ts 中):
测量: '<svg width="48" height="48" viewBox="0 0 48 48"><path fill="currentColor" d="M0,28.207H3.429v3.526H44.571V28.207H48v7.052H0ZM0,3.526v14.1a3.478,3.478,0,0,0,3.429,3.526H6.857V17.629h3.429v3.526h3.429V17.629h3.429v3.526h3.429V10.578H24V21.155h3.429V17.629h3.429v3.526h3.429V17.629h3.429v3.526h3.429V10.578h3.429V21.155A3.478,3.478,0,0,0,48,17.629V3.526A3.478,3.478,0,0,0,44.571,0H3.429A3.478,3.478,0,0,0,0,3.526Z" transform="translate(0 5.456)"/></svg>',
关键变化:
- 移除了
xmlns,xmlns:xlink,<defs>,<clipPath>,<g>等 - 将
fill="#000"改为fill="currentColor"以支持主题 - 保留了核心的
<path>和viewBox
6. 图标尺寸规范
6.1 尺寸分类
根据使用场景,图标分为三种尺寸:
- 48x48: 主要功能按钮(toolbar、工具栏)
- 32x32: 测量工具图标
- 24x24: 通用 UI 图标(关闭、展开等)
6.2 与 CSS 的配合
图标尺寸在 CSS 中可以被覆盖:
/* Toolbar 按钮图标 */
.opt-btn-icon svg {
width: 100%;
height: 100%;
}
/* 漫游控制面板按钮图标 */
.walk-icon-btn svg {
width: 32px;
height: 32px;
}
实际显示尺寸由 CSS 控制,SVG 的 width 和 height 属性主要用于:
- 定义默认尺寸
- 计算宽高比
- 作为
viewBox的参考
7. 添加新图标
7.1 添加流程
-
准备 SVG 文件:
- 将新图标文件放到
src/assets/目录 - 或直接获取 SVG 代码
- 将新图标文件放到
-
简化 SVG:
- 按照 5.1 节的简化原则处理 SVG
- 确保
fill="currentColor"以支持主题 - 设置合适的尺寸
-
添加到 ICONS 对象:
const ICONS: Record<string, string> = { // ... 现有图标 新图标名称: '<svg width="48" height="48" viewBox="0 0 48 48"><path fill="currentColor" d="..."/></svg>', }; -
使用新图标:
const icon = getIcon('新图标名称');
7.2 命名规范
- 使用中文名称:便于理解和维护
- 描述功能:名称应清晰描述图标用途
- 避免重复:检查是否已存在类似图标
推荐命名:
- ✅ 好的命名:
测量,地图,全屏,剖切盒 - ❌ 不好的命名:
icon1,svg2,btn_icon
8. 实现细节(供 AI 重现)
8.1 核心数据结构
const ICONS: Record<string, string> = {
// key: 图标名称(中文)
// value: SVG 字符串(完整的 <svg>...</svg>)
};
8.2 获取逻辑
export function getIcon(name: string): string {
const icon = ICONS[name];
if (!icon) {
console.warn(`[IconManager] Icon "${name}" not found, using default icon`);
return ICONS.default;
}
return icon;
}
关键点:
- 简单的字典查找
- 未找到时返回默认图标而不是
undefined - 在控制台输出警告信息,便于调试
8.3 为什么不使用枚举?
设计选择:使用字符串而不是 TypeScript 枚举
原因:
- 简化使用:直接传中文字符串,更直观
- 灵活性:可以动态添加图标而不需要修改类型定义
- 国际化友好:中文名称与 UI 文案保持一致
- 降低耦合:使用方不需要导入枚举类型
9. 与主题系统的配合
9.1 currentColor 属性
所有图标使用 fill="currentColor",这样图标颜色会继承父元素的 color 属性:
测量: '<svg width="48" height="48" viewBox="0 0 48 48"><path fill="currentColor" d="..."/></svg>',
9.2 在 CSS 中控制颜色
.opt-btn-icon {
color: var(--bim-icon-color, #ccc);
}
.opt-btn-icon svg {
fill: currentColor; /* 继承父元素的 color */
}
9.3 主题变更时的自动适配
当主题颜色变更时,只需更新 CSS 变量,所有图标会自动适配新颜色:
// 在 setTheme 中
element.style.setProperty('--bim-icon-color', theme.icon ?? '#ccc');
// 所有使用 currentColor 的图标自动更新颜色
10. 最佳实践
10.1 使用建议
✅ 推荐做法:
// 在组件顶部导入
import { getIcon } from '../../utils/icon-manager';
// 在需要时调用
const icon = getIcon('测量');
button.innerHTML = icon;
❌ 避免做法:
// 不要在组件中硬编码 SVG
const icon = '<svg>...</svg>'; // 不推荐
// 不要重复定义相同的图标
const myIcon = '<svg>...</svg>'; // 应该使用 getIcon()
10.2 性能考虑
- 字符串查找很快:
ICONS对象的查找是 O(1) 操作 - 无需缓存:图标字符串很小,不需要额外的缓存机制
- 按需使用:只在需要时调用
getIcon(),不需要预加载所有图标
10.3 维护建议
- 定期整理:删除不再使用的图标
- 统一风格:新增图标应与现有图标风格一致
- 文档同步:添加新图标时更新本文档的图标清单
- 命名规范:使用清晰、一致的中文命名
11. 更新记录
| 日期 | 修改内容 | 修改人 |
|---|---|---|
| 2025-12-25 | 创建图标管理器,整合所有 SVG 图标资源 | AI Assistant |
| 2025-12-25 | 添加"文档"图标,替换所有 toolbar 按钮图标 | AI Assistant |