Files
bim_engine/docs-old/utils/图标管理器-IconManager.md

424 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 函数
```typescript
function getIcon(name: string): string
```
**参数**:
- `name`: string - 图标名称(中文)
**返回值**:
- string - SVG 图标的完整字符串
**行为**:
1.`ICONS` 对象中查找对应名称的图标
2. 如果找到,返回该图标的 SVG 字符串
3. 如果未找到,在控制台输出警告并返回默认图标
**示例**:
```typescript
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 在按钮配置中使用
```typescript
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 在组件中使用
```typescript
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 在树节点中使用
```typescript
import { getIcon } from '../../utils/icon-manager';
const treeData: TreeNodeConfig[] = [
{
id: 'level-1',
label: '一层',
icon: getIcon('目录树'),
children: [...]
}
];
```
---
## 5. SVG 简化规范
### 5.1 简化原则
从 assets 目录中的 SVG 文件简化时,遵循以下原则:
1. **保留核心路径**:只保留 `<path>` 元素及其 `d` 属性
2. **移除冗余属性**:删除 `<defs>`, `<clipPath>`, `<style>`, `<g>` 等非必要元素
3. **保持颜色属性**:保留 `fill="currentColor"` 以支持主题颜色
4. **统一尺寸**:根据用途设置合适的 `viewBox``width/height`
5. **简化变换**:如果有 `transform`,尽量简化或合并到路径中
### 5.2 简化示例
**原始 SVG (从 assets/测量.svg)**:
```xml
<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 中)**:
```typescript
测量: '<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 尺寸分类
根据使用场景,图标分为三种尺寸:
1. **48x48**: 主要功能按钮(toolbar、工具栏)
2. **32x32**: 测量工具图标
3. **24x24**: 通用 UI 图标(关闭、展开等)
### 6.2 与 CSS 的配合
图标尺寸在 CSS 中可以被覆盖:
```css
/* Toolbar 按钮图标 */
.opt-btn-icon svg {
width: 100%;
height: 100%;
}
/* 漫游控制面板按钮图标 */
.walk-icon-btn svg {
width: 32px;
height: 32px;
}
```
实际显示尺寸由 CSS 控制,SVG 的 `width``height` 属性主要用于:
1. 定义默认尺寸
2. 计算宽高比
3. 作为 `viewBox` 的参考
---
## 7. 添加新图标
### 7.1 添加流程
1. **准备 SVG 文件**:
- 将新图标文件放到 `src/assets/` 目录
- 或直接获取 SVG 代码
2. **简化 SVG**:
- 按照 5.1 节的简化原则处理 SVG
- 确保 `fill="currentColor"` 以支持主题
- 设置合适的尺寸
3. **添加到 ICONS 对象**:
```typescript
const ICONS: Record<string, string> = {
// ... 现有图标
新图标名称: '<svg width="48" height="48" viewBox="0 0 48 48"><path fill="currentColor" d="..."/></svg>',
};
```
4. **使用新图标**:
```typescript
const icon = getIcon('新图标名称');
```
### 7.2 命名规范
- **使用中文名称**:便于理解和维护
- **描述功能**:名称应清晰描述图标用途
- **避免重复**:检查是否已存在类似图标
**推荐命名**:
- ✅ 好的命名: `测量`, `地图`, `全屏`, `剖切盒`
- ❌ 不好的命名: `icon1`, `svg2`, `btn_icon`
---
## 8. 实现细节(供 AI 重现)
### 8.1 核心数据结构
```typescript
const ICONS: Record<string, string> = {
// key: 图标名称(中文)
// value: SVG 字符串(完整的 <svg>...</svg>)
};
```
### 8.2 获取逻辑
```typescript
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;
}
```
**关键点**:
1. 简单的字典查找
2. 未找到时返回默认图标而不是 `undefined`
3. 在控制台输出警告信息,便于调试
### 8.3 为什么不使用枚举?
设计选择:使用字符串而不是 TypeScript 枚举
**原因**:
1. **简化使用**:直接传中文字符串,更直观
2. **灵活性**:可以动态添加图标而不需要修改类型定义
3. **国际化友好**:中文名称与 UI 文案保持一致
4. **降低耦合**:使用方不需要导入枚举类型
---
## 9. 与主题系统的配合
### 9.1 currentColor 属性
所有图标使用 `fill="currentColor"`,这样图标颜色会继承父元素的 `color` 属性:
```typescript
测量: '<svg width="48" height="48" viewBox="0 0 48 48"><path fill="currentColor" d="..."/></svg>',
```
### 9.2 在 CSS 中控制颜色
```css
.opt-btn-icon {
color: var(--bim-icon-color, #ccc);
}
.opt-btn-icon svg {
fill: currentColor; /* 继承父元素的 color */
}
```
### 9.3 主题变更时的自动适配
当主题颜色变更时,只需更新 CSS 变量,所有图标会自动适配新颜色:
```typescript
// 在 setTheme 中
element.style.setProperty('--bim-icon-color', theme.icon ?? '#ccc');
// 所有使用 currentColor 的图标自动更新颜色
```
---
## 10. 最佳实践
### 10.1 使用建议
**✅ 推荐做法**:
```typescript
// 在组件顶部导入
import { getIcon } from '../../utils/icon-manager';
// 在需要时调用
const icon = getIcon('测量');
button.innerHTML = icon;
```
**❌ 避免做法**:
```typescript
// 不要在组件中硬编码 SVG
const icon = '<svg>...</svg>'; // 不推荐
// 不要重复定义相同的图标
const myIcon = '<svg>...</svg>'; // 应该使用 getIcon()
```
### 10.2 性能考虑
- **字符串查找很快**:`ICONS` 对象的查找是 O(1) 操作
- **无需缓存**:图标字符串很小,不需要额外的缓存机制
- **按需使用**:只在需要时调用 `getIcon()`,不需要预加载所有图标
### 10.3 维护建议
1. **定期整理**:删除不再使用的图标
2. **统一风格**:新增图标应与现有图标风格一致
3. **文档同步**:添加新图标时更新本文档的图标清单
4. **命名规范**:使用清晰、一致的中文命名
---
## 11. 更新记录
| 日期 | 修改内容 | 修改人 |
| ---------- | ----------------------------------------- | ------------ |
| 2025-12-25 | 创建图标管理器,整合所有 SVG 图标资源 | AI Assistant |
| 2025-12-25 | 添加"文档"图标,替换所有 toolbar 按钮图标 | AI Assistant |