初始化
This commit is contained in:
@@ -562,12 +562,314 @@ const dialog = engine.dialog.create({
|
||||
| -------------- | ---------------------------- | ------------------------------ | ----------------------------- |
|
||||
| `IconManager` | `src/utils/icon-manager.ts` | 统一管理所有 SVG 图标资源 | `docs/utils/icon-manager.md` |
|
||||
|
||||
**IconManager 说明**:
|
||||
- 提供 `getIcon(name: string): string` 函数
|
||||
- 所有组件通过该函数获取 SVG 图标字符串
|
||||
- 支持默认图标回退机制
|
||||
- 图标使用 `currentColor` 以支持主题颜色
|
||||
- 详细说明见 `docs/utils/icon-manager.md`
|
||||
---
|
||||
|
||||
## 4.4.1 IconManager 图标管理器使用指南
|
||||
|
||||
### 核心概念
|
||||
|
||||
**IconManager 是项目中所有 SVG 图标的统一管理工具,必须严格遵循以下规范:**
|
||||
|
||||
#### 强制要求
|
||||
1. **禁止在代码中硬编码 SVG**: 所有图标必须通过 `getIcon()` 函数获取
|
||||
2. **使用中文名称**: 图标名称使用清晰的中文描述,如 `'测量'`, `'地图'`, `'全屏'`
|
||||
3. **支持主题颜色**: 所有图标使用 `fill="currentColor"` 以自动适配主题
|
||||
|
||||
### API 使用
|
||||
|
||||
#### 基本用法
|
||||
|
||||
```typescript
|
||||
import { getIcon } from '../../utils/icon-manager';
|
||||
|
||||
// 获取图标 SVG 字符串
|
||||
const icon = getIcon('测量');
|
||||
|
||||
// 在按钮配置中使用
|
||||
const buttonConfig: ButtonConfig = {
|
||||
id: 'measure',
|
||||
icon: getIcon('测量'),
|
||||
label: 'toolbar.measure'
|
||||
};
|
||||
|
||||
// 在 DOM 中使用
|
||||
button.innerHTML = getIcon('全屏');
|
||||
```
|
||||
|
||||
#### 在组件中使用
|
||||
|
||||
```typescript
|
||||
export class MyComponent implements IBimComponent {
|
||||
private createButton(): HTMLButtonElement {
|
||||
const btn = document.createElement('button');
|
||||
// 直接使用 getIcon 获取图标
|
||||
btn.innerHTML = getIcon('设置');
|
||||
return btn;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 图标分类
|
||||
|
||||
#### 1. 主要功能图标 (48x48)
|
||||
用于 toolbar 和主要功能按钮:
|
||||
- `测量`, `地图`, `框选放大`, `漫游`, `目录树`
|
||||
- `剖切`, `剖切盒`, `全屏`, `设置`, `拾曲面剖切`
|
||||
- `轴向剖切`, `主视角`, `文档`
|
||||
|
||||
#### 2. 测量工具图标 (32x32)
|
||||
用于测量面板:
|
||||
- `标高`, `距离`, `最小距离`, `激光边距`
|
||||
- `角度`, `坡度`, `体积`, `空间体积`
|
||||
|
||||
#### 3. 通用 UI 图标 (24x24)
|
||||
用于通用界面元素:
|
||||
- `close`, `check`, `warning`, `error`, `success`
|
||||
- `plus`, `minus`, `arrowUp`, `arrowDown`, `arrowLeft`, `arrowRight`
|
||||
- `search`, `refresh`, `delete`, `edit`, `save`
|
||||
- `expand`, `collapse`
|
||||
|
||||
### 图标尺寸规范
|
||||
|
||||
#### CSS 控制实际显示尺寸
|
||||
|
||||
虽然 SVG 有默认尺寸,但实际显示尺寸由 CSS 控制:
|
||||
|
||||
```css
|
||||
/* Toolbar 按钮图标 - 底部工具栏 */
|
||||
.bim-btn-group-root.is-bottom-toolbar .opt-btn-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
/* Walk 控制面板按钮图标 */
|
||||
.walk-icon-btn svg {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
/* 通用按钮图标 */
|
||||
.opt-btn-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
```
|
||||
|
||||
**重要**: 确保不同组件的图标尺寸保持一致,推荐使用:
|
||||
- **主按钮**: 32x32 (toolbar, walk-control-panel)
|
||||
- **次要按钮**: 24x24 (menu, tree, dialog)
|
||||
- **小图标**: 18x18 (下拉菜单项)
|
||||
|
||||
### 主题适配
|
||||
|
||||
#### currentColor 机制
|
||||
|
||||
所有图标使用 `fill="currentColor"`,会自动继承父元素的 `color` 属性:
|
||||
|
||||
```typescript
|
||||
// icon-manager.ts 中的图标定义
|
||||
测量: '<svg width="48" height="48" viewBox="0 0 48 48"><path fill="currentColor" d="..."/></svg>',
|
||||
```
|
||||
|
||||
```css
|
||||
/* CSS 中控制图标颜色 */
|
||||
.opt-btn-icon {
|
||||
color: var(--bim-icon-color, #ccc);
|
||||
}
|
||||
|
||||
.opt-btn-icon svg {
|
||||
fill: currentColor; /* 自动继承父元素的 color */
|
||||
}
|
||||
```
|
||||
|
||||
#### 主题变更自动适配
|
||||
|
||||
当主题切换时,只需更新 CSS 变量,所有图标自动更新颜色:
|
||||
|
||||
```typescript
|
||||
// setTheme 方法中
|
||||
element.style.setProperty('--bim-icon-color', theme.icon ?? '#ccc');
|
||||
// 所有使用 currentColor 的图标自动适配新颜色
|
||||
```
|
||||
|
||||
### 添加新图标
|
||||
|
||||
#### 流程步骤
|
||||
|
||||
1. **准备 SVG 文件**:
|
||||
- 放到 `src/assets/` 目录
|
||||
- 或直接获取 SVG 代码
|
||||
|
||||
2. **简化 SVG** (移除冗余):
|
||||
```xml
|
||||
<!-- 简化前 -->
|
||||
<svg xmlns="..." xmlns:xlink="...">
|
||||
<defs>...</defs>
|
||||
<clipPath>...</clipPath>
|
||||
<g clip-path="...">
|
||||
<path d="..." fill="#000"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<!-- 简化后 -->
|
||||
<svg width="48" height="48" viewBox="0 0 48 48">
|
||||
<path fill="currentColor" d="..."/>
|
||||
</svg>
|
||||
```
|
||||
|
||||
3. **添加到 icon-manager.ts**:
|
||||
```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('新功能');
|
||||
```
|
||||
|
||||
#### 命名规范
|
||||
|
||||
**✅ 推荐命名**:
|
||||
- 使用清晰的中文描述功能
|
||||
- 避免歧义和重复
|
||||
- 示例: `测量`, `全屏`, `剖切盒`, `空间体积`
|
||||
|
||||
**❌ 不推荐命名**:
|
||||
- 通用名称: `icon1`, `svg2`, `image`
|
||||
- 英文缩写: `msr`, `cfg`, `btn_icon`
|
||||
- 过长名称: `这是一个用于测量距离的图标`
|
||||
|
||||
### 错误处理
|
||||
|
||||
#### 自动回退机制
|
||||
|
||||
当请求的图标不存在时,自动返回默认图标:
|
||||
|
||||
```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;
|
||||
}
|
||||
```
|
||||
|
||||
**开发时的警告**:
|
||||
```
|
||||
[IconManager] Icon "不存在的图标" not found, using default icon
|
||||
```
|
||||
|
||||
这帮助开发者快速发现图标名称错误。
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### ✅ 推荐做法
|
||||
|
||||
```typescript
|
||||
// 1. 在组件顶部导入
|
||||
import { getIcon } from '../../utils/icon-manager';
|
||||
|
||||
// 2. 在需要时调用
|
||||
export const createButton = (): ButtonConfig => ({
|
||||
id: 'home',
|
||||
icon: getIcon('主视角'),
|
||||
label: 'toolbar.home'
|
||||
});
|
||||
|
||||
// 3. 在 DOM 中使用
|
||||
const btn = document.createElement('button');
|
||||
btn.innerHTML = getIcon('设置');
|
||||
```
|
||||
|
||||
#### ❌ 避免做法
|
||||
|
||||
```typescript
|
||||
// ❌ 不要硬编码 SVG
|
||||
const icon = '<svg>...</svg>';
|
||||
|
||||
// ❌ 不要重复定义相同图标
|
||||
const homeIcon = '<svg>...</svg>';
|
||||
const anotherHomeIcon = '<svg>...</svg>';
|
||||
|
||||
// ❌ 不要使用未定义的图标名称
|
||||
const icon = getIcon('ThisIconDoesNotExist'); // 会触发警告
|
||||
```
|
||||
|
||||
### 性能说明
|
||||
|
||||
- **查找速度**: O(1) 字典查找,无性能问题
|
||||
- **无需缓存**: 图标字符串很小,直接返回即可
|
||||
- **按需使用**: 只在需要时调用 `getIcon()`,不需要预加载
|
||||
|
||||
### 维护建议
|
||||
|
||||
1. **定期清理**: 删除不再使用的图标
|
||||
2. **统一风格**: 新增图标应与现有图标风格一致
|
||||
3. **文档同步**: 添加新图标后更新 `docs/utils/icon-manager.md`
|
||||
4. **测试验证**: 确保新图标在浅色/深色主题下都清晰可见
|
||||
|
||||
### 完整示例
|
||||
|
||||
#### 按钮配置中使用图标
|
||||
|
||||
```typescript
|
||||
import { getIcon } from '../../../utils/icon-manager';
|
||||
import type { ButtonConfig } from '../index.type';
|
||||
import type { BimEngine } from '../../../bim-engine';
|
||||
|
||||
export const createMeasureButton = (engine: BimEngine): ButtonConfig => {
|
||||
return {
|
||||
id: 'measure',
|
||||
groupId: 'group-1',
|
||||
type: 'button',
|
||||
label: 'toolbar.measure',
|
||||
icon: getIcon('测量'), // 使用图标管理器
|
||||
onClick: () => {
|
||||
engine.measure?.show();
|
||||
}
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
#### 组件中动态使用图标
|
||||
|
||||
```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] || getIcon('default');
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**相关文档**:
|
||||
- 详细的图标清单和使用说明见 `docs/utils/icon-manager.md`
|
||||
- SVG 简化规范和主题适配详见同一文档
|
||||
|
||||
### 4.5 事件总线定义
|
||||
|
||||
|
||||
Reference in New Issue
Block a user