@mint-ui/map 1.2.0-test.65 → 1.2.0-test.67
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.d.ts +2 -122
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/CanvasMarkerLayer.js +129 -180
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/index.d.ts +1 -0
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/types.d.ts +252 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/CanvasPolygonLayer.d.ts +2 -279
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/index.d.ts +1 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/types.d.ts +280 -0
- package/dist/components/mint-map/core/advanced/shared/types.d.ts +2 -2
- package/dist/index.es.js +127 -178
- package/dist/index.umd.js +127 -178
- package/package.json +1 -1
|
@@ -1,128 +1,8 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import {
|
|
3
|
-
import { CanvasData, CustomRenderBase, CustomRenderEvent } from '../shared';
|
|
2
|
+
import type { CanvasMarkerLayerProps } from './types';
|
|
4
3
|
export { CanvasDataType, CanvasProvider, LRUCache, SpatialHashGrid } from '../shared';
|
|
5
4
|
export type { CanvasData, CanvasOption, CustomRenderBase, CustomRenderEvent, MarkerBoundingBox, RenderBaseParams, RenderEventParams, RenderUtils } from '../shared';
|
|
6
|
-
|
|
7
|
-
* CanvasMarkerLayer Props (renderEvent가 없는 경우 - 인터랙션 불가)
|
|
8
|
-
*
|
|
9
|
-
* @template T 마커 데이터의 추가 속성 타입
|
|
10
|
-
*/
|
|
11
|
-
interface CanvasMarkerLayerPropsWithoutEvent<T> extends Pick<MarkerOptions, 'zIndex' | 'anchor' | 'visible'> {
|
|
12
|
-
/** 렌더링할 마커 데이터 배열 */
|
|
13
|
-
data: CanvasData<T>[];
|
|
14
|
-
/** 뷰포트 컬링 활성화 여부 (기본값: false) */
|
|
15
|
-
enableViewportCulling?: boolean;
|
|
16
|
-
/** 뷰포트 컬링 여유 공간 (픽셀 단위, 기본값: 100) */
|
|
17
|
-
cullingMargin?: number;
|
|
18
|
-
/** LRU 캐시 최대 크기 (기본값: 10000) */
|
|
19
|
-
maxCacheSize?: number;
|
|
20
|
-
/** Base Layer 렌더링 함수 (필수) */
|
|
21
|
-
renderBase: CustomRenderBase<T>;
|
|
22
|
-
/** Event Layer 렌더링 함수가 없으면 인터랙션 관련 props 사용 불가 */
|
|
23
|
-
renderEvent?: never;
|
|
24
|
-
/** 인터랙션 관련 props는 renderEvent가 있을 때만 사용 가능 */
|
|
25
|
-
onClick?: never;
|
|
26
|
-
onMouseOver?: never;
|
|
27
|
-
onMouseOut?: never;
|
|
28
|
-
enableMultiSelect?: never;
|
|
29
|
-
topOnHover?: never;
|
|
30
|
-
selectedItems?: never;
|
|
31
|
-
selectedItem?: never;
|
|
32
|
-
disableInteraction?: never;
|
|
33
|
-
topStageZIndex?: never;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* CanvasMarkerLayer Props (renderEvent가 있는 경우 - 인터랙션 가능)
|
|
37
|
-
* topStageZIndex가 없을 때
|
|
38
|
-
*
|
|
39
|
-
* @template T 마커 데이터의 추가 속성 타입
|
|
40
|
-
*/
|
|
41
|
-
interface CanvasMarkerLayerPropsWithEventBase<T> extends Pick<MarkerOptions, 'zIndex' | 'anchor' | 'visible'> {
|
|
42
|
-
/** 렌더링할 마커 데이터 배열 */
|
|
43
|
-
data: CanvasData<T>[];
|
|
44
|
-
/** 마커 클릭 시 호출되는 콜백 함수 */
|
|
45
|
-
onClick?: (payload: CanvasData<T>, selectedIds: Set<string>) => void;
|
|
46
|
-
/** 마커에 마우스 오버 시 호출되는 콜백 함수 */
|
|
47
|
-
onMouseOver?: (payload: CanvasData<T>) => void;
|
|
48
|
-
/** 마커에서 마우스 아웃 시 호출되는 콜백 함수 */
|
|
49
|
-
onMouseOut?: (payload: CanvasData<T>) => void;
|
|
50
|
-
/** 다중 선택 활성화 여부 (기본값: false) */
|
|
51
|
-
enableMultiSelect?: boolean;
|
|
52
|
-
/** hover 시 마커를 최상단으로 표시할지 여부 (기본값: false) */
|
|
53
|
-
topOnHover?: boolean;
|
|
54
|
-
/** 뷰포트 컬링 활성화 여부 (기본값: false) */
|
|
55
|
-
enableViewportCulling?: boolean;
|
|
56
|
-
/** 뷰포트 컬링 여유 공간 (픽셀 단위, 기본값: 100) */
|
|
57
|
-
cullingMargin?: number;
|
|
58
|
-
/** LRU 캐시 최대 크기 (기본값: 10000) */
|
|
59
|
-
maxCacheSize?: number;
|
|
60
|
-
/** 외부에서 제어하는 선택된 항목 배열 */
|
|
61
|
-
selectedItems?: CanvasData<T>[];
|
|
62
|
-
/** 외부에서 전달된 단일 선택 아이템 */
|
|
63
|
-
selectedItem?: CanvasData<T> | null;
|
|
64
|
-
/** 상호작용 비활성화 여부 (기본값: false) */
|
|
65
|
-
disableInteraction?: boolean;
|
|
66
|
-
/** Base Layer 렌더링 함수 (필수) */
|
|
67
|
-
renderBase: CustomRenderBase<T>;
|
|
68
|
-
/** Event Layer 렌더링 함수 (필수 - 인터랙션 사용 시) */
|
|
69
|
-
renderEvent: CustomRenderEvent<T>;
|
|
70
|
-
/** Top Layer의 zIndex (hover된 항목을 최상단에 렌더링하기 위한 레이어, topOnHover가 true일 때만 사용 가능) */
|
|
71
|
-
topStageZIndex?: never;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* CanvasMarkerLayer Props (renderEvent가 있는 경우 - 인터랙션 가능)
|
|
75
|
-
* topStageZIndex가 있을 때 (topOnHover가 반드시 true여야 함)
|
|
76
|
-
*
|
|
77
|
-
* @template T 마커 데이터의 추가 속성 타입
|
|
78
|
-
*/
|
|
79
|
-
interface CanvasMarkerLayerPropsWithEventWithTopStage<T> extends Pick<MarkerOptions, 'zIndex' | 'anchor' | 'visible'> {
|
|
80
|
-
/** 렌더링할 마커 데이터 배열 */
|
|
81
|
-
data: CanvasData<T>[];
|
|
82
|
-
/** 마커 클릭 시 호출되는 콜백 함수 */
|
|
83
|
-
onClick?: (payload: CanvasData<T>, selectedIds: Set<string>) => void;
|
|
84
|
-
/** 마커에 마우스 오버 시 호출되는 콜백 함수 */
|
|
85
|
-
onMouseOver?: (payload: CanvasData<T>) => void;
|
|
86
|
-
/** 마커에서 마우스 아웃 시 호출되는 콜백 함수 */
|
|
87
|
-
onMouseOut?: (payload: CanvasData<T>) => void;
|
|
88
|
-
/** 다중 선택 활성화 여부 (기본값: false) */
|
|
89
|
-
enableMultiSelect?: boolean;
|
|
90
|
-
/** hover 시 마커를 최상단으로 표시할지 여부 (topStageZIndex 사용 시 반드시 true) */
|
|
91
|
-
topOnHover: true;
|
|
92
|
-
/** 뷰포트 컬링 활성화 여부 (기본값: false) */
|
|
93
|
-
enableViewportCulling?: boolean;
|
|
94
|
-
/** 뷰포트 컬링 여유 공간 (픽셀 단위, 기본값: 100) */
|
|
95
|
-
cullingMargin?: number;
|
|
96
|
-
/** LRU 캐시 최대 크기 (기본값: 10000) */
|
|
97
|
-
maxCacheSize?: number;
|
|
98
|
-
/** 외부에서 제어하는 선택된 항목 배열 */
|
|
99
|
-
selectedItems?: CanvasData<T>[];
|
|
100
|
-
/** 외부에서 전달된 단일 선택 아이템 */
|
|
101
|
-
selectedItem?: CanvasData<T> | null;
|
|
102
|
-
/** 상호작용 비활성화 여부 (기본값: false) */
|
|
103
|
-
disableInteraction?: boolean;
|
|
104
|
-
/** Base Layer 렌더링 함수 (필수) */
|
|
105
|
-
renderBase: CustomRenderBase<T>;
|
|
106
|
-
/** Event Layer 렌더링 함수 (필수 - 인터랙션 사용 시) */
|
|
107
|
-
renderEvent: CustomRenderEvent<T>;
|
|
108
|
-
/** Top Layer의 zIndex (hover된 항목을 최상단에 렌더링하기 위한 레이어, topOnHover가 true일 때만 사용 가능) */
|
|
109
|
-
topStageZIndex: number;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* CanvasMarkerLayer Props (renderEvent가 있는 경우 - 인터랙션 가능)
|
|
113
|
-
*
|
|
114
|
-
* @template T 마커 데이터의 추가 속성 타입
|
|
115
|
-
*/
|
|
116
|
-
declare type CanvasMarkerLayerPropsWithEvent<T> = CanvasMarkerLayerPropsWithEventBase<T> | CanvasMarkerLayerPropsWithEventWithTopStage<T>;
|
|
117
|
-
/**
|
|
118
|
-
* CanvasMarkerLayer Props
|
|
119
|
-
*
|
|
120
|
-
* renderEvent가 없으면 인터랙션 관련 props를 사용할 수 없습니다.
|
|
121
|
-
* renderEvent가 있으면 모든 인터랙션 관련 props를 사용할 수 있습니다.
|
|
122
|
-
*
|
|
123
|
-
* @template T 마커 데이터의 추가 속성 타입
|
|
124
|
-
*/
|
|
125
|
-
export declare type CanvasMarkerLayerProps<T> = CanvasMarkerLayerPropsWithoutEvent<T> | CanvasMarkerLayerPropsWithEvent<T>;
|
|
5
|
+
export type { CanvasMarkerLayerProps, CanvasMarkerLayerPropsWithEvent, CanvasMarkerLayerPropsWithEventWithoutSelection, CanvasMarkerLayerPropsWithEventWithSelectedItem, CanvasMarkerLayerPropsWithEventWithSelectedItems, CanvasMarkerLayerPropsWithEventWithTopStageWithoutSelection, CanvasMarkerLayerPropsWithEventWithTopStageWithSelectedItem, CanvasMarkerLayerPropsWithEventWithTopStageWithSelectedItems, CanvasMarkerLayerPropsWithoutEvent } from './types';
|
|
126
6
|
declare const CanvasMarkerLayer: <T>(props: CanvasMarkerLayerProps<T>) => JSX.Element;
|
|
127
7
|
/**
|
|
128
8
|
* CanvasMarkerLayer - Konva 기반 고성능 마커 렌더링 컴포넌트
|
|
@@ -40,32 +40,26 @@ var CanvasMarkerLayer = function (props) {
|
|
|
40
40
|
|
|
41
41
|
var _d = hasRenderEvent && 'renderEvent' in props ? props : {
|
|
42
42
|
disableInteraction: false,
|
|
43
|
-
enableMultiSelect: false,
|
|
44
43
|
onClick: undefined,
|
|
45
44
|
onMouseOut: undefined,
|
|
46
45
|
onMouseOver: undefined,
|
|
47
46
|
renderEvent: undefined,
|
|
48
47
|
selectedItem: undefined,
|
|
49
48
|
selectedItems: undefined,
|
|
50
|
-
topOnHover: false,
|
|
51
49
|
topStageZIndex: undefined
|
|
52
50
|
},
|
|
53
51
|
_e = _d.disableInteraction,
|
|
54
52
|
disableInteraction = _e === void 0 ? false : _e,
|
|
55
|
-
_f = _d.enableMultiSelect,
|
|
56
|
-
enableMultiSelect = _f === void 0 ? false : _f,
|
|
57
53
|
onClick = _d.onClick,
|
|
58
54
|
onMouseOut = _d.onMouseOut,
|
|
59
55
|
onMouseOver = _d.onMouseOver,
|
|
60
56
|
renderEvent = _d.renderEvent,
|
|
61
57
|
externalSelectedItem = _d.selectedItem,
|
|
62
58
|
externalSelectedItems = _d.selectedItems,
|
|
63
|
-
rawTopStageZIndex = _d.topStageZIndex
|
|
64
|
-
_g = _d.topOnHover,
|
|
65
|
-
topOnHover = _g === void 0 ? false : _g; // topOnHover가 false이거나 없으면 topStageZIndex를 사용하지 못하도록 제한
|
|
59
|
+
rawTopStageZIndex = _d.topStageZIndex; // topStageZIndex가 있으면 hover 최상단 표시 활성화, 없으면 비활성화 (성능 우선)
|
|
66
60
|
|
|
67
61
|
|
|
68
|
-
var topStageZIndex =
|
|
62
|
+
var topStageZIndex = rawTopStageZIndex;
|
|
69
63
|
var controller = MintMapProvider.useMintMapController();
|
|
70
64
|
var context$1 = context.useCanvasContext();
|
|
71
65
|
var currentZIndex = options.zIndex !== undefined ? options.zIndex : 0; // DOM Refs
|
|
@@ -170,49 +164,20 @@ var CanvasMarkerLayer = function (props) {
|
|
|
170
164
|
name: 'base-render-shape',
|
|
171
165
|
perfectDrawEnabled: false,
|
|
172
166
|
sceneFunc: function (konvaContext) {
|
|
173
|
-
var ctx = konvaContext;
|
|
174
|
-
var hovered = hoveredItemRef.current; // 뷰포트 컬링: 화면에 보이는 항목만 필터링
|
|
167
|
+
var ctx = konvaContext; // 뷰포트 컬링: 화면에 보이는 항목만 필터링
|
|
175
168
|
|
|
176
169
|
var visibleItems = enableViewportCullingRef.current ? dataRef.current.filter(function (item) {
|
|
177
170
|
return isInViewport(item);
|
|
178
|
-
}) : dataRef.current; //
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
if (topStageZIndex !== undefined && topOnHover && hovered) {
|
|
182
|
-
visibleItems = visibleItems.filter(function (item) {
|
|
183
|
-
return item.id !== hovered.id;
|
|
184
|
-
});
|
|
185
|
-
} else if (topOnHover && !renderEvent && hovered) {
|
|
186
|
-
visibleItems = visibleItems.filter(function (item) {
|
|
187
|
-
return item.id !== hovered.id;
|
|
188
|
-
});
|
|
189
|
-
} // 일반 항목들 먼저 렌더링
|
|
190
|
-
// topOnHover가 false이고 renderEvent가 있으면 선택된 항목도 Base Layer에서 렌더링
|
|
191
|
-
// (Event Layer에서 선택된 항목을 렌더링하지 않으므로)
|
|
192
|
-
// topOnHover가 true이거나 renderEvent가 없으면 선택된 항목은 Base Layer에서 스킵됨
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
var baseSelectedIds = !topOnHover && renderEvent ? selectedIdsRef.current : new Set();
|
|
171
|
+
}) : dataRef.current; // Base Layer는 기본 마커만 렌더링 (hover된 항목도 포함)
|
|
172
|
+
// hover 스타일은 Event Layer와 Top Layer에서 덧그려짐
|
|
173
|
+
|
|
196
174
|
renderBase({
|
|
197
175
|
ctx: ctx,
|
|
198
|
-
hoveredItem:
|
|
176
|
+
hoveredItem: null,
|
|
199
177
|
items: visibleItems,
|
|
200
|
-
selectedIds:
|
|
178
|
+
selectedIds: new Set(),
|
|
201
179
|
utils: renderUtils
|
|
202
|
-
});
|
|
203
|
-
// hover된 항목을 마지막에 렌더링하여 최상위에 표시
|
|
204
|
-
|
|
205
|
-
if (topStageZIndex === undefined && topOnHover && !renderEvent && hovered) {
|
|
206
|
-
if (!enableViewportCullingRef.current || isInViewport(hovered)) {
|
|
207
|
-
renderBase({
|
|
208
|
-
ctx: ctx,
|
|
209
|
-
hoveredItem: hovered,
|
|
210
|
-
items: [hovered],
|
|
211
|
-
selectedIds: selectedIdsRef.current,
|
|
212
|
-
utils: renderUtils
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
}
|
|
180
|
+
});
|
|
216
181
|
}
|
|
217
182
|
});
|
|
218
183
|
layer.add(shape);
|
|
@@ -236,67 +201,30 @@ var CanvasMarkerLayer = function (props) {
|
|
|
236
201
|
sceneFunc: function (konvaContext) {
|
|
237
202
|
var ctx = konvaContext;
|
|
238
203
|
var selectedItems = helpers.mapValuesToArray(selectedItemsMapRef.current);
|
|
239
|
-
var hovered = hoveredItemRef.current; //
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
ctx: ctx,
|
|
250
|
-
hoveredItem: null,
|
|
251
|
-
selectedItem: selectedItemRef.current,
|
|
252
|
-
selectedItems: selectedItemsWithoutHovered,
|
|
253
|
-
topOnHover: topOnHover,
|
|
254
|
-
utils: renderUtils
|
|
255
|
-
});
|
|
256
|
-
} else if (topOnHover && hovered) {
|
|
257
|
-
renderEvent({
|
|
258
|
-
ctx: ctx,
|
|
259
|
-
hoveredItem: null,
|
|
260
|
-
selectedItem: selectedItemRef.current,
|
|
261
|
-
selectedItems: selectedItems.filter(function (item) {
|
|
262
|
-
return item.id !== hovered.id;
|
|
263
|
-
}),
|
|
264
|
-
topOnHover: topOnHover,
|
|
265
|
-
utils: renderUtils
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
if (!enableViewportCullingRef.current || isInViewport(hovered)) {
|
|
269
|
-
var hoveredIsSelected = selectedItems.some(function (item) {
|
|
270
|
-
return item.id === hovered.id;
|
|
271
|
-
});
|
|
272
|
-
var hoverSelectedItems = hoveredIsSelected ? [hovered] : [];
|
|
273
|
-
renderEvent({
|
|
274
|
-
ctx: ctx,
|
|
275
|
-
hoveredItem: hovered,
|
|
276
|
-
selectedItem: selectedItemRef.current,
|
|
277
|
-
selectedItems: hoverSelectedItems,
|
|
278
|
-
topOnHover: topOnHover,
|
|
279
|
-
utils: renderUtils
|
|
280
|
-
});
|
|
204
|
+
var hovered = hoveredItemRef.current; // selectedItem이 있으면 selectedItems 배열에 포함 (renderMarkerEvent가 selectedItems만 사용하므로)
|
|
205
|
+
|
|
206
|
+
if (selectedItemRef.current) {
|
|
207
|
+
// selectedItem이 이미 selectedItems에 포함되어 있지 않으면 추가
|
|
208
|
+
var selectedItemId_1 = selectedItemRef.current.id;
|
|
209
|
+
|
|
210
|
+
if (!selectedItems.some(function (item) {
|
|
211
|
+
return item.id === selectedItemId_1;
|
|
212
|
+
})) {
|
|
213
|
+
selectedItems = tslib.__spreadArray(tslib.__spreadArray([], selectedItems, true), [selectedItemRef.current], false);
|
|
281
214
|
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
selectedItems: finalSelectedItems,
|
|
296
|
-
topOnHover: topOnHover,
|
|
297
|
-
utils: renderUtils
|
|
298
|
-
});
|
|
299
|
-
}
|
|
215
|
+
} // Event Layer는 hover 효과 및 선택 상태를 덧그림
|
|
216
|
+
// topStageZIndex가 있으면 hover된 항목은 Top Stage에서도 처리되지만,
|
|
217
|
+
// Event Layer에서도 hover 스타일을 덧그려서 Base Layer 위에 표시됨
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
renderEvent({
|
|
221
|
+
ctx: ctx,
|
|
222
|
+
hasTopStage: topStageZIndex !== undefined,
|
|
223
|
+
hoveredItem: hovered,
|
|
224
|
+
selectedItem: selectedItemRef.current,
|
|
225
|
+
selectedItems: selectedItems,
|
|
226
|
+
utils: renderUtils
|
|
227
|
+
});
|
|
300
228
|
}
|
|
301
229
|
});
|
|
302
230
|
layer.add(shape);
|
|
@@ -309,7 +237,7 @@ var CanvasMarkerLayer = function (props) {
|
|
|
309
237
|
var doRenderTop = function () {
|
|
310
238
|
var stage = topStageRef.current;
|
|
311
239
|
var layer = topLayerRef.current;
|
|
312
|
-
if (!stage || !layer || topStageZIndex === undefined
|
|
240
|
+
if (!stage || !layer || topStageZIndex === undefined) return;
|
|
313
241
|
var hovered = hoveredItemRef.current;
|
|
314
242
|
var shape = layer.findOne('.top-render-shape'); // hover된 항목이 없으면 shape 제거
|
|
315
243
|
|
|
@@ -337,6 +265,8 @@ var CanvasMarkerLayer = function (props) {
|
|
|
337
265
|
|
|
338
266
|
|
|
339
267
|
shape.sceneFunc(function (konvaContext) {
|
|
268
|
+
var _a;
|
|
269
|
+
|
|
340
270
|
var ctx = konvaContext;
|
|
341
271
|
var currentHovered = hoveredItemRef.current; // hover된 항목이 없으면 아무것도 그리지 않음
|
|
342
272
|
|
|
@@ -346,10 +276,11 @@ var CanvasMarkerLayer = function (props) {
|
|
|
346
276
|
return;
|
|
347
277
|
}
|
|
348
278
|
|
|
349
|
-
var selectedItems = helpers.mapValuesToArray(selectedItemsMapRef.current);
|
|
279
|
+
var selectedItems = helpers.mapValuesToArray(selectedItemsMapRef.current); // selectedItem이 있으면 hover된 항목이 선택되었는지 확인
|
|
280
|
+
|
|
350
281
|
var hoveredIsSelected = selectedItems.some(function (item) {
|
|
351
282
|
return item.id === currentHovered.id;
|
|
352
|
-
}); // Top Layer에서는 hover된 마커만 hover 스타일로 그리기
|
|
283
|
+
}) || ((_a = selectedItemRef.current) === null || _a === void 0 ? void 0 : _a.id) === currentHovered.id; // Top Layer에서는 hover된 마커만 hover 스타일로 그리기
|
|
353
284
|
// renderEvent가 있으면: base는 그리지 않고 event만 그리기 (hover 스타일 적용)
|
|
354
285
|
// renderEvent가 없으면: base를 hover 스타일로 그리기
|
|
355
286
|
|
|
@@ -358,10 +289,10 @@ var CanvasMarkerLayer = function (props) {
|
|
|
358
289
|
var hoverSelectedItems = hoveredIsSelected ? [currentHovered] : [];
|
|
359
290
|
renderEvent({
|
|
360
291
|
ctx: ctx,
|
|
292
|
+
hasTopStage: true,
|
|
361
293
|
hoveredItem: currentHovered,
|
|
362
294
|
selectedItem: selectedItemRef.current,
|
|
363
295
|
selectedItems: hoverSelectedItems,
|
|
364
|
-
topOnHover: topOnHover,
|
|
365
296
|
utils: renderUtils
|
|
366
297
|
});
|
|
367
298
|
} else {
|
|
@@ -392,13 +323,13 @@ var CanvasMarkerLayer = function (props) {
|
|
|
392
323
|
topContainerRef.current.style.transform = containerRef.current.style.transform || '';
|
|
393
324
|
}
|
|
394
325
|
|
|
395
|
-
if (topStageZIndex !== undefined
|
|
326
|
+
if (topStageZIndex !== undefined) {
|
|
396
327
|
doRenderTop();
|
|
397
328
|
}
|
|
398
329
|
}; // 지도 이벤트 핸들러 생성
|
|
399
330
|
|
|
400
331
|
|
|
401
|
-
var
|
|
332
|
+
var _f = hooks.createMapEventHandlers({
|
|
402
333
|
accumTranslateRef: accumTranslateRef,
|
|
403
334
|
boundingBoxCacheRef: boundingBoxCacheRef,
|
|
404
335
|
containerRef: containerRef,
|
|
@@ -409,12 +340,30 @@ var CanvasMarkerLayer = function (props) {
|
|
|
409
340
|
prevCenterOffsetRef: prevCenterOffsetRef,
|
|
410
341
|
renderAllImmediate: renderAllImmediate
|
|
411
342
|
}),
|
|
412
|
-
|
|
413
|
-
handleZoomStart =
|
|
414
|
-
handleZoomEnd =
|
|
415
|
-
|
|
416
|
-
handleDragStartShared =
|
|
417
|
-
handleDragEndShared =
|
|
343
|
+
handleIdleShared = _f.handleIdle,
|
|
344
|
+
handleZoomStart = _f.handleZoomStart,
|
|
345
|
+
handleZoomEnd = _f.handleZoomEnd,
|
|
346
|
+
handleCenterChangedShared = _f.handleCenterChanged,
|
|
347
|
+
handleDragStartShared = _f.handleDragStart,
|
|
348
|
+
handleDragEndShared = _f.handleDragEnd; // handleIdle 래핑: topStage transform 제거 추가
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
var handleIdle = function () {
|
|
352
|
+
handleIdleShared(); // 드래그 완료 시 topStage의 transform도 제거 (메인 stage와 동기화)
|
|
353
|
+
|
|
354
|
+
if (topStageZIndex !== undefined && topContainerRef.current) {
|
|
355
|
+
topContainerRef.current.style.transform = '';
|
|
356
|
+
}
|
|
357
|
+
}; // handleCenterChanged 래핑: topStage transform 동기화 추가
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
var handleCenterChanged = function () {
|
|
361
|
+
handleCenterChangedShared(); // 드래그 중 메인 stage의 transform을 topStage에도 동기화 (반대 방향 이동 방지)
|
|
362
|
+
|
|
363
|
+
if (topStageZIndex !== undefined && topContainerRef.current && containerRef.current) {
|
|
364
|
+
topContainerRef.current.style.transform = containerRef.current.style.transform || '';
|
|
365
|
+
}
|
|
366
|
+
};
|
|
418
367
|
|
|
419
368
|
var handleDragStart = function () {
|
|
420
369
|
handleDragStartShared(); // 드래그 시작 시점의 hover 상태 저장
|
|
@@ -442,8 +391,8 @@ var CanvasMarkerLayer = function (props) {
|
|
|
442
391
|
|
|
443
392
|
|
|
444
393
|
var findData = function (offset) {
|
|
445
|
-
//
|
|
446
|
-
if (
|
|
394
|
+
// topStageZIndex가 설정되어 있으면 hover된 항목을 최우선으로 확인
|
|
395
|
+
if (topStageZIndex !== undefined && hoveredItemRef.current) {
|
|
447
396
|
var hovered = hoveredItemRef.current;
|
|
448
397
|
|
|
449
398
|
if (utils.isPointInMarkerData(offset, hovered, getOrComputeMarkerOffset)) {
|
|
@@ -480,57 +429,40 @@ var CanvasMarkerLayer = function (props) {
|
|
|
480
429
|
controller.setMapCursor(hoveredData ? 'pointer' : 'grab');
|
|
481
430
|
}
|
|
482
431
|
|
|
483
|
-
if (topStageZIndex !== undefined
|
|
484
|
-
// topStageZIndex가
|
|
485
|
-
//
|
|
486
|
-
|
|
432
|
+
if (topStageZIndex !== undefined) {
|
|
433
|
+
// topStageZIndex가 설정된 경우 Top Layer에서 hover된 항목 렌더링
|
|
434
|
+
// Base Layer는 모든 마커를 포함하므로 hover 상태 변경 시 재렌더링 불필요
|
|
435
|
+
// Event Layer는 hover 스타일과 선택된 항목을 렌더링하므로 업데이트 필요
|
|
487
436
|
doRenderEvent();
|
|
488
437
|
doRenderTop();
|
|
489
438
|
} else if (renderEvent) {
|
|
490
|
-
// renderEvent가 있을 때는 Event Layer 업데이트
|
|
491
|
-
//
|
|
492
|
-
|
|
493
|
-
doRenderBase();
|
|
494
|
-
}
|
|
495
|
-
|
|
439
|
+
// renderEvent가 있을 때는 Event Layer만 업데이트
|
|
440
|
+
// topStageZIndex가 없으면 Base Layer는 정적이므로 재렌더링 불필요 (성능 우선)
|
|
441
|
+
// hover 효과는 Event Layer에서만 처리하면 됨
|
|
496
442
|
doRenderEvent();
|
|
497
|
-
} else if (topOnHover) {
|
|
498
|
-
doRenderBase();
|
|
499
443
|
}
|
|
500
|
-
}; // 클릭 처리: 선택 상태 업데이트
|
|
444
|
+
}; // 클릭 처리: 선택 상태 업데이트 (단일 선택만 지원)
|
|
501
445
|
|
|
502
446
|
|
|
503
447
|
var handleLocalClick = function (clickedData) {
|
|
504
|
-
|
|
505
|
-
var newSelected = new Set(selectedIdsRef.current);
|
|
448
|
+
var newSelected = new Set();
|
|
506
449
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
newSelected.add(clickedData.id);
|
|
512
|
-
selectedItemsMapRef.current.set(clickedData.id, clickedData);
|
|
513
|
-
}
|
|
450
|
+
if (!selectedIdsRef.current.has(clickedData.id)) {
|
|
451
|
+
newSelected.add(clickedData.id);
|
|
452
|
+
selectedItemsMapRef.current.clear();
|
|
453
|
+
selectedItemsMapRef.current.set(clickedData.id, clickedData); // externalSelectedItem이 있을 때를 대비해 selectedItemRef도 업데이트
|
|
514
454
|
|
|
515
|
-
|
|
455
|
+
selectedItemRef.current = clickedData;
|
|
516
456
|
} else {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
if (!selectedIdsRef.current.has(clickedData.id)) {
|
|
520
|
-
newSelected.add(clickedData.id);
|
|
521
|
-
selectedItemsMapRef.current.clear();
|
|
522
|
-
selectedItemsMapRef.current.set(clickedData.id, clickedData);
|
|
523
|
-
} else {
|
|
524
|
-
selectedItemsMapRef.current.clear();
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
selectedIdsRef.current = newSelected;
|
|
457
|
+
selectedItemsMapRef.current.clear();
|
|
458
|
+
selectedItemRef.current = null;
|
|
528
459
|
}
|
|
529
460
|
|
|
530
|
-
|
|
461
|
+
selectedIdsRef.current = newSelected; // 선택 상태 변경은 Event Layer에서만 처리 (Base Layer는 정적이므로 재렌더링 불필요)
|
|
462
|
+
|
|
531
463
|
doRenderEvent();
|
|
532
464
|
|
|
533
|
-
if (topStageZIndex !== undefined
|
|
465
|
+
if (topStageZIndex !== undefined) {
|
|
534
466
|
doRenderTop();
|
|
535
467
|
}
|
|
536
468
|
}; // 클릭 이벤트 핸들러
|
|
@@ -594,18 +526,15 @@ var CanvasMarkerLayer = function (props) {
|
|
|
594
526
|
hoveredItemRef.current = null;
|
|
595
527
|
controller.setMapCursor('grab');
|
|
596
528
|
|
|
597
|
-
if (topStageZIndex !== undefined
|
|
598
|
-
//
|
|
599
|
-
|
|
529
|
+
if (topStageZIndex !== undefined) {
|
|
530
|
+
// Base Layer는 모든 마커를 포함하므로 hover 상태 변경 시 재렌더링 불필요
|
|
531
|
+
// Event Layer는 hover 스타일과 선택된 항목을 렌더링하므로 업데이트 필요
|
|
600
532
|
doRenderEvent();
|
|
601
533
|
doRenderTop();
|
|
602
534
|
} else if (renderEvent) {
|
|
603
|
-
// renderEvent가 있을 때는 Event Layer 업데이트
|
|
604
|
-
//
|
|
605
|
-
|
|
606
|
-
doRenderBase();
|
|
607
|
-
}
|
|
608
|
-
|
|
535
|
+
// renderEvent가 있을 때는 Event Layer만 업데이트
|
|
536
|
+
// topStageZIndex가 없으면 Base Layer는 정적이므로 재렌더링 불필요 (성능 우선)
|
|
537
|
+
// hover 효과 제거는 Event Layer에서만 처리하면 됨
|
|
609
538
|
doRenderEvent();
|
|
610
539
|
}
|
|
611
540
|
|
|
@@ -614,9 +543,9 @@ var CanvasMarkerLayer = function (props) {
|
|
|
614
543
|
|
|
615
544
|
|
|
616
545
|
React.useEffect(function () {
|
|
617
|
-
divElement.style.width = 'fit-content'; // Top Layer용 div도 초기화 (topStageZIndex가
|
|
546
|
+
divElement.style.width = 'fit-content'; // Top Layer용 div도 초기화 (topStageZIndex가 설정된 경우)
|
|
618
547
|
|
|
619
|
-
if (topStageZIndex !== undefined
|
|
548
|
+
if (topStageZIndex !== undefined) {
|
|
620
549
|
topDivElement.style.width = 'fit-content';
|
|
621
550
|
}
|
|
622
551
|
|
|
@@ -802,10 +731,10 @@ var CanvasMarkerLayer = function (props) {
|
|
|
802
731
|
|
|
803
732
|
renderAllImmediate();
|
|
804
733
|
}
|
|
805
|
-
}, [enableViewportCulling]); // Top Layer용 별도 캔버스 DOM 생성 (topStageZIndex가
|
|
734
|
+
}, [enableViewportCulling]); // Top Layer용 별도 캔버스 DOM 생성 (topStageZIndex가 설정된 경우)
|
|
806
735
|
|
|
807
736
|
React.useEffect(function () {
|
|
808
|
-
if (topStageZIndex === undefined
|
|
737
|
+
if (topStageZIndex === undefined) return;
|
|
809
738
|
if (!topContainerRef.current) return;
|
|
810
739
|
var mapDiv = controller.mapDivElement; // Top Layer용 div 요소 설정
|
|
811
740
|
|
|
@@ -874,13 +803,14 @@ var CanvasMarkerLayer = function (props) {
|
|
|
874
803
|
|
|
875
804
|
|
|
876
805
|
var handleTopIdle = function () {
|
|
877
|
-
// topMarker의 position을 메인 marker와 동일하게 업데이트
|
|
806
|
+
// 드래그 완료 후 topMarker의 position을 메인 marker와 동일하게 업데이트
|
|
878
807
|
updateTopMarkerPosition(); // topStage 크기 업데이트
|
|
879
808
|
|
|
880
809
|
if (topStageRef.current) {
|
|
881
810
|
topStageRef.current.width(mapDiv.offsetWidth);
|
|
882
811
|
topStageRef.current.height(mapDiv.offsetHeight);
|
|
883
|
-
} //
|
|
812
|
+
} // 드래그 완료 후 transform은 handleIdle에서 제거되므로 여기서는 동기화만
|
|
813
|
+
// (handleIdle이 먼저 실행되어 transform을 제거한 후, 여기서 position 업데이트)
|
|
884
814
|
|
|
885
815
|
|
|
886
816
|
if (topContainerRef.current && containerRef.current) {
|
|
@@ -909,13 +839,18 @@ var CanvasMarkerLayer = function (props) {
|
|
|
909
839
|
};
|
|
910
840
|
|
|
911
841
|
var handleTopCenterChanged = function () {
|
|
912
|
-
//
|
|
913
|
-
|
|
842
|
+
// 드래그 중에는 transform만 동기화 (position 업데이트는 드래그 완료 후에만)
|
|
843
|
+
// 드래그 중에 position을 업데이트하면 transform과 충돌하여 반대 방향으로 이동하는 버그 발생
|
|
844
|
+
if (!draggingRef.current) {
|
|
845
|
+
// 드래그가 아닐 때만 topMarker의 position을 업데이트
|
|
846
|
+
updateTopMarkerPosition();
|
|
847
|
+
} // topStage 크기 업데이트
|
|
848
|
+
|
|
914
849
|
|
|
915
850
|
if (topStageRef.current) {
|
|
916
851
|
topStageRef.current.width(mapDiv.offsetWidth);
|
|
917
852
|
topStageRef.current.height(mapDiv.offsetHeight);
|
|
918
|
-
} // 메인 stage의 transform을 topStage에도 동기화
|
|
853
|
+
} // 메인 stage의 transform을 topStage에도 동기화 (드래그 중 필수)
|
|
919
854
|
|
|
920
855
|
|
|
921
856
|
if (topContainerRef.current && containerRef.current) {
|
|
@@ -957,25 +892,39 @@ var CanvasMarkerLayer = function (props) {
|
|
|
957
892
|
}, [topStageZIndex, renderEvent, options]); // 외부 selectedItems 동기화
|
|
958
893
|
|
|
959
894
|
React.useEffect(function () {
|
|
960
|
-
if (!stageRef.current) return;
|
|
961
|
-
|
|
962
|
-
|
|
895
|
+
if (!stageRef.current) return; // externalSelectedItems가 있으면 selectedItem은 무시 (공존 불가)
|
|
896
|
+
|
|
897
|
+
if (externalSelectedItems !== undefined) {
|
|
898
|
+
selectedItemRef.current = undefined;
|
|
899
|
+
hooks.syncExternalSelectedItems(externalSelectedItems, selectedIdsRef, selectedItemsMapRef);
|
|
900
|
+
} // 선택 상태 변경은 Event Layer에서만 처리 (Base Layer는 정적이므로 재렌더링 불필요)
|
|
901
|
+
|
|
902
|
+
|
|
963
903
|
doRenderEvent();
|
|
964
904
|
|
|
965
|
-
if (topStageZIndex !== undefined
|
|
905
|
+
if (topStageZIndex !== undefined) {
|
|
966
906
|
doRenderTop();
|
|
967
907
|
}
|
|
968
908
|
}, [externalSelectedItems]); // 외부 selectedItem 변경 시 Event Layer 리렌더링
|
|
969
909
|
|
|
970
910
|
React.useEffect(function () {
|
|
971
|
-
if (!stageRef.current) return;
|
|
972
|
-
|
|
911
|
+
if (!stageRef.current) return; // externalSelectedItem이 있으면 selectedItems는 무시 (공존 불가)
|
|
912
|
+
|
|
913
|
+
if (externalSelectedItem !== undefined) {
|
|
914
|
+
selectedIdsRef.current.clear();
|
|
915
|
+
selectedItemsMapRef.current.clear();
|
|
916
|
+
selectedItemRef.current = externalSelectedItem;
|
|
917
|
+
} else if (externalSelectedItems === undefined) {
|
|
918
|
+
// 둘 다 없으면 selectedItemRef만 업데이트 (내부 클릭으로 선택한 항목은 유지)
|
|
919
|
+
selectedItemRef.current = externalSelectedItem;
|
|
920
|
+
}
|
|
921
|
+
|
|
973
922
|
doRenderEvent();
|
|
974
923
|
|
|
975
|
-
if (topStageZIndex !== undefined
|
|
924
|
+
if (topStageZIndex !== undefined) {
|
|
976
925
|
doRenderTop();
|
|
977
926
|
}
|
|
978
|
-
}, [externalSelectedItem]); // 데이터 변경 시 렌더링 (캐시 정리 및 선택 상태 동기화)
|
|
927
|
+
}, [externalSelectedItem, externalSelectedItems]); // 데이터 변경 시 렌더링 (캐시 정리 및 선택 상태 동기화)
|
|
979
928
|
|
|
980
929
|
React.useEffect(function () {
|
|
981
930
|
if (!stageRef.current) return;
|