# Sketch 图标尺寸提取问题

> **问题标签**: `sketch`, `icon`, `size`, `group`, `shape`  
> **框架**: Flutter  
> **严重程度**: 中等（还原精度）

---

## 🔍 问题识别

### 用户描述关键词
- "图标尺寸与设计稿不符"
- "设置了尺寸但没效果"
- "Group 和 Shape 尺寸不一样"
- "提取的尺寸是外层容器的"

### 问题特征
- [ ] 从 Sketch 提取了图标尺寸
- [ ] 实际显示比预期大或小
- [ ] Sketch 中图标有 Group 包裹
- [ ] Group 尺寸与内部 Shape 尺寸不同

---

## 🎯 核心原理

**根本原因**：Sketch 中图标通常有两层结构，外层 Group 用于布局定位，内层 Shape 才是实际视觉尺寸。

```
Sketch 图标结构:
├─ Group "Tab Icon" (22x22)       ← 外层容器，用于布局
│  └─ Shape "Icon_path" (14.67x14.67)  ← 内部实际图形
```

如果提取外层 Group 的尺寸，图标会比设计稿看起来大。

---

## ✅ 正确解决方案

### 使用脚本提取内部 Shape 尺寸

```javascript
// Sketch 脚本：提取图标的内部实际尺寸
const sketch = require('sketch');
const document = sketch.getSelectedDocument();
const page = document.selectedPage;

function extractIconInternalSize(frameName) {
  const frame = sketch.find(`[name="${frameName}"]`, page)[0];
  if (!frame) return console.log('Frame not found');
  
  function traverse(layer, parentY = 0) {
    const f = layer.frame;
    const absY = parentY + f.y;
    
    if (layer.type === 'Group' && layer.name.includes('Icon')) {
      console.log(`\n📦 ${layer.name} (外层 Group): ${f.width}x${f.height}`);
      layer.layers?.forEach(child => {
        if (child.type === 'Shape' || child.type === 'ShapePath') {
          const cf = child.frame;
          console.log(`  └─ ${child.name} (内部图形): ${cf.width.toFixed(1)}x${cf.height.toFixed(1)} ← 使用这个`);
        }
      });
    }
    if (layer.layers) layer.layers.forEach(child => traverse(child, absY));
  }
  traverse(frame);
}

extractIconInternalSize('Frame Name');
```

### 输出示例

```
📦 Tab Recipient Icon (外层 Group): 22x22
  └─ Tab Recipient Icon_path_0 (内部图形): 14.7x14.7 ← 使用这个尺寸
```

### Flutter 中使用正确尺寸

```dart
// ✅ 使用内部图形的实际尺寸
SvgPicture.asset(
  '<asset-dir>/recipient.svg',
  width: 15.0,  // 14.7 取整
  height: 15.0,
)

// ❌ 错误：使用外层 Group 尺寸
SvgPicture.asset(
  '<asset-dir>/recipient.svg',
  width: 22.0,  // 这是 Group 尺寸，图标会偏大
  height: 22.0,
)
```

---

## 📝 验证检查清单

1. **确认提取的是 Shape 尺寸**
   - 不是 Group、Frame、Artboard 的尺寸
   - 查看脚本输出中带 ← 标记的行

2. **视觉对比验证**
   - 在模拟器/设备上与设计稿截图对比
   - 图标边缘应与设计稿完全重合

3. **属性使用验证**
   ```bash
   # 搜索确认尺寸属性被使用
   grep -n "iconSize" lib/widgets/my_widget.dart
   ```

---

## ❌ 常见错误排查路线（避免重复）

| 尝试方向 | 为什么无效 | 浪费时间 |
|----------|-----------|---------|
| 调整 Flutter 中的尺寸 | 如果基准就错了，调来调去 | 3-5 轮对话 |
| 添加 transform scale | Hack 方案，难以精确 | 2-3 轮对话 |
| 重新导出 SVG | 如果不知道问题在哪，重复错误 | 2-3 轮对话 |

**最佳做法**：先用脚本确认正确尺寸，再修改代码

---

## 📁 适用场景

- ✅ TabBar 图标
- ✅ 按钮内图标
- ✅ 任何从 Sketch 导出的图标
