# Easyeda Draw Placement

> Component placement techniques for EasyEDA Pro schematics. Invoke when placing components, assigning designators, rotating/mirroring parts, or adjusting layout spacing.

- Skill: `kukucaicndy/easyeda-draw-placement` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add kukucaicndy/easyeda-draw-placement`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kukucaicndy/easyeda-draw-placement/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: kukucaicndy (https://skillmd.com/u/kukucaicndy)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kukucaicndy/easyeda-draw-placement

---


# 器件摆放

元器件放置、位号分配、旋转镜像、间距控制的完整指南。

---

## 1. 基本放置

```javascript
const result = await eda.sch_PrimitiveComponent.create(
  { libraryUuid: "库UUID", uuid: "器件UUID" },
  x,           // X 坐标 (0.01inch 单位)
  y,           // Y 坐标
  "",          // 子部件名，单 Part 器件留空 ""
  0,           // 旋转角度: 0, 90, 180, 270
  false,       // 是否镜像
  true,        // 加入 BOM
  true         // 加入 PCB
);
const primitiveId = result?.primitiveId;
```

**⚠️ 坐标注意**: `(x, y)` 是符号**原点/锚点**，不是器件中心。引脚实际位置由符号定义决定。

---

## 2. 位号分配

### 手动设置

```javascript
await eda.sch_PrimitiveComponent.modify(primitiveId, {
  designator: "SW1"
});
```

### 批量分配

```javascript
const compIds = await eda.sch_PrimitiveComponent.getAllPrimitiveId();
const designatorMap = {
  "primitiveId1": "SW1",
  "primitiveId2": "SW2",
  "primitiveId3": "D1",
};
for (const [id, des] of Object.entries(designatorMap)) {
  await eda.sch_PrimitiveComponent.modify(id, { designator: des });
}
```

### 位号规范

| 元件类型 | 前缀 | 示例 |
|---------|------|------|
| 电阻 | R | R1, R2 |
| 电容 | C | C1, C5 |
| 二极管 | D | D1, D5 |
| IC | U | U1, U3 |
| 连接器 | J | J1, P2 |
| 开关 | SW | SW1, SW2 |
| 编码器 | SW | SW7 (带开关) |
| OLED | DS | DS1 |
| 测试点 | TP | TP1 |

---

## 3. 旋转和镜像

### 放置时旋转

```javascript
// rotation: 传角度值: 0, 90, 180, 270
// 注意: 传 90 时 API 内部存储为 270，但视觉上旋转 90° 正确
await eda.sch_PrimitiveComponent.create(comp, x, y, "", 90, false, true, true);
```

### 放置后旋转

```javascript
const comps = await eda.sch_PrimitiveComponent.get([primitiveId]);
const comp = comps[0];
const ac = comp.toAsync();
ac.setState_Rotation(90);
ac.done();
```

### 镜像

```javascript
// 放置时镜像
await eda.sch_PrimitiveComponent.create(comp, x, y, "", 0, true, true, true);

// 放置后镜像
const ac = comp.toAsync();
ac.setState_Mirror(true);
ac.done();
```

**⚠️ 如果 API 无法旋转（某些符号不支持），需要人工在 EasyEDA 中手动旋转。**

---

## 4. 间距控制

### 实测器件引脚范围

| 器件类型 | 引脚范围 (宽x高) | 建议最小列距 | 建议行距 |
|---------|----------------|------------|---------|
| 轻触开关 | 40x20 单位 | 150 单位 (1.5 inch) | 130 单位 |
| 二极管 | 40x0 (水平线) | 100 单位 | 40 单位 |
| 电阻 0402 | 40x0 (水平线) | 100 单位 | 40 单位 |
| 旋转编码器 | 60x60 单位 | 150 单位 | 130 单位 |
| 4P Header | 0x30 (垂直线) | 80 单位 | 60 单位 |
| OLED 显示屏 | 视具体符号 | 100 单位 | 80 单位 |

### 电阻符号实测数据

以 `0402WGF3301TCE` (0402 3.3K 电阻) 为例：
- 放置坐标 (anchor): (585, 412)
- 实际 anchor: (585, 410) — Y 有 2 单位微小偏差
- 引脚位置: 左 (565, 410), 右 (605, 410)
- 引脚间距: 40 单位 (0.4 inch = 10.16 mm)
- **anchor 在引脚中点**，引脚水平对称分布

> **⚠️ 器件 anchor 偏差**: 某些符号的放置坐标与实际 anchor 可能有微小偏差（1-2 单位），这是符号内部 origin 定义导致的。放置时以 anchor 为参考即可。

### 推荐布局区域

```
A4 图纸约 1170x825 单位（占位符示意，实际坐标由 Zone Plan 决定）

