反应器系统
大约 2 分钟
反应器系统
反应器用于实时响应实体变化并自动执行操作。
概念
反应器是一种事件驱动的机制,可以:
- 监听实体的添加、修改、删除
- 自动响应变化并执行关联操作
- 实现实体间的依赖关系(如关联标注)
自定义反应器
通过事件监听实现自定义反应逻辑。
const { CadEventManager, CadEvents, Engine, CircleEnt, PolylineEnt } = vjcad;
class CircleBoundingBoxReactor {
constructor() {
this.enabled = true;
this.boundingLines = new Map(); // 存储关联数据
}
install() {
// 监听实体添加
Engine.eventManager.on(CadEvents.EntityAdded, (args) => {
if (this.enabled && args.entity.type === 'CIRCLE') {
this.createBoundingBox(args.entity);
}
});
// 监听实体修改
Engine.eventManager.on(CadEvents.EntityModified, (args) => {
if (this.enabled && args.entity.type === 'CIRCLE') {
this.updateBoundingBox(args.entity);
}
});
// 监听实体删除
Engine.eventManager.on(CadEvents.EntitiesErased, (args) => {
args.entities.forEach(entity => {
if (entity.type === 'CIRCLE') {
this.removeBoundingBox(entity);
}
});
});
}
createBoundingBox(circle) {
const r = circle.radius;
const cx = circle.center.x;
const cy = circle.center.y;
const rect = new PolylineEnt();
rect.setPoints([
[cx - r, cy - r],
[cx + r, cy - r],
[cx + r, cy + r],
[cx - r, cy + r]
]);
rect.isClosed = true;
rect.setDefaults();
rect.color = 3;
Engine.addEntities(rect);
this.boundingLines.set(circle.id, rect);
Engine.regen();
}
updateBoundingBox(circle) {
const rect = this.boundingLines.get(circle.id);
if (!rect) return;
const r = circle.radius;
const cx = circle.center.x;
const cy = circle.center.y;
rect.setPoints([
[cx - r, cy - r],
[cx + r, cy - r],
[cx + r, cy + r],
[cx - r, cy + r]
]);
Engine.regen();
}
removeBoundingBox(circle) {
const rect = this.boundingLines.get(circle.id);
if (rect) {
Engine.eraseEntities(rect);
this.boundingLines.delete(circle.id);
Engine.regen();
}
}
toggle() {
this.enabled = !this.enabled;
message.info(`反应器已${this.enabled ? '启用' : '禁用'}`);
}
}
// 安装反应器
const reactor = new CircleBoundingBoxReactor();
reactor.install();关键事件
| 事件 | 说明 |
|---|---|
CadEvents.EntityAdded | 实体添加后触发 |
CadEvents.EntityModified | 实体修改后触发 |
CadEvents.EntitiesErased | 实体删除后触发(批量) |
关联标注反应器
标注实体内置反应器机制,通过 setSourceEntities() 建立关联,源实体移动时标注自动更新。
const { LinearDimensionEnt, LineEnt, Point2D, Engine } = vjcad;
// 创建直线
const line = new LineEnt([0, 0], [100, 0]);
line.setDefaults();
Engine.addEntities(line);
// 创建标注
const dim = new LinearDimensionEnt(
new Point2D(0, 0),
new Point2D(100, 0),
new Point2D(50, 20),
0
);
dim.setDefaults();
Engine.addEntities(dim);
// 建立关联(必须在 addEntities 之后)
dim.setSourceEntities(
line.id, -1, // 起点关联实体和线段索引(-1=整条线)
line.id, -1, // 终点关联实体
'start', // 起点端点类型
'end' // 终点端点类型
);
// 检查关联状态
console.log("isAssociative:", dim.isAssociative);
// 移动直线时,标注会自动更新
line.move([0, 0], [50, 0]);
Engine.regen();端点类型
| 类型 | 说明 |
|---|---|
'start' | 起点 |
'end' | 终点 |
'center' | 中心点 |
'midpoint' | 中点 |
精确定位
使用 parameterT 指定在线段上的比例位置(0~1):
dim.setSourceEntities(
line.id, -1,
line.id, -1,
undefined, // 不使用 pointType
undefined,
0.25, // startParameterT: 1/4 处
0.75 // endParameterT: 3/4 处
);支持的标注类型
LinearDimensionEnt- 线性标注AlignedDimensionEnt- 对齐标注
反应器生命周期管理
启用/禁用控制
class MyReactor {
constructor() {
this.enabled = true;
}
toggle() {
this.enabled = !this.enabled;
}
}数据管理
使用 Map 存储关联数据:
class MyReactor {
constructor() {
this.relations = new Map(); // entityId -> relatedEntity
}
// 创建关联
onCreate(entity) {
const related = this.createRelated(entity);
this.relations.set(entity.id, related);
}
// 更新关联
onModify(entity) {
const related = this.relations.get(entity.id);
if (related) {
this.updateRelated(entity, related);
}
}
// 删除关联
onDelete(entity) {
const related = this.relations.get(entity.id);
if (related) {
Engine.eraseEntities(related);
this.relations.delete(entity.id);
}
}
}注意事项
- 关联标注必须在 addEntities 之后设置
- 线段索引
-1表示整条线 - 使用
parameterT时,pointType应设为undefined - 关联后源实体变化时标注自动更新,无需手动调用