Skip to content

Commit 4e1a67f

Browse files
committed
refactor(Graph): enhance zoomTo method to support various target types and improve documentation
1 parent 6f2923f commit 4e1a67f

File tree

2 files changed

+80
-17
lines changed

2 files changed

+80
-17
lines changed

src/api/PublicGraphApi.ts

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { selectBlockById } from "../store/block/selectors";
1010
import { TConnection, TConnectionId } from "../store/connection/ConnectionState";
1111
import { selectConnectionById } from "../store/connection/selectors";
1212
import { TGraphSettingsConfig } from "../store/settings";
13-
import { getBlocksRect, getElementsRect, startAnimation } from "../utils/functions";
13+
import { getElementsRect, startAnimation } from "../utils/functions";
1414
import { TRect } from "../utils/types/shapes";
1515

1616
export type ZoomConfig = {
@@ -23,18 +23,44 @@ export class PublicGraphApi {
2323
// noop
2424
}
2525

26+
/**
27+
* Zooms to blocks
28+
* @param blockIds - block ids to zoom to
29+
* @param zoomConfig - {@link ZoomConfig} zoom config
30+
* @returns {boolean} true if zoom is successful, false otherwise
31+
*
32+
* @example
33+
* ```typescript
34+
* graph.zoomToBlocks([block1.id, block2.id]);
35+
* graph.zoomToBlocks([block1.id, block2.id], { transition: 1000, padding: 50 });
36+
* ```
37+
*/
2638
public zoomToBlocks(blockIds: TBlockId[], zoomConfig?: ZoomConfig) {
27-
const blocks = blockIds.map((id) => this.graph.rootStore.blocksList.$blocksMap.value.get(id)).filter(Boolean);
28-
if (blocks.length === 0) {
29-
return;
30-
}
31-
const blocksRect = getBlocksRect(blocks.map((block) => block.asTBlock()));
32-
this.zoomToRect(blocksRect, zoomConfig);
39+
return this.zoomToElements(
40+
this.graph.rootStore.blocksList.getBlockStates(blockIds).map((blockState) => blockState.getViewComponent()),
41+
zoomConfig
42+
);
3343
}
3444

45+
/**
46+
* Zooms to GraphComponent instances
47+
* @param instances - {@link GraphComponent} instances to zoom to
48+
* @param zoomConfig - {@link ZoomConfig} zoom config
49+
* @returns {boolean} true if zoom is successful, false otherwise
50+
*
51+
* @example
52+
* ```typescript
53+
* graph.zoomToElements([component1, component2]);
54+
* graph.zoomToElements([component1, component2], { transition: 1000, padding: 50 });
55+
* ```
56+
*/
3557
public zoomToElements<T extends GraphComponent = GraphComponent>(elements: T[], zoomConfig?: ZoomConfig) {
58+
if (elements.length === 0) {
59+
return false;
60+
}
3661
const elementsRect = getElementsRect(elements);
3762
this.zoomToRect(elementsRect, zoomConfig);
63+
return true;
3864
}
3965

4066
/**
@@ -61,6 +87,21 @@ export class PublicGraphApi {
6187
});
6288
}
6389

90+
/**
91+
* Zooms to the specified rectangle in camera coordinates
92+
*
93+
* Zooms the camera to fit the specified rectangle in the viewport. The rectangle will be scaled
94+
* to fill the visible area (respecting camera insets) and centered in the viewport.
95+
*
96+
* @param rect - {@link TRect} rectangle to zoom to in camera coordinates
97+
* @param zoomConfig - {@link ZoomConfig} zoom config
98+
* @returns {undefined}
99+
*
100+
* @example
101+
* ```typescript
102+
* graph.zoomToRect({ x: 0, y: 0, width: 100, height: 100 });
103+
* graph.zoomToRect({ x: 0, y: 0, width: 100, height: 100 }, { transition: 1000, padding: 50 });
104+
*/
64105
public zoomToRect(rect: TRect, zoomConfig?: ZoomConfig) {
65106
const transition = zoomConfig?.transition || 0;
66107
const padding = zoomConfig?.padding || 0;

src/graph.ts

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -170,20 +170,42 @@ export class Graph {
170170
this.cameraService.zoom(zoomConfig.x || width / 2, zoomConfig.y || height / 2, zoomConfig.scale);
171171
}
172172

173-
public zoomTo(target: TGraphZoomTarget, config?: ZoomConfig) {
174-
if (target === "center") {
175-
this.api.zoomToViewPort(config);
176-
return;
177-
}
173+
/**
174+
* Zooms to the target
175+
*
176+
* - If target is rectangle, it will be zoomed({@link PublicGraphApi.zoomToRect}) to the rectangle and returns true.
177+
* - If target is array of block ids, it will be zoomed({@link PublicGraphApi.zoomToBlocks}) to the blocks, if at least one block is found, returns true, otherwise returns false.
178+
* - If target is array of {@link GraphComponent} instances, it will be zoomed({@link PublicGraphApi.zoomToElements}) to the rect containing all components and returns true.
179+
* - If target is center, it will be zoomed({@link PublicGraphApi.zoomToViewPort}) to the center and returns true.
180+
*
181+
* @example
182+
* ```typescript
183+
* graph.zoomTo("center");
184+
* graph.zoomTo([block1.id, block2.id]);
185+
* graph.zoomTo([block1, block2]);
186+
* graph.zoomTo({x: 100, y: 100, width: 100, height: 100 });
187+
* ```
188+
* @param target - target to zoom to
189+
* @param config - zoom config, optional, optional
190+
* @returns {boolean} true if zoom is successful, false otherwise
191+
*
192+
* */
193+
public zoomTo(target: TGraphZoomTarget, config?: ZoomConfig): boolean {
178194
if (isTRect(target)) {
179195
this.api.zoomToRect(target, config);
180-
return;
196+
return true;
181197
}
182-
if (Array.isArray(target) && target.every((item) => item instanceof GraphComponent)) {
183-
this.api.zoomToElements(target, config);
184-
return;
198+
if (Array.isArray(target)) {
199+
if (target.every((item) => item instanceof GraphComponent)) {
200+
return this.api.zoomToElements(target, config);
201+
}
202+
if (target.every((item) => typeof item === "string")) {
203+
return this.api.zoomToBlocks(target, config);
204+
}
185205
}
186-
this.api.zoomToBlocks(target, config);
206+
207+
this.api.zoomToViewPort(config);
208+
return true;
187209
}
188210

189211
public getElementsOverPoint<T extends Constructor<GraphComponent>>(point: IPoint, filter?: T[]): InstanceType<T>[] {

0 commit comments

Comments
 (0)