┌─────────────────────────────────────────┐
│  模块 C (接口)        │  主控 / 核心 IC  │
│  (示例坐标)           │  (示例坐标)      │
├─────────────────────────────────────────┤
│  模块 A (核心功能)                       │
│  器件 1 器件 2 器件 3                    │
│  器件 4 器件 5 器件 6                    │
├─────────────────────────────────────────┤
│  模块 B (辅助输入)    │  模块 D (调试)   │
├─────────────────────────────────────────┤
│  信号连接说明                            │
└─────────────────────────────────────────┘
```

---

## 5. 获取器件实际位置

```javascript
const comps = await eda.sch_PrimitiveComponent.get([primitiveId]);
const c = comps[0];
const pins = await eda.sch_PrimitiveComponent.getAllPinsByPrimitiveId(primitiveId);

// 计算引脚包围盒
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
for (const p of pins) {
  minX = Math.min(minX, p.x);
  maxX = Math.max(maxX, p.x);
  minY = Math.min(minY, p.y);
  maxY = Math.max(maxY, p.y);
}

return {
  designator: c.designator,
  anchor: {x: c.x, y: c.y},           // 放置坐标（原点）
  pinBBox: [minX, minY, maxX, maxY],  // 引脚实际范围
  pinCount: pins.length,
};
```

---

## 6. 移动器件

```javascript
const comps = await eda.sch_PrimitiveComponent.get([primitiveId]);
const comp = comps[0];
const ac = comp.toAsync();
ac.setState_X(newX);
ac.setState_Y(newY);
ac.done();
```

---

## 7. 删除器件

```javascript
// 删除单个
await eda.sch_PrimitiveComponent.delete(primitiveId);

// 删除多个
await eda.sch_PrimitiveComponent.delete([id1, id2, id3]);

// 删除所有（保留特定器件）
const compIds = await eda.sch_PrimitiveComponent.getAllPrimitiveId();
const toDelete = compIds.filter(id => id !== "保留的ID");
await eda.sch_PrimitiveComponent.delete(toDelete);
```

> **⚠️ 图纸边框和表头保护**
>
> 图纸边框（Border）和标题块（Title Block）**不是**通过 `sch_PrimitiveComponent` 管理的图元，
> 而是文档级别的属性。使用 `delete()` 删除元器件**不会**影响它们。
>
> 但是，如果 `titleBlockData` 被清空，标题块会显示为空白。可通过以下方式恢复：
> ```javascript
> await eda.dmt_Schematic.modifySchematicPageTitleBlock(true, {
>   '@Project Name': {showTitle: true, showValue: true, value: '项目名称'},
>   Version: {showTitle: true, showValue: true, value: 'V1.0'},
> });
> ```

---

## 8. 文本标注

```javascript
await eda.sch_PrimitiveText.create(
  x, y,           // 位置
  "文本内容",      // 内容
  0,              // 旋转角度
  null,           // 颜色
  null,           // 字体
  8,              // 字号 (与坐标同单位)
  false,          // 粗体
  false,          // 斜体
  false,          // 下划线
  0               // 对齐: 0=左, 1=中, 2=右
);
```

**字号参考**:
- 功能区域标题: 8-10
- 引脚标注: 5-6
- 注释说明: 4-5

---

## 9. 矩形绘制

```javascript
await eda.sch_PrimitiveRectangle.create(
  topLeftX, topLeftY,   // 左上角
  width, height,        // 宽高
  0,                    // 圆角半径
  0,                    // 旋转角度
  "#000000",            // 边框颜色
  null,                 // 填充颜色
  null,                 // 线宽
  null,                 // 线型
  null                  // 填充样式
);
```

---

## 10. 常见错误

| 错误 | 原因 | 解决方案 |
|------|------|----------|
| `Request timed out` | 一次创建太多器件 | 分批创建，减少单次批量 |
| `无法创建矩形图元` | 参数顺序错误 | 检查 create() 签名 |
| `comp.getState_X is not a function` | get() 返回数组 | 取 `comps[0]` |
| `comp.toAsync is not a function` | 同步对象无此方法 | 直接访问属性 |
| 位号显示 `?` | API 不自动分配 | 使用 `modify()` 设置 |
| 位号文字与引脚重叠 | 默认位号位置在符号左上角 | 需在 EasyEDA UI 中手动拖拽调整 |
| 名称显示 `={Manufacturer Part}` | 属性未设置 | 正常行为 |
| 器件重叠 | 间距太小 | 参考间距表调整 |
| 自定义符号无法放置 | 符号源码格式错误 | 检查 updateDocumentSource 格式 |

