@mint-ui/map 1.2.0-test.33 → 1.2.0-test.35
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/shared/context.d.ts +71 -2
- package/dist/components/mint-map/core/advanced/shared/context.js +74 -1
- package/dist/components/mint-map/core/advanced/shared/helpers.d.ts +28 -0
- package/dist/components/mint-map/core/advanced/shared/helpers.js +52 -0
- package/dist/components/mint-map/core/advanced/shared/hooks.d.ts +144 -0
- package/dist/components/mint-map/core/advanced/shared/hooks.js +283 -0
- package/dist/components/mint-map/core/advanced/shared/index.d.ts +3 -0
- package/dist/components/mint-map/core/advanced/shared/performance.d.ts +105 -24
- package/dist/components/mint-map/core/advanced/shared/performance.js +105 -24
- package/dist/components/mint-map/core/advanced/shared/utils.d.ts +128 -14
- package/dist/components/mint-map/core/advanced/shared/utils.js +128 -14
- package/dist/components/mint-map/core/advanced/shared/viewport.d.ts +72 -0
- package/dist/components/mint-map/core/advanced/shared/viewport.js +81 -0
- package/dist/components/mint-map/core/advanced/woongCanvasMarker/WoongCanvasMarker.js +142 -209
- package/dist/components/mint-map/core/advanced/woongCanvasPolygon/WoongCanvasPolygon.d.ts +0 -4
- package/dist/components/mint-map/core/advanced/woongCanvasPolygon/WoongCanvasPolygon.js +122 -217
- package/dist/components/mint-map/core/advanced/woongCanvasPolygon/renderer.d.ts +64 -5
- package/dist/components/mint-map/core/advanced/woongCanvasPolygon/renderer.js +81 -20
- package/dist/index.es.js +1066 -511
- package/dist/index.js +11 -0
- package/dist/index.umd.js +1072 -509
- package/package.json +1 -1
|
@@ -14,6 +14,9 @@ var types = require('../shared/types.js');
|
|
|
14
14
|
var utils = require('../shared/utils.js');
|
|
15
15
|
var context = require('../shared/context.js');
|
|
16
16
|
var performance = require('../shared/performance.js');
|
|
17
|
+
var viewport = require('../shared/viewport.js');
|
|
18
|
+
var hooks = require('../shared/hooks.js');
|
|
19
|
+
var helpers = require('../shared/helpers.js');
|
|
17
20
|
|
|
18
21
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
19
22
|
|
|
@@ -146,14 +149,7 @@ var WoongCanvasMarker = function (props) {
|
|
|
146
149
|
*/
|
|
147
150
|
|
|
148
151
|
var updateViewport = function () {
|
|
149
|
-
|
|
150
|
-
var stage = stageRef.current;
|
|
151
|
-
viewportRef.current = {
|
|
152
|
-
minX: -cullingMargin,
|
|
153
|
-
maxX: stage.width() + cullingMargin,
|
|
154
|
-
minY: -cullingMargin,
|
|
155
|
-
maxY: stage.height() + cullingMargin
|
|
156
|
-
};
|
|
152
|
+
viewport.updateViewport(stageRef.current, cullingMargin, viewportRef);
|
|
157
153
|
};
|
|
158
154
|
/**
|
|
159
155
|
* 아이템이 현재 뷰포트 안에 있는지 확인 (바운딩 박스 캐싱)
|
|
@@ -161,21 +157,7 @@ var WoongCanvasMarker = function (props) {
|
|
|
161
157
|
|
|
162
158
|
|
|
163
159
|
var isInViewport = function (item) {
|
|
164
|
-
|
|
165
|
-
var viewport = viewportRef.current; // 캐시된 바운딩 박스 확인
|
|
166
|
-
|
|
167
|
-
var bbox = boundingBoxCacheRef.current.get(item.id);
|
|
168
|
-
|
|
169
|
-
if (!bbox) {
|
|
170
|
-
// 바운딩 박스 계산 (공통 함수 사용)
|
|
171
|
-
var computed = computeBoundingBox(item);
|
|
172
|
-
if (!computed) return false;
|
|
173
|
-
bbox = computed;
|
|
174
|
-
boundingBoxCacheRef.current.set(item.id, bbox);
|
|
175
|
-
} // 바운딩 박스와 viewport 교차 체크
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return !(bbox.maxX < viewport.minX || bbox.minX > viewport.maxX || bbox.maxY < viewport.minY || bbox.minY > viewport.maxY);
|
|
160
|
+
return viewport.isInViewport(item, enableViewportCulling, viewportRef, boundingBoxCacheRef, computeBoundingBox);
|
|
179
161
|
}; // --------------------------------------------------------------------------
|
|
180
162
|
// 유틸리티 함수: 좌표 변환 캐싱
|
|
181
163
|
// --------------------------------------------------------------------------
|
|
@@ -205,12 +187,23 @@ var WoongCanvasMarker = function (props) {
|
|
|
205
187
|
/**
|
|
206
188
|
* 마커의 바운딩 박스 계산
|
|
207
189
|
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
* - tailHeight: 꼬리 높이 (Viewport Culling용, 화면에 보이는 전체 영역)
|
|
190
|
+
* 마커의 화면 상 위치와 크기를 기반으로 바운딩 박스를 계산합니다.
|
|
191
|
+
* Viewport Culling에 사용되며, tailHeight를 포함하여 전체 표시 영역을 계산합니다.
|
|
211
192
|
*
|
|
212
193
|
* @param item 마커 데이터
|
|
213
|
-
* @returns 바운딩 박스 또는 null
|
|
194
|
+
* @returns 바운딩 박스 (minX, minY, maxX, maxY) 또는 null (좌표 변환 실패 시)
|
|
195
|
+
*
|
|
196
|
+
* @remarks
|
|
197
|
+
* - **boxHeight**: 마커 본체만 포함 (Hit Test 영역)
|
|
198
|
+
* - **tailHeight**: 마커 꼬리 높이 (Viewport Culling용, 화면에 보이는 전체 영역 포함)
|
|
199
|
+
* - 바운딩 박스는 캐시되어 성능 최적화
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```typescript
|
|
203
|
+
* const bbox = computeBoundingBox(item);
|
|
204
|
+
* if (!bbox) return; // 계산 실패
|
|
205
|
+
* // bbox.minX, bbox.minY, bbox.maxX, bbox.maxY 사용
|
|
206
|
+
* ```
|
|
214
207
|
*/
|
|
215
208
|
|
|
216
209
|
|
|
@@ -234,29 +227,32 @@ var WoongCanvasMarker = function (props) {
|
|
|
234
227
|
|
|
235
228
|
/**
|
|
236
229
|
* 공간 인덱스 빌드 (빠른 Hit Test를 위한 자료구조)
|
|
230
|
+
*
|
|
231
|
+
* 모든 마커의 바운딩 박스를 Spatial Hash Grid에 삽입합니다.
|
|
232
|
+
* 이를 통해 클릭/호버 시 해당 위치 주변의 마커만 빠르게 조회할 수 있습니다.
|
|
233
|
+
*
|
|
234
|
+
* @remarks
|
|
235
|
+
* - 호출 시점: 데이터 변경 시 또는 지도 이동/줌 완료 시
|
|
236
|
+
* - 성능: O(n) 시간복잡도, n은 마커 개수
|
|
237
|
+
* - Hit Test 성능: O(1) 수준 (30,000개 → ~10개 후보만 체크)
|
|
237
238
|
*/
|
|
238
239
|
|
|
239
240
|
|
|
240
241
|
var buildSpatialIndex = function () {
|
|
241
|
-
|
|
242
|
-
spatial.clear();
|
|
243
|
-
var currentData = dataRef.current;
|
|
244
|
-
|
|
245
|
-
for (var _i = 0, currentData_1 = currentData; _i < currentData_1.length; _i++) {
|
|
246
|
-
var item = currentData_1[_i]; // 바운딩 박스 계산 (공통 함수 사용)
|
|
247
|
-
|
|
248
|
-
var bbox = computeBoundingBox(item);
|
|
249
|
-
|
|
250
|
-
if (bbox) {
|
|
251
|
-
spatial.insert(item, bbox.minX, bbox.minY, bbox.maxX, bbox.maxY);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
242
|
+
hooks.buildSpatialIndex(dataRef.current, spatialIndexRef.current, computeBoundingBox);
|
|
254
243
|
}; // --------------------------------------------------------------------------
|
|
255
|
-
// 렌더링 함수 결정
|
|
244
|
+
// 렌더링 함수 결정
|
|
256
245
|
// --------------------------------------------------------------------------
|
|
257
246
|
|
|
258
247
|
/**
|
|
259
248
|
* 외부 렌더링 함수에 전달할 유틸리티 객체
|
|
249
|
+
*
|
|
250
|
+
* 커스텀 렌더링 함수(renderBase, renderAnimation, renderEvent)에서 사용할
|
|
251
|
+
* 좌표 변환 등의 헬퍼 함수들을 제공합니다.
|
|
252
|
+
*
|
|
253
|
+
* @remarks
|
|
254
|
+
* - getOrComputeMarkerOffset: 마커 좌표 변환 (자동 캐싱)
|
|
255
|
+
* - getOrComputePolygonOffsets: 폴리곤 좌표 변환 (마커에서는 사용 안 함)
|
|
260
256
|
*/
|
|
261
257
|
|
|
262
258
|
|
|
@@ -344,7 +340,11 @@ var WoongCanvasMarker = function (props) {
|
|
|
344
340
|
/**
|
|
345
341
|
* Animation 레이어 렌더링 (선택된 마커 애니메이션)
|
|
346
342
|
*
|
|
347
|
-
*
|
|
343
|
+
* 선택된 마커에 대한 애니메이션 효과를 렌더링합니다.
|
|
344
|
+
* renderAnimation prop이 제공된 경우에만 실행됩니다.
|
|
345
|
+
*
|
|
346
|
+
* @remarks
|
|
347
|
+
* - **성능 최적화**: sceneFunc 내부에서 최신 items 참조
|
|
348
348
|
* - 선택 변경 시에만 재생성
|
|
349
349
|
* - 지도 이동 시에는 기존 Animation 계속 실행
|
|
350
350
|
*/
|
|
@@ -364,10 +364,16 @@ var WoongCanvasMarker = function (props) {
|
|
|
364
364
|
/**
|
|
365
365
|
* Event 레이어 렌더링 (hover + 선택 상태 표시)
|
|
366
366
|
*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
*
|
|
367
|
+
* 마커의 hover 효과 및 선택 상태를 표시합니다.
|
|
368
|
+
* renderEvent prop이 제공된 경우에만 실행됩니다.
|
|
369
|
+
*
|
|
370
|
+
* @remarks
|
|
371
|
+
* - **성능 최적화**:
|
|
372
|
+
* 1. Shape 재사용으로 객체 생성/파괴 오버헤드 제거
|
|
373
|
+
* 2. sceneFunc 한 번만 설정 (함수 재생성 제거)
|
|
374
|
+
* 3. 클로저로 최신 데이터 참조
|
|
375
|
+
* - **topOnHover 지원**: hover된 항목을 최상단에 렌더링
|
|
376
|
+
* - 선택된 항목은 Map에서 O(1)로 조회하여 성능 최적화
|
|
371
377
|
*/
|
|
372
378
|
|
|
373
379
|
|
|
@@ -385,8 +391,9 @@ var WoongCanvasMarker = function (props) {
|
|
|
385
391
|
name: 'event-render-shape',
|
|
386
392
|
sceneFunc: function (context, shape) {
|
|
387
393
|
var ctx = context; // 클로저로 최신 ref 값 참조
|
|
394
|
+
// 성능 최적화: Array.from 대신 직접 변환 (메모리 할당 최소화)
|
|
388
395
|
|
|
389
|
-
var selectedItems =
|
|
396
|
+
var selectedItems = helpers.mapValuesToArray(selectedItemsMapRef.current);
|
|
390
397
|
var hovered = hoveredItemRef.current; // topOnHover가 true이면 hover된 항목을 최상단에 렌더링
|
|
391
398
|
|
|
392
399
|
if (topOnHover && hovered) {
|
|
@@ -454,89 +461,43 @@ var WoongCanvasMarker = function (props) {
|
|
|
454
461
|
// 이벤트 핸들러: 지도 이벤트
|
|
455
462
|
// --------------------------------------------------------------------------
|
|
456
463
|
|
|
457
|
-
/**
|
|
458
|
-
* 지도 이동/줌 완료 시 처리
|
|
459
|
-
*/
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
var handleIdle = function () {
|
|
463
|
-
prevCenterOffsetRef.current = null;
|
|
464
|
-
accumTranslateRef.current = {
|
|
465
|
-
x: 0,
|
|
466
|
-
y: 0
|
|
467
|
-
}; // 2. 캐시 정리 (지도 이동/줌으로 좌표 변환 결과가 바뀜)
|
|
468
|
-
|
|
469
|
-
offsetCacheRef.current.clear();
|
|
470
|
-
boundingBoxCacheRef.current.clear(); // 3. 마커 위치 업데이트
|
|
471
|
-
|
|
472
|
-
var bounds = controller.getCurrBounds();
|
|
473
|
-
|
|
474
|
-
var markerOptions = tslib.__assign({
|
|
475
|
-
position: bounds.nw
|
|
476
|
-
}, options);
|
|
477
|
-
|
|
478
|
-
markerRef.current && controller.updateMarker(markerRef.current, markerOptions); // 4. transform 제거 전에 새 데이터로 즉시 렌더링 (겹침 방지)
|
|
479
|
-
|
|
480
|
-
if (containerRef.current) {
|
|
481
|
-
containerRef.current.style.transform = '';
|
|
482
|
-
containerRef.current.style.visibility = '';
|
|
483
|
-
} // 5. 새 위치에서 렌더링
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
renderAllImmediate();
|
|
487
|
-
};
|
|
488
|
-
/**
|
|
489
|
-
* 줌 시작 시 처리 (일시적으로 숨김)
|
|
490
|
-
*/
|
|
491
|
-
|
|
492
464
|
|
|
493
|
-
var
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
465
|
+
var _g = hooks.createMapEventHandlers({
|
|
466
|
+
controller: controller,
|
|
467
|
+
containerRef: containerRef,
|
|
468
|
+
markerRef: markerRef,
|
|
469
|
+
options: options,
|
|
470
|
+
prevCenterOffsetRef: prevCenterOffsetRef,
|
|
471
|
+
accumTranslateRef: accumTranslateRef,
|
|
472
|
+
offsetCacheRef: offsetCacheRef,
|
|
473
|
+
boundingBoxCacheRef: boundingBoxCacheRef,
|
|
474
|
+
renderAllImmediate: renderAllImmediate
|
|
475
|
+
}),
|
|
476
|
+
handleIdle = _g.handleIdle,
|
|
477
|
+
handleZoomStart = _g.handleZoomStart,
|
|
478
|
+
handleZoomEnd = _g.handleZoomEnd,
|
|
479
|
+
handleCenterChanged = _g.handleCenterChanged,
|
|
480
|
+
handleDragStartShared = _g.handleDragStart,
|
|
481
|
+
handleDragEndShared = _g.handleDragEnd;
|
|
498
482
|
/**
|
|
499
|
-
*
|
|
483
|
+
* 드래그 시작 처리 (커서를 grabbing으로 변경)
|
|
500
484
|
*/
|
|
501
485
|
|
|
502
486
|
|
|
503
|
-
var
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
487
|
+
var handleDragStart = function () {
|
|
488
|
+
handleDragStartShared();
|
|
489
|
+
draggingRef.current = true;
|
|
490
|
+
controller.setMapCursor('grabbing');
|
|
507
491
|
};
|
|
508
492
|
/**
|
|
509
|
-
*
|
|
493
|
+
* 드래그 종료 처리 (커서를 기본으로 복원)
|
|
510
494
|
*/
|
|
511
495
|
|
|
512
496
|
|
|
513
|
-
var
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
if (!prev) {
|
|
519
|
-
prevCenterOffsetRef.current = {
|
|
520
|
-
x: curr.x,
|
|
521
|
-
y: curr.y
|
|
522
|
-
};
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
var dx = prev.x - curr.x;
|
|
527
|
-
var dy = prev.y - curr.y;
|
|
528
|
-
accumTranslateRef.current = {
|
|
529
|
-
x: accumTranslateRef.current.x + dx,
|
|
530
|
-
y: accumTranslateRef.current.y + dy
|
|
531
|
-
};
|
|
532
|
-
prevCenterOffsetRef.current = {
|
|
533
|
-
x: curr.x,
|
|
534
|
-
y: curr.y
|
|
535
|
-
};
|
|
536
|
-
|
|
537
|
-
if (containerRef.current) {
|
|
538
|
-
containerRef.current.style.transform = "translate(".concat(accumTranslateRef.current.x, "px, ").concat(accumTranslateRef.current.y, "px)");
|
|
539
|
-
}
|
|
497
|
+
var handleDragEnd = function () {
|
|
498
|
+
handleDragEndShared();
|
|
499
|
+
draggingRef.current = false;
|
|
500
|
+
controller.setMapCursor('grab');
|
|
540
501
|
}; // --------------------------------------------------------------------------
|
|
541
502
|
// Hit Test & 상태 관리
|
|
542
503
|
// --------------------------------------------------------------------------
|
|
@@ -544,12 +505,26 @@ var WoongCanvasMarker = function (props) {
|
|
|
544
505
|
/**
|
|
545
506
|
* 특정 좌표의 마커 데이터 찾기 (Spatial Index 사용)
|
|
546
507
|
*
|
|
547
|
-
*
|
|
548
|
-
*
|
|
549
|
-
*
|
|
508
|
+
* 클릭/호버 이벤트 시 해당 위치에 있는 마커를 찾습니다.
|
|
509
|
+
* Spatial Hash Grid를 사용하여 O(1) 수준의 빠른 Hit Test를 수행합니다.
|
|
510
|
+
*
|
|
511
|
+
* @param offset 검사할 화면 좌표 (픽셀 단위)
|
|
512
|
+
* @returns 찾은 마커 데이터 또는 null (없으면)
|
|
550
513
|
*
|
|
551
|
-
* @
|
|
552
|
-
*
|
|
514
|
+
* @remarks
|
|
515
|
+
* - **topOnHover 지원**: topOnHover가 true일 때 현재 hover된 항목을 최우선으로 체크
|
|
516
|
+
* - 시각적으로 최상단에 있는 항목이 hit test에서도 우선됨
|
|
517
|
+
* - **성능**: O(후보 항목 수) - 보통 ~10개 (30,000개 전체를 체크하지 않음)
|
|
518
|
+
* - Spatial Index를 통해 해당 위치 주변의 후보만 추출 후 정확한 Hit Test 수행
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* ```typescript
|
|
522
|
+
* const clickedOffset = controller.positionToOffset(event.param.position);
|
|
523
|
+
* const data = findData(clickedOffset);
|
|
524
|
+
* if (data) {
|
|
525
|
+
* // 마커를 찾음
|
|
526
|
+
* }
|
|
527
|
+
* ```
|
|
553
528
|
*/
|
|
554
529
|
|
|
555
530
|
|
|
@@ -610,11 +585,17 @@ var WoongCanvasMarker = function (props) {
|
|
|
610
585
|
/**
|
|
611
586
|
* 클릭 처리 (단일/다중 선택)
|
|
612
587
|
*
|
|
613
|
-
*
|
|
588
|
+
* 마커 클릭 시 선택 상태를 업데이트하고 렌더링을 수행합니다.
|
|
589
|
+
*
|
|
590
|
+
* @param data 클릭된 마커 데이터
|
|
614
591
|
*
|
|
615
|
-
*
|
|
616
|
-
* -
|
|
617
|
-
* -
|
|
592
|
+
* @remarks
|
|
593
|
+
* - **단일 선택**: 기존 선택 해제 후 새로 선택 (토글 가능)
|
|
594
|
+
* - **다중 선택**: enableMultiSelect가 true면 기존 선택 유지하며 추가/제거
|
|
595
|
+
* - **성능 최적화**:
|
|
596
|
+
* - 단일 Shape 렌더링으로 Base Layer 재렌더링 속도 향상
|
|
597
|
+
* - sceneFunc에서 selectedIds를 체크하여 선택된 마커만 스킵
|
|
598
|
+
* - 객체 생성 오버헤드 제거로 1,000개 이상도 부드럽게 처리
|
|
618
599
|
*/
|
|
619
600
|
|
|
620
601
|
|
|
@@ -663,75 +644,57 @@ var WoongCanvasMarker = function (props) {
|
|
|
663
644
|
|
|
664
645
|
/**
|
|
665
646
|
* 클릭 이벤트 처리
|
|
647
|
+
*
|
|
648
|
+
* @param event 클릭 이벤트 파라미터
|
|
649
|
+
*
|
|
650
|
+
* @remarks
|
|
651
|
+
* - Context가 있으면 전역 이벤트 핸들러가 처리하므로 스킵
|
|
652
|
+
* - 상호작용이 비활성화되어 있으면 스킵
|
|
653
|
+
* - Spatial Index를 사용하여 빠른 Hit Test 수행
|
|
666
654
|
*/
|
|
667
655
|
|
|
668
656
|
|
|
669
657
|
var handleClick = function (event) {
|
|
670
|
-
var _a;
|
|
671
|
-
|
|
672
658
|
if (disableInteractionRef.current) return; // 🚫 상호작용 비활성화 시 즉시 반환
|
|
673
659
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
var clickedOffset = controller.positionToOffset(event.param.position);
|
|
678
|
-
var data_1 = findData(clickedOffset);
|
|
660
|
+
var clickedOffset = helpers.validateEvent(event, context$1, controller);
|
|
661
|
+
if (!clickedOffset) return;
|
|
662
|
+
var data = findData(clickedOffset);
|
|
679
663
|
|
|
680
|
-
|
|
681
|
-
|
|
664
|
+
if (data) {
|
|
665
|
+
handleLocalClick(data);
|
|
682
666
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
}
|
|
667
|
+
if (onClick) {
|
|
668
|
+
onClick(data, selectedIdsRef.current);
|
|
686
669
|
}
|
|
687
|
-
} catch (error) {
|
|
688
|
-
console.error('[WoongCanvasMarker] handleClick error:', error);
|
|
689
670
|
}
|
|
690
671
|
};
|
|
691
672
|
/**
|
|
692
673
|
* 마우스 이동 이벤트 처리 (hover 감지)
|
|
674
|
+
*
|
|
675
|
+
* @param event 마우스 이동 이벤트 파라미터
|
|
676
|
+
*
|
|
677
|
+
* @remarks
|
|
678
|
+
* - Context가 있으면 전역 이벤트 핸들러가 처리하므로 스킵
|
|
679
|
+
* - 상호작용이 비활성화되어 있으면 스킵
|
|
680
|
+
* - hover 상태 변경 시에만 렌더링 및 콜백 호출 (최적화)
|
|
693
681
|
*/
|
|
694
682
|
|
|
695
683
|
|
|
696
684
|
var handleMouseMove = function (event) {
|
|
697
|
-
var _a;
|
|
698
|
-
|
|
699
685
|
if (disableInteractionRef.current) return; // 🚫 상호작용 비활성화 시 즉시 반환
|
|
700
686
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
var hoveredItem = findData(mouseOffset);
|
|
706
|
-
var prevHovered = hoveredItemRef.current;
|
|
687
|
+
var mouseOffset = helpers.validateEvent(event, context$1, controller);
|
|
688
|
+
if (!mouseOffset) return;
|
|
689
|
+
var hoveredItem = findData(mouseOffset);
|
|
690
|
+
var prevHovered = hoveredItemRef.current;
|
|
707
691
|
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
}
|
|
713
|
-
} catch (error) {
|
|
714
|
-
console.error('[WoongCanvasMarker] handleMouseMove error:', error);
|
|
692
|
+
if (prevHovered !== hoveredItem) {
|
|
693
|
+
setHovered(hoveredItem);
|
|
694
|
+
if (prevHovered && onMouseOut) onMouseOut(prevHovered);
|
|
695
|
+
if (hoveredItem && onMouseOver) onMouseOver(hoveredItem);
|
|
715
696
|
}
|
|
716
697
|
};
|
|
717
|
-
/**
|
|
718
|
-
* 드래그 시작 처리 (커서를 grabbing으로 변경)
|
|
719
|
-
*/
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
var handleDragStart = function () {
|
|
723
|
-
draggingRef.current = true;
|
|
724
|
-
controller.setMapCursor('grabbing');
|
|
725
|
-
};
|
|
726
|
-
/**
|
|
727
|
-
* 드래그 종료 처리 (커서를 기본으로 복원)
|
|
728
|
-
*/
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
var handleDragEnd = function () {
|
|
732
|
-
draggingRef.current = false;
|
|
733
|
-
controller.setMapCursor('grab');
|
|
734
|
-
};
|
|
735
698
|
/**
|
|
736
699
|
* 마우스가 canvas를 벗어날 때 hover cleanup
|
|
737
700
|
*/
|
|
@@ -929,18 +892,8 @@ var WoongCanvasMarker = function (props) {
|
|
|
929
892
|
// --------------------------------------------------------------------------
|
|
930
893
|
|
|
931
894
|
React.useEffect(function () {
|
|
932
|
-
if (!stageRef.current) return;
|
|
933
|
-
|
|
934
|
-
if (externalSelectedItems === undefined) return; // 외부에서 전달된 selectedItems로 동기화
|
|
935
|
-
|
|
936
|
-
var newSelectedIds = new Set();
|
|
937
|
-
var newSelectedItemsMap = new Map();
|
|
938
|
-
externalSelectedItems.forEach(function (item) {
|
|
939
|
-
newSelectedIds.add(item.id);
|
|
940
|
-
newSelectedItemsMap.set(item.id, item);
|
|
941
|
-
});
|
|
942
|
-
selectedIdsRef.current = newSelectedIds;
|
|
943
|
-
selectedItemsMapRef.current = newSelectedItemsMap; // 렌더링
|
|
895
|
+
if (!stageRef.current) return;
|
|
896
|
+
hooks.syncExternalSelectedItems(externalSelectedItems, selectedIdsRef, selectedItemsMapRef); // 렌더링
|
|
944
897
|
|
|
945
898
|
doRenderBase();
|
|
946
899
|
doRenderAnimation();
|
|
@@ -991,27 +944,7 @@ var WoongCanvasMarker = function (props) {
|
|
|
991
944
|
* - O(전체 데이터 수 + 선택된 개수) - 매우 효율적
|
|
992
945
|
*/
|
|
993
946
|
|
|
994
|
-
|
|
995
|
-
return [m.id, m];
|
|
996
|
-
}));
|
|
997
|
-
var newSelectedItemsMap = new Map();
|
|
998
|
-
selectedIdsRef.current.forEach(function (id) {
|
|
999
|
-
// 현재 data에 있으면 최신 데이터 사용
|
|
1000
|
-
var currentItem = dataMap.get(id);
|
|
1001
|
-
|
|
1002
|
-
if (currentItem) {
|
|
1003
|
-
newSelectedItemsMap.set(id, currentItem);
|
|
1004
|
-
} else {
|
|
1005
|
-
// 화면 밖이면 기존 데이터 유지
|
|
1006
|
-
var prevItem = selectedItemsMapRef.current.get(id);
|
|
1007
|
-
|
|
1008
|
-
if (prevItem) {
|
|
1009
|
-
newSelectedItemsMap.set(id, prevItem);
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
}); // selectedIdsRef는 그대로 유지 (화면 밖 항목도 선택 상태 유지)
|
|
1013
|
-
|
|
1014
|
-
selectedItemsMapRef.current = newSelectedItemsMap; // 즉시 렌더링
|
|
947
|
+
selectedItemsMapRef.current = hooks.syncSelectedItems(data, selectedIdsRef.current, selectedItemsMapRef.current); // 즉시 렌더링
|
|
1015
948
|
|
|
1016
949
|
renderAllImmediate();
|
|
1017
950
|
}, [data]);
|
|
@@ -11,10 +11,6 @@ export interface WoongCanvasPolygonProps<T> extends Pick<MarkerOptions, 'zIndex'
|
|
|
11
11
|
data: KonvaCanvasData<T>[];
|
|
12
12
|
/** 폴리곤 클릭 시 호출되는 콜백 (선택) */
|
|
13
13
|
onClick?: (payload: KonvaCanvasData<T>, selectedIds: Set<string>) => void;
|
|
14
|
-
/** 폴리곤에 마우스 오버 시 호출되는 콜백 (선택) */
|
|
15
|
-
onMouseOver?: (payload: KonvaCanvasData<T>) => void;
|
|
16
|
-
/** 폴리곤에서 마우스 아웃 시 호출되는 콜백 (선택) */
|
|
17
|
-
onMouseOut?: (payload: KonvaCanvasData<T>) => void;
|
|
18
14
|
/** 다중 선택 활성화 여부 (기본: false) */
|
|
19
15
|
enableMultiSelect?: boolean;
|
|
20
16
|
/** 뷰포트 컬링 활성화 여부 (기본: true) */
|