@mint-ui/map 1.2.0-test.71 → 1.2.0-test.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/CanvasMarkerLayer.js +60 -32
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/types.d.ts +43 -1
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/CanvasPolygonLayer.js +52 -25
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/types.d.ts +7 -1
- package/dist/components/mint-map/core/advanced/shared/context.d.ts +5 -0
- package/dist/components/mint-map/core/advanced/shared/context.js +12 -2
- package/dist/components/mint-map/core/advanced/shared/hooks.d.ts +1 -1
- package/dist/components/mint-map/core/advanced/shared/hooks.js +2 -2
- package/dist/components/mint-map/core/advanced/shared/performance.d.ts +8 -4
- package/dist/components/mint-map/core/advanced/shared/performance.js +24 -4
- package/dist/index.es.js +678 -594
- package/dist/index.umd.js +678 -594
- package/package.json +1 -1
|
@@ -30,13 +30,12 @@ var CanvasMarkerLayer = function (props) {
|
|
|
30
30
|
var data = props.data,
|
|
31
31
|
_a = props.cullingMargin,
|
|
32
32
|
cullingMargin = _a === void 0 ? performance.DEFAULT_CULLING_MARGIN : _a,
|
|
33
|
-
|
|
34
|
-
maxCacheSize = _b === void 0 ? performance.DEFAULT_MAX_CACHE_SIZE : _b,
|
|
33
|
+
onOptimizationDataUpdate = props.onOptimizationDataUpdate,
|
|
35
34
|
renderBase = props.renderBase,
|
|
36
|
-
options = tslib.__rest(props, ["data", "cullingMargin", "
|
|
35
|
+
options = tslib.__rest(props, ["data", "cullingMargin", "onOptimizationDataUpdate", "renderBase"]); // renderEvent가 있는 경우에만 인터랙션 관련 props 추출
|
|
37
36
|
|
|
38
37
|
|
|
39
|
-
var
|
|
38
|
+
var _b = hasRenderEvent && 'renderEvent' in props ? props : {
|
|
40
39
|
disableInteraction: false,
|
|
41
40
|
onClick: undefined,
|
|
42
41
|
onMouseOut: undefined,
|
|
@@ -46,15 +45,15 @@ var CanvasMarkerLayer = function (props) {
|
|
|
46
45
|
selectedItems: undefined,
|
|
47
46
|
topStageZIndex: undefined
|
|
48
47
|
},
|
|
49
|
-
|
|
50
|
-
disableInteraction =
|
|
51
|
-
onClick =
|
|
52
|
-
onMouseOut =
|
|
53
|
-
onMouseOver =
|
|
54
|
-
renderEvent =
|
|
55
|
-
externalSelectedItem =
|
|
56
|
-
externalSelectedItems =
|
|
57
|
-
rawTopStageZIndex =
|
|
48
|
+
_c = _b.disableInteraction,
|
|
49
|
+
disableInteraction = _c === void 0 ? false : _c,
|
|
50
|
+
onClick = _b.onClick,
|
|
51
|
+
onMouseOut = _b.onMouseOut,
|
|
52
|
+
onMouseOver = _b.onMouseOver,
|
|
53
|
+
renderEvent = _b.renderEvent,
|
|
54
|
+
externalSelectedItem = _b.selectedItem,
|
|
55
|
+
externalSelectedItems = _b.selectedItems,
|
|
56
|
+
rawTopStageZIndex = _b.topStageZIndex; // topStageZIndex가 있으면 hover 최상단 표시 활성화, 없으면 비활성화 (성능 우선)
|
|
58
57
|
|
|
59
58
|
|
|
60
59
|
var topStageZIndex = rawTopStageZIndex;
|
|
@@ -92,24 +91,30 @@ var CanvasMarkerLayer = function (props) {
|
|
|
92
91
|
y: 0
|
|
93
92
|
}); // 드래그 시작 시점의 hover 상태 저장 (드래그 중 hover 고정용)
|
|
94
93
|
|
|
95
|
-
var dragStartHoveredItemRef = React.useRef(null); //
|
|
94
|
+
var dragStartHoveredItemRef = React.useRef(null); // 공유 캐시 사용 (모든 마커 레이어가 공유)
|
|
95
|
+
|
|
96
|
+
var sharedMarkerCache = context$1 === null || context$1 === void 0 ? void 0 : context$1.sharedMarkerCache;
|
|
97
|
+
|
|
98
|
+
if (!sharedMarkerCache) {
|
|
99
|
+
throw new Error('CanvasMarkerLayer must be used within CanvasProvider');
|
|
100
|
+
} // 성능 최적화 Refs
|
|
101
|
+
|
|
96
102
|
|
|
97
|
-
var offsetCacheRef = React.useRef(new performance.QueueCache(maxCacheSize));
|
|
98
103
|
var spatialIndexRef = React.useRef(new performance.SpatialHashGrid(performance.SPATIAL_GRID_CELL_SIZE));
|
|
99
104
|
var boundingBoxCacheRef = React.useRef(new Map());
|
|
100
105
|
var viewportRef = React.useRef(null); // 뷰포트 영역 계산 (Viewport Culling용)
|
|
101
106
|
|
|
102
107
|
var updateViewport = function () {
|
|
103
108
|
viewport.updateViewport(stageRef.current, cullingMargin, viewportRef);
|
|
104
|
-
}; // 마커 좌표 변환 (위경도 → 화면 좌표,
|
|
109
|
+
}; // 마커 좌표 변환 (위경도 → 화면 좌표, 공유 캐시 사용)
|
|
105
110
|
|
|
106
111
|
|
|
107
112
|
var getOrComputeMarkerOffset = function (markerData) {
|
|
108
|
-
var cached =
|
|
109
|
-
if (cached
|
|
113
|
+
var cached = sharedMarkerCache.get(markerData.id);
|
|
114
|
+
if (cached) return cached;
|
|
110
115
|
var result = utils.computeMarkerOffset(markerData, controller);
|
|
111
116
|
if (!result) return null;
|
|
112
|
-
|
|
117
|
+
sharedMarkerCache.set(markerData.id, result);
|
|
113
118
|
return result;
|
|
114
119
|
}; // 마커 바운딩 박스 계산 (Viewport Culling 및 Hit Test용, 오프셋 지원)
|
|
115
120
|
|
|
@@ -306,6 +311,24 @@ var CanvasMarkerLayer = function (props) {
|
|
|
306
311
|
}
|
|
307
312
|
});
|
|
308
313
|
layer.batchDraw();
|
|
314
|
+
}; // 최적화 데이터 업데이트 콜백 호출
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
var notifyOptimizationData = function () {
|
|
318
|
+
if (!onOptimizationDataUpdate) return; // 공유 캐시에서 마커 타입 항목만 필터링 (Offset 타입만)
|
|
319
|
+
|
|
320
|
+
var allCacheEntries = sharedMarkerCache.getAllEntries();
|
|
321
|
+
var cacheEntries = allCacheEntries.map(function (_a) {
|
|
322
|
+
var key = _a[0],
|
|
323
|
+
value = _a[1];
|
|
324
|
+
return [key, value];
|
|
325
|
+
});
|
|
326
|
+
var spatialGridCells = spatialIndexRef.current.getAllCells();
|
|
327
|
+
onOptimizationDataUpdate({
|
|
328
|
+
cacheEntries: cacheEntries,
|
|
329
|
+
cacheSize: sharedMarkerCache.size(),
|
|
330
|
+
spatialGridCells: spatialGridCells
|
|
331
|
+
});
|
|
309
332
|
}; // 전체 즉시 렌더링
|
|
310
333
|
|
|
311
334
|
|
|
@@ -321,27 +344,32 @@ var CanvasMarkerLayer = function (props) {
|
|
|
321
344
|
|
|
322
345
|
if (topStageZIndex !== undefined) {
|
|
323
346
|
doRenderTop();
|
|
324
|
-
}
|
|
347
|
+
} // 최적화 데이터 업데이트 콜백 호출
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
notifyOptimizationData();
|
|
325
351
|
}; // 지도 이벤트 핸들러 생성
|
|
326
352
|
|
|
327
353
|
|
|
328
|
-
var
|
|
354
|
+
var _d = hooks.createMapEventHandlers({
|
|
329
355
|
accumTranslateRef: accumTranslateRef,
|
|
330
356
|
boundingBoxCacheRef: boundingBoxCacheRef,
|
|
357
|
+
clearCache: function () {
|
|
358
|
+
return sharedMarkerCache.clear();
|
|
359
|
+
},
|
|
331
360
|
containerRef: containerRef,
|
|
332
361
|
controller: controller,
|
|
333
362
|
markerRef: markerRef,
|
|
334
|
-
offsetCacheRef: offsetCacheRef,
|
|
335
363
|
options: options,
|
|
336
364
|
prevCenterOffsetRef: prevCenterOffsetRef,
|
|
337
365
|
renderAllImmediate: renderAllImmediate
|
|
338
366
|
}),
|
|
339
|
-
handleIdleShared =
|
|
340
|
-
handleZoomStart =
|
|
341
|
-
handleZoomEnd =
|
|
342
|
-
handleCenterChangedShared =
|
|
343
|
-
handleDragStartShared =
|
|
344
|
-
handleDragEndShared =
|
|
367
|
+
handleIdleShared = _d.handleIdle,
|
|
368
|
+
handleZoomStart = _d.handleZoomStart,
|
|
369
|
+
handleZoomEnd = _d.handleZoomEnd,
|
|
370
|
+
handleCenterChangedShared = _d.handleCenterChanged,
|
|
371
|
+
handleDragStartShared = _d.handleDragStart,
|
|
372
|
+
handleDragEndShared = _d.handleDragEnd; // handleIdle 래핑: topStage transform 제거 추가
|
|
345
373
|
|
|
346
374
|
|
|
347
375
|
var handleIdle = function () {
|
|
@@ -606,7 +634,7 @@ var CanvasMarkerLayer = function (props) {
|
|
|
606
634
|
resizeRafId = requestAnimationFrame(function () {
|
|
607
635
|
stage.width(mapDiv.offsetWidth);
|
|
608
636
|
stage.height(mapDiv.offsetHeight);
|
|
609
|
-
|
|
637
|
+
sharedMarkerCache.clear();
|
|
610
638
|
boundingBoxCacheRef.current.clear();
|
|
611
639
|
updateViewport();
|
|
612
640
|
renderAllImmediate();
|
|
@@ -681,8 +709,8 @@ var CanvasMarkerLayer = function (props) {
|
|
|
681
709
|
|
|
682
710
|
baseLayer.destroyChildren();
|
|
683
711
|
eventLayer.destroyChildren();
|
|
684
|
-
stage.destroy();
|
|
685
|
-
|
|
712
|
+
stage.destroy(); // 공유 캐시는 cleanup 시 clear하지 않음 (다른 레이어가 사용 중일 수 있음)
|
|
713
|
+
|
|
686
714
|
boundingBoxCacheRef.current.clear();
|
|
687
715
|
spatialIndexRef.current.clear();
|
|
688
716
|
};
|
|
@@ -898,7 +926,7 @@ var CanvasMarkerLayer = function (props) {
|
|
|
898
926
|
x: 0,
|
|
899
927
|
y: 0
|
|
900
928
|
};
|
|
901
|
-
|
|
929
|
+
sharedMarkerCache.clear();
|
|
902
930
|
boundingBoxCacheRef.current.clear();
|
|
903
931
|
selectedItemsMapRef.current = hooks.syncSelectedItems(data, selectedIdsRef.current, selectedItemsMapRef.current);
|
|
904
932
|
renderAllImmediate();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MarkerOptions } from '../../../types';
|
|
1
|
+
import type { MarkerOptions, Offset } from '../../../types';
|
|
2
2
|
import type { CanvasData, CustomRenderBase, CustomRenderEvent } from '../shared';
|
|
3
3
|
/**
|
|
4
4
|
* CanvasMarkerLayer Props (renderEvent가 없는 경우 - 인터랙션 불가)
|
|
@@ -25,6 +25,12 @@ export interface CanvasMarkerLayerPropsWithoutEvent<T> extends Pick<MarkerOption
|
|
|
25
25
|
selectedItem?: never;
|
|
26
26
|
disableInteraction?: never;
|
|
27
27
|
topStageZIndex?: never;
|
|
28
|
+
/** 최적화 데이터 콜백 (디버깅/모니터링용) */
|
|
29
|
+
onOptimizationDataUpdate?: (data: {
|
|
30
|
+
cacheSize: number;
|
|
31
|
+
cacheEntries: Array<[string, number[][][][] | Offset]>;
|
|
32
|
+
spatialGridCells: Map<string, CanvasData<T>[]>;
|
|
33
|
+
}) => void;
|
|
28
34
|
}
|
|
29
35
|
/**
|
|
30
36
|
* CanvasMarkerLayer Props (renderEvent가 있는 경우 - 인터랙션 가능)
|
|
@@ -57,6 +63,12 @@ export interface CanvasMarkerLayerPropsWithEventWithSelectedItem<T> extends Pick
|
|
|
57
63
|
renderEvent: CustomRenderEvent<T>;
|
|
58
64
|
/** Top Layer의 zIndex (hover된 항목을 최상단에 렌더링하기 위한 레이어) */
|
|
59
65
|
topStageZIndex?: never;
|
|
66
|
+
/** 최적화 데이터 콜백 (디버깅/모니터링용) */
|
|
67
|
+
onOptimizationDataUpdate?: (data: {
|
|
68
|
+
cacheSize: number;
|
|
69
|
+
cacheEntries: Array<[string, number[][][][] | Offset]>;
|
|
70
|
+
spatialGridCells: Map<string, CanvasData<T>[]>;
|
|
71
|
+
}) => void;
|
|
60
72
|
}
|
|
61
73
|
/**
|
|
62
74
|
* CanvasMarkerLayer Props (renderEvent가 있는 경우 - 인터랙션 가능)
|
|
@@ -89,6 +101,12 @@ export interface CanvasMarkerLayerPropsWithEventWithSelectedItems<T> extends Pic
|
|
|
89
101
|
renderEvent: CustomRenderEvent<T>;
|
|
90
102
|
/** Top Layer의 zIndex (hover된 항목을 최상단에 렌더링하기 위한 레이어) */
|
|
91
103
|
topStageZIndex?: never;
|
|
104
|
+
/** 최적화 데이터 콜백 (디버깅/모니터링용) */
|
|
105
|
+
onOptimizationDataUpdate?: (data: {
|
|
106
|
+
cacheSize: number;
|
|
107
|
+
cacheEntries: Array<[string, number[][][][] | Offset]>;
|
|
108
|
+
spatialGridCells: Map<string, CanvasData<T>[]>;
|
|
109
|
+
}) => void;
|
|
92
110
|
}
|
|
93
111
|
/**
|
|
94
112
|
* CanvasMarkerLayer Props (renderEvent가 있는 경우 - 인터랙션 가능)
|
|
@@ -121,6 +139,12 @@ export interface CanvasMarkerLayerPropsWithEventWithoutSelection<T> extends Pick
|
|
|
121
139
|
renderEvent: CustomRenderEvent<T>;
|
|
122
140
|
/** Top Layer의 zIndex (hover된 항목을 최상단에 렌더링하기 위한 레이어) */
|
|
123
141
|
topStageZIndex?: never;
|
|
142
|
+
/** 최적화 데이터 콜백 (디버깅/모니터링용) */
|
|
143
|
+
onOptimizationDataUpdate?: (data: {
|
|
144
|
+
cacheSize: number;
|
|
145
|
+
cacheEntries: Array<[string, number[][][][] | Offset]>;
|
|
146
|
+
spatialGridCells: Map<string, CanvasData<T>[]>;
|
|
147
|
+
}) => void;
|
|
124
148
|
}
|
|
125
149
|
/**
|
|
126
150
|
* CanvasMarkerLayer Props (renderEvent가 있는 경우 - 인터랙션 가능)
|
|
@@ -154,6 +178,12 @@ export interface CanvasMarkerLayerPropsWithEventWithTopStageWithSelectedItem<T>
|
|
|
154
178
|
renderEvent: CustomRenderEvent<T>;
|
|
155
179
|
/** Top Layer의 zIndex (hover된 항목을 최상단에 렌더링하기 위한 레이어) */
|
|
156
180
|
topStageZIndex: number;
|
|
181
|
+
/** 최적화 데이터 콜백 (디버깅/모니터링용) */
|
|
182
|
+
onOptimizationDataUpdate?: (data: {
|
|
183
|
+
cacheSize: number;
|
|
184
|
+
cacheEntries: Array<[string, number[][][][] | Offset]>;
|
|
185
|
+
spatialGridCells: Map<string, CanvasData<T>[]>;
|
|
186
|
+
}) => void;
|
|
157
187
|
}
|
|
158
188
|
/**
|
|
159
189
|
* CanvasMarkerLayer Props (renderEvent가 있는 경우 - 인터랙션 가능)
|
|
@@ -187,6 +217,12 @@ export interface CanvasMarkerLayerPropsWithEventWithTopStageWithSelectedItems<T>
|
|
|
187
217
|
renderEvent: CustomRenderEvent<T>;
|
|
188
218
|
/** Top Layer의 zIndex (hover된 항목을 최상단에 렌더링하기 위한 레이어) */
|
|
189
219
|
topStageZIndex: number;
|
|
220
|
+
/** 최적화 데이터 콜백 (디버깅/모니터링용) */
|
|
221
|
+
onOptimizationDataUpdate?: (data: {
|
|
222
|
+
cacheSize: number;
|
|
223
|
+
cacheEntries: Array<[string, number[][][][] | Offset]>;
|
|
224
|
+
spatialGridCells: Map<string, CanvasData<T>[]>;
|
|
225
|
+
}) => void;
|
|
190
226
|
}
|
|
191
227
|
/**
|
|
192
228
|
* CanvasMarkerLayer Props (renderEvent가 있는 경우 - 인터랙션 가능)
|
|
@@ -220,6 +256,12 @@ export interface CanvasMarkerLayerPropsWithEventWithTopStageWithoutSelection<T>
|
|
|
220
256
|
renderEvent: CustomRenderEvent<T>;
|
|
221
257
|
/** Top Layer의 zIndex (hover된 항목을 최상단에 렌더링하기 위한 레이어) */
|
|
222
258
|
topStageZIndex: number;
|
|
259
|
+
/** 최적화 데이터 콜백 (디버깅/모니터링용) */
|
|
260
|
+
onOptimizationDataUpdate?: (data: {
|
|
261
|
+
cacheSize: number;
|
|
262
|
+
cacheEntries: Array<[string, number[][][][] | Offset]>;
|
|
263
|
+
spatialGridCells: Map<string, CanvasData<T>[]>;
|
|
264
|
+
}) => void;
|
|
223
265
|
}
|
|
224
266
|
/**
|
|
225
267
|
* CanvasMarkerLayer Props (renderEvent가 있는 경우 - 인터랙션 가능)
|
|
@@ -26,18 +26,17 @@ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
|
26
26
|
|
|
27
27
|
var CanvasPolygonLayer = function (props) {
|
|
28
28
|
var data = props.data,
|
|
29
|
-
onClick = props.onClick,
|
|
30
29
|
_a = props.enableMultiSelect,
|
|
31
30
|
enableMultiSelect = _a === void 0 ? false : _a,
|
|
32
31
|
_b = props.cullingMargin,
|
|
33
32
|
cullingMargin = _b === void 0 ? performance.DEFAULT_CULLING_MARGIN : _b,
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
onClick = props.onClick,
|
|
34
|
+
onOptimizationDataUpdate = props.onOptimizationDataUpdate,
|
|
36
35
|
externalSelectedItems = props.selectedItems,
|
|
37
36
|
externalSelectedItem = props.selectedItem,
|
|
38
|
-
|
|
39
|
-
disableInteraction =
|
|
40
|
-
options = tslib.__rest(props, ["data", "
|
|
37
|
+
_c = props.disableInteraction,
|
|
38
|
+
disableInteraction = _c === void 0 ? false : _c,
|
|
39
|
+
options = tslib.__rest(props, ["data", "enableMultiSelect", "cullingMargin", "onClick", "onOptimizationDataUpdate", "selectedItems", "selectedItem", "disableInteraction"]); // customStyle은 다른 방식과 함께 사용 가능
|
|
41
40
|
|
|
42
41
|
|
|
43
42
|
var hasCustomStyle = 'customStyle' in props && props.customStyle !== undefined;
|
|
@@ -80,19 +79,25 @@ var CanvasPolygonLayer = function (props) {
|
|
|
80
79
|
y: 0
|
|
81
80
|
}); // 드래그 시작 시점의 hover 상태 저장 (드래그 중 hover 고정용)
|
|
82
81
|
|
|
83
|
-
var dragStartHoveredItemRef = React.useRef(null); //
|
|
82
|
+
var dragStartHoveredItemRef = React.useRef(null); // 공유 캐시 사용 (모든 폴리곤 레이어가 공유)
|
|
83
|
+
|
|
84
|
+
var sharedPolygonCache = context$1 === null || context$1 === void 0 ? void 0 : context$1.sharedPolygonCache;
|
|
85
|
+
|
|
86
|
+
if (!sharedPolygonCache) {
|
|
87
|
+
throw new Error('CanvasPolygonLayer must be used within CanvasProvider');
|
|
88
|
+
} // 성능 최적화 Refs
|
|
89
|
+
|
|
84
90
|
|
|
85
|
-
var offsetCacheRef = React.useRef(new performance.QueueCache(maxCacheSize));
|
|
86
91
|
var spatialIndexRef = React.useRef(new performance.SpatialHashGrid(performance.SPATIAL_GRID_CELL_SIZE));
|
|
87
92
|
var boundingBoxCacheRef = React.useRef(new Map());
|
|
88
|
-
var viewportRef = React.useRef(null); // 폴리곤 좌표 변환 (위경도 → 화면 좌표,
|
|
93
|
+
var viewportRef = React.useRef(null); // 폴리곤 좌표 변환 (위경도 → 화면 좌표, 공유 캐시 사용)
|
|
89
94
|
|
|
90
95
|
var getOrComputePolygonOffsets = function (polygonData) {
|
|
91
|
-
var cached =
|
|
92
|
-
if (cached
|
|
96
|
+
var cached = sharedPolygonCache.get(polygonData.id);
|
|
97
|
+
if (cached) return cached;
|
|
93
98
|
var result = utils.computePolygonOffsets(polygonData, controller);
|
|
94
99
|
if (!result) return null;
|
|
95
|
-
|
|
100
|
+
sharedPolygonCache.set(polygonData.id, result);
|
|
96
101
|
return result;
|
|
97
102
|
}; // 폴리곤 바운딩 박스 계산 (Viewport Culling 및 Hit Test용)
|
|
98
103
|
|
|
@@ -251,6 +256,24 @@ var CanvasPolygonLayer = function (props) {
|
|
|
251
256
|
}
|
|
252
257
|
|
|
253
258
|
layer.batchDraw();
|
|
259
|
+
}; // 최적화 데이터 업데이트 콜백 호출
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
var notifyOptimizationData = function () {
|
|
263
|
+
if (!onOptimizationDataUpdate) return; // 공유 캐시에서 폴리곤 타입 항목만 필터링 (number[][][][] 타입만)
|
|
264
|
+
|
|
265
|
+
var allCacheEntries = sharedPolygonCache.getAllEntries();
|
|
266
|
+
var cacheEntries = allCacheEntries.map(function (_a) {
|
|
267
|
+
var key = _a[0],
|
|
268
|
+
value = _a[1];
|
|
269
|
+
return [key, value];
|
|
270
|
+
});
|
|
271
|
+
var spatialGridCells = spatialIndexRef.current.getAllCells();
|
|
272
|
+
onOptimizationDataUpdate({
|
|
273
|
+
cacheEntries: cacheEntries,
|
|
274
|
+
cacheSize: sharedPolygonCache.size(),
|
|
275
|
+
spatialGridCells: spatialGridCells
|
|
276
|
+
});
|
|
254
277
|
}; // 전체 즉시 렌더링
|
|
255
278
|
|
|
256
279
|
|
|
@@ -258,27 +281,31 @@ var CanvasPolygonLayer = function (props) {
|
|
|
258
281
|
updateViewport();
|
|
259
282
|
buildSpatialIndex();
|
|
260
283
|
doRenderBase();
|
|
261
|
-
doRenderEvent();
|
|
284
|
+
doRenderEvent(); // 최적화 데이터 업데이트 콜백 호출
|
|
285
|
+
|
|
286
|
+
notifyOptimizationData();
|
|
262
287
|
}; // 지도 이벤트 핸들러 생성
|
|
263
288
|
|
|
264
289
|
|
|
265
|
-
var
|
|
290
|
+
var _d = hooks.createMapEventHandlers({
|
|
266
291
|
accumTranslateRef: accumTranslateRef,
|
|
267
292
|
boundingBoxCacheRef: boundingBoxCacheRef,
|
|
293
|
+
clearCache: function () {
|
|
294
|
+
return sharedPolygonCache.clear();
|
|
295
|
+
},
|
|
268
296
|
containerRef: containerRef,
|
|
269
297
|
controller: controller,
|
|
270
298
|
markerRef: markerRef,
|
|
271
|
-
offsetCacheRef: offsetCacheRef,
|
|
272
299
|
options: options,
|
|
273
300
|
prevCenterOffsetRef: prevCenterOffsetRef,
|
|
274
301
|
renderAllImmediate: renderAllImmediate
|
|
275
302
|
}),
|
|
276
|
-
handleIdle =
|
|
277
|
-
handleZoomStart =
|
|
278
|
-
handleZoomEnd =
|
|
279
|
-
handleCenterChanged =
|
|
280
|
-
handleDragStartShared =
|
|
281
|
-
handleDragEndShared =
|
|
303
|
+
handleIdle = _d.handleIdle,
|
|
304
|
+
handleZoomStart = _d.handleZoomStart,
|
|
305
|
+
handleZoomEnd = _d.handleZoomEnd,
|
|
306
|
+
handleCenterChanged = _d.handleCenterChanged,
|
|
307
|
+
handleDragStartShared = _d.handleDragStart,
|
|
308
|
+
handleDragEndShared = _d.handleDragEnd;
|
|
282
309
|
|
|
283
310
|
var handleDragStart = function () {
|
|
284
311
|
handleDragStartShared(); // 드래그 시작 시점의 hover 상태 저장
|
|
@@ -462,7 +489,7 @@ var CanvasPolygonLayer = function (props) {
|
|
|
462
489
|
resizeRafId = requestAnimationFrame(function () {
|
|
463
490
|
stage.width(mapDiv.offsetWidth);
|
|
464
491
|
stage.height(mapDiv.offsetHeight);
|
|
465
|
-
|
|
492
|
+
sharedPolygonCache.clear();
|
|
466
493
|
boundingBoxCacheRef.current.clear();
|
|
467
494
|
updateViewport();
|
|
468
495
|
renderAllImmediate();
|
|
@@ -525,8 +552,8 @@ var CanvasPolygonLayer = function (props) {
|
|
|
525
552
|
|
|
526
553
|
baseLayer.destroyChildren();
|
|
527
554
|
eventLayer.destroyChildren();
|
|
528
|
-
stage.destroy();
|
|
529
|
-
|
|
555
|
+
stage.destroy(); // 공유 캐시는 cleanup 시 clear하지 않음 (다른 레이어가 사용 중일 수 있음)
|
|
556
|
+
|
|
530
557
|
boundingBoxCacheRef.current.clear();
|
|
531
558
|
spatialIndexRef.current.clear();
|
|
532
559
|
};
|
|
@@ -562,7 +589,7 @@ var CanvasPolygonLayer = function (props) {
|
|
|
562
589
|
x: 0,
|
|
563
590
|
y: 0
|
|
564
591
|
};
|
|
565
|
-
|
|
592
|
+
sharedPolygonCache.clear();
|
|
566
593
|
boundingBoxCacheRef.current.clear();
|
|
567
594
|
selectedItemsMapRef.current = hooks.syncSelectedItems(data, selectedIdsRef.current, selectedItemsMapRef.current);
|
|
568
595
|
renderAllImmediate();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
|
-
import type { MarkerOptions } from '../../../types';
|
|
2
|
+
import type { MarkerOptions, Offset } from '../../../types';
|
|
3
3
|
import type { CanvasData } from '../shared';
|
|
4
4
|
/**
|
|
5
5
|
* 폴리곤 스타일 정의
|
|
@@ -123,6 +123,12 @@ export interface CanvasPolygonLayerBaseProps<T> extends Pick<MarkerOptions, 'zIn
|
|
|
123
123
|
selectedItem?: CanvasData<T> | null;
|
|
124
124
|
/** 상호작용 비활성화 여부 (기본값: false) */
|
|
125
125
|
disableInteraction?: boolean;
|
|
126
|
+
/** 최적화 데이터 콜백 (디버깅/모니터링용) */
|
|
127
|
+
onOptimizationDataUpdate?: (data: {
|
|
128
|
+
cacheSize: number;
|
|
129
|
+
cacheEntries: Array<[string, number[][][][] | Offset]>;
|
|
130
|
+
spatialGridCells: Map<string, CanvasData<T>[]>;
|
|
131
|
+
}) => void;
|
|
126
132
|
}
|
|
127
133
|
/**
|
|
128
134
|
* 개별 Props 방식 (기존 방식)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { QueueCache } from './performance';
|
|
2
3
|
import { CanvasData } from './types';
|
|
3
4
|
import { Offset } from '../../../types';
|
|
4
5
|
/**
|
|
@@ -21,6 +22,8 @@ export interface ComponentInstance<T> {
|
|
|
21
22
|
interface CanvasContextValue {
|
|
22
23
|
registerComponent: <T>(instance: ComponentInstance<T>) => void;
|
|
23
24
|
unregisterComponent: <T>(instance: ComponentInstance<T>) => void;
|
|
25
|
+
sharedMarkerCache: QueueCache<string, Offset>;
|
|
26
|
+
sharedPolygonCache: QueueCache<string, number[][][][]>;
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
26
29
|
* CanvasProvider 컴포넌트
|
|
@@ -29,6 +32,8 @@ interface CanvasContextValue {
|
|
|
29
32
|
*/
|
|
30
33
|
export declare const CanvasProvider: React.FC<{
|
|
31
34
|
children: React.ReactNode;
|
|
35
|
+
markerMaxCacheSize?: number;
|
|
36
|
+
polygonMaxCacheSize?: number;
|
|
32
37
|
}>;
|
|
33
38
|
/**
|
|
34
39
|
* Canvas Context Hook
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
|
+
var performance = require('./performance.js');
|
|
6
7
|
var MintMapProvider = require('../../provider/MintMapProvider.js');
|
|
7
8
|
|
|
8
9
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -21,7 +22,11 @@ var CanvasContext = React.createContext(null);
|
|
|
21
22
|
/* eslint-disable no-continue */
|
|
22
23
|
|
|
23
24
|
var CanvasProvider = function (_a) {
|
|
24
|
-
var children = _a.children
|
|
25
|
+
var children = _a.children,
|
|
26
|
+
_b = _a.markerMaxCacheSize,
|
|
27
|
+
markerMaxCacheSize = _b === void 0 ? 5000 : _b,
|
|
28
|
+
_c = _a.polygonMaxCacheSize,
|
|
29
|
+
polygonMaxCacheSize = _c === void 0 ? 30000 : _c;
|
|
25
30
|
var controller = MintMapProvider.useMintMapController(); // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
31
|
|
|
27
32
|
var componentsRef = React.useRef([]); // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -29,7 +34,10 @@ var CanvasProvider = function (_a) {
|
|
|
29
34
|
var currentHoveredRef = React.useRef(null); // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
35
|
|
|
31
36
|
var currentHoveredDataRef = React.useRef(null);
|
|
32
|
-
var draggingRef = React.useRef(false); //
|
|
37
|
+
var draggingRef = React.useRef(false); // 공유 캐시 (모든 레이어가 공유)
|
|
38
|
+
|
|
39
|
+
var sharedMarkerCacheRef = React.useRef(new performance.QueueCache(markerMaxCacheSize));
|
|
40
|
+
var sharedPolygonCacheRef = React.useRef(new performance.QueueCache(polygonMaxCacheSize)); // 컴포넌트 등록 (zIndex 내림차순 정렬)
|
|
33
41
|
|
|
34
42
|
var registerComponent = React.useCallback(function (instance) {
|
|
35
43
|
componentsRef.current.push(instance);
|
|
@@ -199,6 +207,8 @@ var CanvasProvider = function (_a) {
|
|
|
199
207
|
var contextValue = React.useMemo(function () {
|
|
200
208
|
return {
|
|
201
209
|
registerComponent: registerComponent,
|
|
210
|
+
sharedMarkerCache: sharedMarkerCacheRef.current,
|
|
211
|
+
sharedPolygonCache: sharedPolygonCacheRef.current,
|
|
202
212
|
unregisterComponent: unregisterComponent
|
|
203
213
|
};
|
|
204
214
|
}, [registerComponent, unregisterComponent]);
|
|
@@ -21,7 +21,7 @@ export interface EventHandlerDeps<T> {
|
|
|
21
21
|
containerRef: MutableRefObject<HTMLDivElement | null>;
|
|
22
22
|
controller: MintMapController;
|
|
23
23
|
markerRef: MutableRefObject<Marker | undefined>;
|
|
24
|
-
|
|
24
|
+
clearCache: () => void;
|
|
25
25
|
options: Pick<MarkerOptions, 'anchor' | 'visible' | 'zIndex'>;
|
|
26
26
|
prevCenterOffsetRef: MutableRefObject<{
|
|
27
27
|
x: number;
|
|
@@ -17,10 +17,10 @@ var tslib = require('tslib');
|
|
|
17
17
|
var createMapEventHandlers = function (deps) {
|
|
18
18
|
var accumTranslateRef = deps.accumTranslateRef,
|
|
19
19
|
boundingBoxCacheRef = deps.boundingBoxCacheRef,
|
|
20
|
+
clearCache = deps.clearCache,
|
|
20
21
|
containerRef = deps.containerRef,
|
|
21
22
|
controller = deps.controller,
|
|
22
23
|
markerRef = deps.markerRef,
|
|
23
|
-
offsetCacheRef = deps.offsetCacheRef,
|
|
24
24
|
options = deps.options,
|
|
25
25
|
prevCenterOffsetRef = deps.prevCenterOffsetRef,
|
|
26
26
|
renderAllImmediate = deps.renderAllImmediate; // 지도 이동/줌 완료 시 처리 (캐시 초기화 및 렌더링)
|
|
@@ -32,7 +32,7 @@ var createMapEventHandlers = function (deps) {
|
|
|
32
32
|
y: 0
|
|
33
33
|
}; // 캐시 정리 (지도 이동/줌으로 좌표 변환 결과가 바뀜)
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
clearCache();
|
|
36
36
|
boundingBoxCacheRef.current.clear(); // 마커 위치 업데이트
|
|
37
37
|
|
|
38
38
|
var bounds = controller.getCurrBounds();
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 공간 인덱스 그리드 셀 크기 (픽셀 단위)
|
|
3
3
|
*
|
|
4
|
-
* @default
|
|
4
|
+
* @default 200
|
|
5
5
|
*
|
|
6
6
|
* @remarks
|
|
7
7
|
* 셀 크기는 평균 마커 크기의 1.5~2배가 적절합니다.
|
|
8
8
|
* - 마커가 50px 이하: 50px 권장
|
|
9
|
-
* - 마커가 60-80px: 100px 권장
|
|
10
|
-
* - 마커가 100px 이상: 150-200px 권장
|
|
9
|
+
* - 마커가 60-80px: 100px 권장
|
|
10
|
+
* - 마커가 100px 이상: 150-200px 권장 (현재 설정)
|
|
11
11
|
*
|
|
12
12
|
* 셀 크기가 너무 작으면:
|
|
13
13
|
* - 한 마커가 여러 셀에 등록되어 메모리 사용량 증가
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* - 한 셀에 많은 마커가 들어가서 Hit Test 시 후보 항목이 많아짐
|
|
18
18
|
* - Hit Test 성능 저하
|
|
19
19
|
*/
|
|
20
|
-
export declare const SPATIAL_GRID_CELL_SIZE =
|
|
20
|
+
export declare const SPATIAL_GRID_CELL_SIZE = 200;
|
|
21
21
|
/**
|
|
22
22
|
* 뷰포트 컬링 여유 공간 (픽셀 단위)
|
|
23
23
|
*
|
|
@@ -48,6 +48,8 @@ export declare class QueueCache<K, V> {
|
|
|
48
48
|
clear(): void;
|
|
49
49
|
size(): number;
|
|
50
50
|
has(key: K): boolean;
|
|
51
|
+
getAllKeys(): K[];
|
|
52
|
+
getAllEntries(): Array<[K, V]>;
|
|
51
53
|
}
|
|
52
54
|
/**
|
|
53
55
|
* Spatial Hash Grid (공간 해시 그리드)
|
|
@@ -75,4 +77,6 @@ export declare class SpatialHashGrid<T> {
|
|
|
75
77
|
totalCells: number;
|
|
76
78
|
totalItems: number;
|
|
77
79
|
};
|
|
80
|
+
getAllCells(): Map<string, T[]>;
|
|
81
|
+
getCellItems(cellKey: string): T[];
|
|
78
82
|
}
|
|
@@ -9,13 +9,13 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
9
9
|
/**
|
|
10
10
|
* 공간 인덱스 그리드 셀 크기 (픽셀 단위)
|
|
11
11
|
*
|
|
12
|
-
* @default
|
|
12
|
+
* @default 200
|
|
13
13
|
*
|
|
14
14
|
* @remarks
|
|
15
15
|
* 셀 크기는 평균 마커 크기의 1.5~2배가 적절합니다.
|
|
16
16
|
* - 마커가 50px 이하: 50px 권장
|
|
17
|
-
* - 마커가 60-80px: 100px 권장
|
|
18
|
-
* - 마커가 100px 이상: 150-200px 권장
|
|
17
|
+
* - 마커가 60-80px: 100px 권장
|
|
18
|
+
* - 마커가 100px 이상: 150-200px 권장 (현재 설정)
|
|
19
19
|
*
|
|
20
20
|
* 셀 크기가 너무 작으면:
|
|
21
21
|
* - 한 마커가 여러 셀에 등록되어 메모리 사용량 증가
|
|
@@ -25,7 +25,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
25
25
|
* - 한 셀에 많은 마커가 들어가서 Hit Test 시 후보 항목이 많아짐
|
|
26
26
|
* - Hit Test 성능 저하
|
|
27
27
|
*/
|
|
28
|
-
var SPATIAL_GRID_CELL_SIZE =
|
|
28
|
+
var SPATIAL_GRID_CELL_SIZE = 200;
|
|
29
29
|
/**
|
|
30
30
|
* 뷰포트 컬링 여유 공간 (픽셀 단위)
|
|
31
31
|
*
|
|
@@ -100,6 +100,16 @@ function () {
|
|
|
100
100
|
|
|
101
101
|
QueueCache.prototype.has = function (key) {
|
|
102
102
|
return this.cache.has(key);
|
|
103
|
+
}; // 모든 캐시 키 반환 (디버깅/모니터링용)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
QueueCache.prototype.getAllKeys = function () {
|
|
107
|
+
return Array.from(this.cache.keys());
|
|
108
|
+
}; // 모든 캐시 항목 반환 (디버깅/모니터링용)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
QueueCache.prototype.getAllEntries = function () {
|
|
112
|
+
return Array.from(this.cache.entries());
|
|
103
113
|
};
|
|
104
114
|
|
|
105
115
|
return QueueCache;
|
|
@@ -256,6 +266,16 @@ function () {
|
|
|
256
266
|
totalCells: this.grid.size,
|
|
257
267
|
totalItems: this.itemToCells.size
|
|
258
268
|
};
|
|
269
|
+
}; // 모든 그리드 셀 데이터 반환 (디버깅/모니터링용)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
SpatialHashGrid.prototype.getAllCells = function () {
|
|
273
|
+
return new Map(this.grid);
|
|
274
|
+
}; // 특정 셀의 항목 조회
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
SpatialHashGrid.prototype.getCellItems = function (cellKey) {
|
|
278
|
+
return this.grid.get(cellKey) || [];
|
|
259
279
|
};
|
|
260
280
|
|
|
261
281
|
return SpatialHashGrid;
|