@mint-ui/map 1.2.0-test.11 → 1.2.0-test.13
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/MintMapCore.js +1 -2
- package/dist/components/mint-map/core/advanced/woongCanvas/WoongCanvasLayer.d.ts +94 -20
- package/dist/components/mint-map/core/advanced/woongCanvas/WoongCanvasLayer.js +108 -57
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/context.d.ts +7 -7
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/renderer.d.ts +3 -3
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/types.d.ts +177 -27
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/utils.d.ts +21 -5
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/utils.js +24 -0
- package/dist/components/mint-map/google/GoogleMintMapController.js +1 -0
- package/dist/components/mint-map/kakao/KakaoMintMapController.js +1 -0
- package/dist/components/mint-map/naver/NaverMintMapController.js +1 -0
- package/dist/index.es.js +132 -58
- package/dist/index.js +1 -0
- package/dist/index.umd.js +132 -57
- package/package.json +1 -1
- package/dist/components/mint-map/core/advanced/woongCanvas/ClusterMarker.d.ts +0 -11
|
@@ -9,8 +9,7 @@ var MapTypes = require('../types/MapTypes.js');
|
|
|
9
9
|
var MintMapProvider = require('./provider/MintMapProvider.js');
|
|
10
10
|
var MintMapCore_module = require('./MintMapCore.module.scss.js');
|
|
11
11
|
require('./advanced/woongCanvas/shared/types.js');
|
|
12
|
-
require('
|
|
13
|
-
require('../types/MapEventTypes.js');
|
|
12
|
+
require('./advanced/woongCanvas/shared/utils.js');
|
|
14
13
|
var context = require('./advanced/woongCanvas/shared/context.js');
|
|
15
14
|
require('./advanced/woongCanvas/shared/performance.js');
|
|
16
15
|
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { MarkerOptions } from "../../../types";
|
|
3
|
-
import {
|
|
3
|
+
import { KonvaCanvasData, CanvasDataType, CustomRenderBase, CustomRenderAnimation, CustomRenderEvent } from "./shared";
|
|
4
4
|
export { KonvaMarkerProvider, LRUCache, SpatialHashGrid, CanvasDataType } from "./shared";
|
|
5
|
-
export type {
|
|
5
|
+
export type { KonvaCanvasOption, Paths, KonvaCanvasData, CustomRenderBase, CustomRenderAnimation, CustomRenderEvent, RenderUtils, RenderBaseParams, RenderAnimationParams, RenderEventParams } from "./shared";
|
|
6
6
|
/**
|
|
7
7
|
* 공통 Props (MARKER와 POLYGON 모두 사용)
|
|
8
8
|
*/
|
|
9
9
|
interface WoongCanvasLayerBaseProps<T> extends Pick<MarkerOptions, 'zIndex' | 'anchor' | 'visible'> {
|
|
10
|
-
/** 렌더링할
|
|
11
|
-
|
|
10
|
+
/** 렌더링할 데이터 배열 (마커 또는 폴리곤) */
|
|
11
|
+
data: KonvaCanvasData<T>[];
|
|
12
12
|
/** 마커 클릭 시 호출되는 콜백 (선택) */
|
|
13
|
-
onClick?: (payload:
|
|
13
|
+
onClick?: (payload: KonvaCanvasData<T>, selectedIds: Set<string>) => void;
|
|
14
14
|
/** 마커에 마우스 오버 시 호출되는 콜백 (선택) */
|
|
15
|
-
onMouseOver?: (payload:
|
|
15
|
+
onMouseOver?: (payload: KonvaCanvasData<T>) => void;
|
|
16
16
|
/** 마커에서 마우스 아웃 시 호출되는 콜백 (선택) */
|
|
17
|
-
onMouseOut?: (payload:
|
|
17
|
+
onMouseOut?: (payload: KonvaCanvasData<T>) => void;
|
|
18
18
|
/** 다중 선택 활성화 여부 (기본: false) */
|
|
19
19
|
enableMultiSelect?: boolean;
|
|
20
20
|
/** hover 시 마커를 최상단으로 표시 (기본: false) */
|
|
@@ -26,24 +26,26 @@ interface WoongCanvasLayerBaseProps<T> extends Pick<MarkerOptions, 'zIndex' | 'a
|
|
|
26
26
|
/** LRU 캐시 최대 크기 (기본: 10000) */
|
|
27
27
|
maxCacheSize?: number;
|
|
28
28
|
/** 외부에서 제어하는 선택된 항목 배열 (선택) */
|
|
29
|
-
selectedItems?:
|
|
29
|
+
selectedItems?: KonvaCanvasData<T>[];
|
|
30
30
|
/** 외부에서 전달된 단일 선택 아이템 (특별한 효과용) */
|
|
31
|
-
selectedItem?:
|
|
31
|
+
selectedItem?: KonvaCanvasData<T> | null;
|
|
32
32
|
/** 상호작용 비활성화 (hover, click 등 모든 이벤트 차단) */
|
|
33
33
|
disableInteraction?: boolean;
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* MARKER 타입 Props - 커스텀 렌더링 필수
|
|
37
37
|
*/
|
|
38
|
-
interface WoongCanvasLayerPropsForMarker<T> extends WoongCanvasLayerBaseProps<T> {
|
|
38
|
+
interface WoongCanvasLayerPropsForMarker<T, C = any> extends WoongCanvasLayerBaseProps<T> {
|
|
39
39
|
/** 데이터 타입 */
|
|
40
40
|
dataType: CanvasDataType.MARKER;
|
|
41
41
|
/** Base Layer 렌더링 함수 (필수) */
|
|
42
|
-
renderBase: CustomRenderBase<T>;
|
|
42
|
+
renderBase: CustomRenderBase<T, C>;
|
|
43
43
|
/** Animation Layer 렌더링 함수 (선택, 애니메이션용) */
|
|
44
|
-
renderAnimation?: CustomRenderAnimation<T>;
|
|
44
|
+
renderAnimation?: CustomRenderAnimation<T, C>;
|
|
45
45
|
/** Event Layer 렌더링 함수 (선택) */
|
|
46
|
-
renderEvent?: CustomRenderEvent<T>;
|
|
46
|
+
renderEvent?: CustomRenderEvent<T, C>;
|
|
47
|
+
/** 렌더링 설정 (색상, 표시 여부, 모양 등) */
|
|
48
|
+
renderConfig?: C;
|
|
47
49
|
}
|
|
48
50
|
/**
|
|
49
51
|
* POLYGON 타입 Props - 스타일 속성으로 내부 처리
|
|
@@ -78,16 +80,88 @@ interface WoongCanvasLayerPropsForPolygon<T> extends WoongCanvasLayerBaseProps<T
|
|
|
78
80
|
}
|
|
79
81
|
/**
|
|
80
82
|
* 최종 Props 타입 - Discriminated Union
|
|
83
|
+
*
|
|
84
|
+
* @template T 데이터 타입
|
|
85
|
+
* @template C 렌더링 설정 타입 (MARKER 모드에서만 사용)
|
|
81
86
|
*/
|
|
82
|
-
export declare type WoongCanvasLayerProps<T> = WoongCanvasLayerPropsForMarker<T> | WoongCanvasLayerPropsForPolygon<T>;
|
|
87
|
+
export declare type WoongCanvasLayerProps<T, C = any> = WoongCanvasLayerPropsForMarker<T, C> | WoongCanvasLayerPropsForPolygon<T>;
|
|
83
88
|
/**
|
|
84
|
-
*
|
|
89
|
+
* 🚀 WoongCanvasLayer - Konva 기반 초고성능 마커/폴리곤 렌더링 컴포넌트
|
|
90
|
+
*
|
|
91
|
+
* ## 📌 주요 특징
|
|
92
|
+
* - **30,000개 이상의 폴리곤/마커를 60fps로 렌더링**
|
|
93
|
+
* - **Multi-Layer 아키텍처**: Base/Animation/Event 레이어 분리
|
|
94
|
+
* - **Spatial Hash Grid**: O(1) 수준의 빠른 Hit Test
|
|
95
|
+
* - **LRU 캐시**: 좌표 변환 결과 캐싱으로 성능 최적화
|
|
96
|
+
* - **Viewport Culling**: 화면에 보이는 영역만 렌더링
|
|
97
|
+
* - **Discriminated Union Props**: 타입 안전한 MARKER/POLYGON 모드
|
|
98
|
+
*
|
|
99
|
+
* ## 🎯 사용 방법
|
|
100
|
+
*
|
|
101
|
+
* ### 1️⃣ POLYGON 모드 (자동 렌더링)
|
|
102
|
+
* ```tsx
|
|
103
|
+
* <WoongCanvasLayer
|
|
104
|
+
* dataType={CanvasDataType.POLYGON}
|
|
105
|
+
* data={polygons}
|
|
106
|
+
* baseFillColor="rgba(255, 100, 100, 0.5)"
|
|
107
|
+
* baseStrokeColor="rgba(200, 50, 50, 0.8)"
|
|
108
|
+
* baseLineWidth={2}
|
|
109
|
+
* selectedFillColor="rgba(255, 193, 7, 0.7)"
|
|
110
|
+
* selectedStrokeColor="rgba(255, 152, 0, 1)"
|
|
111
|
+
* selectedLineWidth={4}
|
|
112
|
+
* hoveredFillColor="rgba(100, 150, 255, 0.8)" // optional
|
|
113
|
+
* hoveredStrokeColor="rgba(0, 100, 200, 1)" // optional
|
|
114
|
+
* hoveredLineWidth={3} // optional
|
|
115
|
+
* enableMultiSelect={true}
|
|
116
|
+
* onClick={handleClick}
|
|
117
|
+
* />
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* ### 2️⃣ MARKER 모드 (커스텀 렌더링)
|
|
121
|
+
* ```tsx
|
|
122
|
+
* <WoongCanvasLayer
|
|
123
|
+
* dataType={CanvasDataType.MARKER}
|
|
124
|
+
* data={markers}
|
|
125
|
+
* renderBase={renderMarkerBase} // required
|
|
126
|
+
* renderAnimation={renderMarkerAnimation} // optional
|
|
127
|
+
* renderEvent={renderMarkerEvent} // optional
|
|
128
|
+
* topOnHover={true}
|
|
129
|
+
* onClick={handleClick}
|
|
130
|
+
* />
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
133
|
+
* ## 📊 데이터 형식
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const data: KonvaCanvasData<T>[] = [
|
|
136
|
+
* {
|
|
137
|
+
* id: 'unique-id',
|
|
138
|
+
* position: new Position(lat, lng),
|
|
139
|
+
* // POLYGON: paths 필수
|
|
140
|
+
* paths: [[[lat, lng], [lat, lng], ...]],
|
|
141
|
+
* // MARKER: boxWidth/boxHeight 권장 (Hit Test 정확도)
|
|
142
|
+
* boxWidth: 60,
|
|
143
|
+
* boxHeight: 75,
|
|
144
|
+
* // 커스텀 데이터
|
|
145
|
+
* ...customData
|
|
146
|
+
* }
|
|
147
|
+
* ];
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* ## ⚡ 성능 최적화 팁
|
|
151
|
+
* 1. **동적 boxWidth 계산**: `measureText()`로 실제 너비 계산 후 전달
|
|
152
|
+
* 2. **enableViewportCulling**: 대량 데이터 시 필수 (기본 true)
|
|
153
|
+
* 3. **selectedItems 외부 관리**: 상태를 외부에서 관리하여 리렌더링 최소화
|
|
154
|
+
* 4. **React.memo 최적화**: 컴포넌트가 자동으로 불필요한 리렌더링 방지
|
|
155
|
+
*
|
|
156
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
85
157
|
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
158
|
+
* @example
|
|
159
|
+
* // 동적 boxWidth 계산 예시
|
|
160
|
+
* const tempCtx = document.createElement('canvas').getContext('2d');
|
|
161
|
+
* tempCtx.font = 'bold 15px Arial';
|
|
162
|
+
* const boxWidth = Math.max(60, tempCtx.measureText(text).width + 20);
|
|
89
163
|
*
|
|
90
|
-
*
|
|
164
|
+
* @see {@link https://github.com/your-repo/docs/WoongCanvasLayer.md} 전체 문서
|
|
91
165
|
*/
|
|
92
|
-
declare const WoongCanvasLayer: <T>(props: WoongCanvasLayerProps<T>) => React.ReactPortal;
|
|
166
|
+
declare const WoongCanvasLayer: <T, C = any>(props: WoongCanvasLayerProps<T, C>) => React.ReactPortal;
|
|
93
167
|
export default WoongCanvasLayer;
|
|
@@ -24,20 +24,8 @@ var Konva__default = /*#__PURE__*/_interopDefaultLegacy(Konva);
|
|
|
24
24
|
// 메인 컴포넌트
|
|
25
25
|
// ============================================================================
|
|
26
26
|
|
|
27
|
-
/**
|
|
28
|
-
* Konva 기반 고성능 마커/폴리곤 렌더링 컴포넌트
|
|
29
|
-
*
|
|
30
|
-
* 특징:
|
|
31
|
-
* - Base/Event 레이어 분리로 성능 최적화
|
|
32
|
-
* - LRU 캐시로 좌표 변환 결과 캐싱
|
|
33
|
-
* - Spatial Hash Grid로 빠른 Hit Test
|
|
34
|
-
* - Viewport Culling으로 보이는 영역만 렌더링
|
|
35
|
-
*
|
|
36
|
-
* @template T 마커 데이터의 추가 속성 타입
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
27
|
var WoongCanvasLayerComponent = function (props) {
|
|
40
|
-
var
|
|
28
|
+
var data = props.data,
|
|
41
29
|
dataType = props.dataType,
|
|
42
30
|
onClick = props.onClick,
|
|
43
31
|
onMouseOver = props.onMouseOver,
|
|
@@ -56,11 +44,13 @@ var WoongCanvasLayerComponent = function (props) {
|
|
|
56
44
|
externalSelectedItem = props.selectedItem,
|
|
57
45
|
_f = props.disableInteraction,
|
|
58
46
|
disableInteraction = _f === void 0 ? false : _f,
|
|
59
|
-
options = tslib.__rest(props, ["
|
|
47
|
+
options = tslib.__rest(props, ["data", "dataType", "onClick", "onMouseOver", "onMouseOut", "enableMultiSelect", "topOnHover", "enableViewportCulling", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction"]); // renderConfig 추출 (MARKER 모드에서만 존재)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
var renderConfig = dataType === types.CanvasDataType.MARKER ? props.renderConfig : undefined; // --------------------------------------------------------------------------
|
|
60
51
|
// Hooks & Context
|
|
61
52
|
// --------------------------------------------------------------------------
|
|
62
53
|
|
|
63
|
-
|
|
64
54
|
var controller = MintMapProvider.useMintMapController();
|
|
65
55
|
var context$1 = context.useKonvaMarkerContext();
|
|
66
56
|
var currentZIndex = options.zIndex !== undefined ? options.zIndex : 0; // --------------------------------------------------------------------------
|
|
@@ -81,9 +71,9 @@ var WoongCanvasLayerComponent = function (props) {
|
|
|
81
71
|
// Data Refs - 선택 및 Hover 상태 관리
|
|
82
72
|
// --------------------------------------------------------------------------
|
|
83
73
|
|
|
84
|
-
/**
|
|
74
|
+
/** data prop을 ref로 추적 (stale closure 방지, useEffect에서 동기화) */
|
|
85
75
|
|
|
86
|
-
var markersRef = React.useRef(
|
|
76
|
+
var markersRef = React.useRef(data); // --------------------------------------------------------------------------
|
|
87
77
|
// State Refs - 선택 및 Hover 상태 관리
|
|
88
78
|
// --------------------------------------------------------------------------
|
|
89
79
|
|
|
@@ -255,6 +245,7 @@ var WoongCanvasLayerComponent = function (props) {
|
|
|
255
245
|
};
|
|
256
246
|
/**
|
|
257
247
|
* 마커 좌표 변환 결과를 캐시하고 반환
|
|
248
|
+
*
|
|
258
249
|
* @param markerData 마커 데이터
|
|
259
250
|
* @returns 변환된 좌표 또는 null
|
|
260
251
|
*/
|
|
@@ -391,7 +382,8 @@ var WoongCanvasLayerComponent = function (props) {
|
|
|
391
382
|
ctx: ctx,
|
|
392
383
|
items: visibleMarkers,
|
|
393
384
|
selectedIds: selectedIdsRef.current,
|
|
394
|
-
utils: renderUtils
|
|
385
|
+
utils: renderUtils,
|
|
386
|
+
config: renderConfig
|
|
395
387
|
});
|
|
396
388
|
},
|
|
397
389
|
perfectDrawEnabled: false,
|
|
@@ -421,7 +413,8 @@ var WoongCanvasLayerComponent = function (props) {
|
|
|
421
413
|
layer: layer,
|
|
422
414
|
selectedIds: selectedIdsRef.current,
|
|
423
415
|
items: markersRef.current,
|
|
424
|
-
utils: renderUtils
|
|
416
|
+
utils: renderUtils,
|
|
417
|
+
config: renderConfig
|
|
425
418
|
});
|
|
426
419
|
};
|
|
427
420
|
/**
|
|
@@ -462,7 +455,8 @@ var WoongCanvasLayerComponent = function (props) {
|
|
|
462
455
|
hoveredItem: hoveredItemRef.current,
|
|
463
456
|
utils: renderUtils,
|
|
464
457
|
selectedItems: selectedItems,
|
|
465
|
-
selectedItem: selectedItemRef.current
|
|
458
|
+
selectedItem: selectedItemRef.current,
|
|
459
|
+
config: renderConfig
|
|
466
460
|
});
|
|
467
461
|
},
|
|
468
462
|
perfectDrawEnabled: false,
|
|
@@ -725,11 +719,11 @@ var WoongCanvasLayerComponent = function (props) {
|
|
|
725
719
|
|
|
726
720
|
try {
|
|
727
721
|
var clickedOffset = controller.positionToOffset(event.param.position);
|
|
728
|
-
var
|
|
722
|
+
var data_1 = findData(clickedOffset);
|
|
729
723
|
|
|
730
|
-
if (
|
|
731
|
-
handleLocalClick(
|
|
732
|
-
onClick(
|
|
724
|
+
if (data_1) {
|
|
725
|
+
handleLocalClick(data_1);
|
|
726
|
+
onClick(data_1, selectedIdsRef.current);
|
|
733
727
|
}
|
|
734
728
|
} catch (error) {
|
|
735
729
|
console.error('[WoongKonvaMarker] handleClick error:', error);
|
|
@@ -1006,13 +1000,13 @@ var WoongCanvasLayerComponent = function (props) {
|
|
|
1006
1000
|
|
|
1007
1001
|
doRenderEvent();
|
|
1008
1002
|
}, [externalSelectedItem]); // --------------------------------------------------------------------------
|
|
1009
|
-
// Lifecycle:
|
|
1003
|
+
// Lifecycle: 데이터 변경 시 렌더링
|
|
1010
1004
|
// --------------------------------------------------------------------------
|
|
1011
1005
|
|
|
1012
1006
|
React.useEffect(function () {
|
|
1013
1007
|
if (!stageRef.current) return; // markersRef 동기화
|
|
1014
1008
|
|
|
1015
|
-
markersRef.current =
|
|
1009
|
+
markersRef.current = data; // 데이터 변경 시 즉시 transform 제거 및 캐시 정리 (겹침 방지)
|
|
1016
1010
|
|
|
1017
1011
|
if (containerRef.current) {
|
|
1018
1012
|
containerRef.current.style.transform = '';
|
|
@@ -1029,18 +1023,18 @@ var WoongCanvasLayerComponent = function (props) {
|
|
|
1029
1023
|
/**
|
|
1030
1024
|
* 선택 상태 동기화 (최적화 버전)
|
|
1031
1025
|
*
|
|
1032
|
-
*
|
|
1026
|
+
* data가 변경되면 selectedItemsMapRef도 업데이트 필요
|
|
1033
1027
|
* (참조가 바뀌므로 기존 Map의 데이터는 stale 상태)
|
|
1034
1028
|
*
|
|
1035
|
-
* 🔥 중요: 화면 밖
|
|
1036
|
-
* - 현재
|
|
1029
|
+
* 🔥 중요: 화면 밖 데이터도 선택 상태 유지!
|
|
1030
|
+
* - 현재 data에 있으면 최신 데이터로 업데이트
|
|
1037
1031
|
* - 없으면 기존 selectedItemsMapRef의 데이터 유지
|
|
1038
1032
|
*
|
|
1039
|
-
* 최적화:
|
|
1040
|
-
* - O(전체
|
|
1033
|
+
* 최적화: data를 Map으로 먼저 변환하여 find() 순회 제거
|
|
1034
|
+
* - O(전체 데이터 수 + 선택된 개수) - 매우 효율적
|
|
1041
1035
|
*/
|
|
1042
1036
|
|
|
1043
|
-
var markersMap = new Map(
|
|
1037
|
+
var markersMap = new Map(data.map(function (m) {
|
|
1044
1038
|
return [m.id, m];
|
|
1045
1039
|
}));
|
|
1046
1040
|
var newSelectedItemsMap = new Map();
|
|
@@ -1063,7 +1057,7 @@ var WoongCanvasLayerComponent = function (props) {
|
|
|
1063
1057
|
selectedItemsMapRef.current = newSelectedItemsMap; // 즉시 렌더링
|
|
1064
1058
|
|
|
1065
1059
|
renderAllImmediate();
|
|
1066
|
-
}, [
|
|
1060
|
+
}, [data]);
|
|
1067
1061
|
return reactDom.createPortal(React__default["default"].createElement("div", {
|
|
1068
1062
|
ref: containerRef,
|
|
1069
1063
|
style: {
|
|
@@ -1074,27 +1068,96 @@ var WoongCanvasLayerComponent = function (props) {
|
|
|
1074
1068
|
}), divElement);
|
|
1075
1069
|
};
|
|
1076
1070
|
/**
|
|
1077
|
-
*
|
|
1071
|
+
* 🚀 WoongCanvasLayer - Konva 기반 초고성능 마커/폴리곤 렌더링 컴포넌트
|
|
1072
|
+
*
|
|
1073
|
+
* ## 📌 주요 특징
|
|
1074
|
+
* - **30,000개 이상의 폴리곤/마커를 60fps로 렌더링**
|
|
1075
|
+
* - **Multi-Layer 아키텍처**: Base/Animation/Event 레이어 분리
|
|
1076
|
+
* - **Spatial Hash Grid**: O(1) 수준의 빠른 Hit Test
|
|
1077
|
+
* - **LRU 캐시**: 좌표 변환 결과 캐싱으로 성능 최적화
|
|
1078
|
+
* - **Viewport Culling**: 화면에 보이는 영역만 렌더링
|
|
1079
|
+
* - **Discriminated Union Props**: 타입 안전한 MARKER/POLYGON 모드
|
|
1080
|
+
*
|
|
1081
|
+
* ## 🎯 사용 방법
|
|
1082
|
+
*
|
|
1083
|
+
* ### 1️⃣ POLYGON 모드 (자동 렌더링)
|
|
1084
|
+
* ```tsx
|
|
1085
|
+
* <WoongCanvasLayer
|
|
1086
|
+
* dataType={CanvasDataType.POLYGON}
|
|
1087
|
+
* data={polygons}
|
|
1088
|
+
* baseFillColor="rgba(255, 100, 100, 0.5)"
|
|
1089
|
+
* baseStrokeColor="rgba(200, 50, 50, 0.8)"
|
|
1090
|
+
* baseLineWidth={2}
|
|
1091
|
+
* selectedFillColor="rgba(255, 193, 7, 0.7)"
|
|
1092
|
+
* selectedStrokeColor="rgba(255, 152, 0, 1)"
|
|
1093
|
+
* selectedLineWidth={4}
|
|
1094
|
+
* hoveredFillColor="rgba(100, 150, 255, 0.8)" // optional
|
|
1095
|
+
* hoveredStrokeColor="rgba(0, 100, 200, 1)" // optional
|
|
1096
|
+
* hoveredLineWidth={3} // optional
|
|
1097
|
+
* enableMultiSelect={true}
|
|
1098
|
+
* onClick={handleClick}
|
|
1099
|
+
* />
|
|
1100
|
+
* ```
|
|
1078
1101
|
*
|
|
1079
|
-
*
|
|
1080
|
-
*
|
|
1081
|
-
*
|
|
1102
|
+
* ### 2️⃣ MARKER 모드 (커스텀 렌더링)
|
|
1103
|
+
* ```tsx
|
|
1104
|
+
* <WoongCanvasLayer
|
|
1105
|
+
* dataType={CanvasDataType.MARKER}
|
|
1106
|
+
* data={markers}
|
|
1107
|
+
* renderBase={renderMarkerBase} // required
|
|
1108
|
+
* renderAnimation={renderMarkerAnimation} // optional
|
|
1109
|
+
* renderEvent={renderMarkerEvent} // optional
|
|
1110
|
+
* topOnHover={true}
|
|
1111
|
+
* onClick={handleClick}
|
|
1112
|
+
* />
|
|
1113
|
+
* ```
|
|
1082
1114
|
*
|
|
1083
|
-
*
|
|
1115
|
+
* ## 📊 데이터 형식
|
|
1116
|
+
* ```typescript
|
|
1117
|
+
* const data: KonvaCanvasData<T>[] = [
|
|
1118
|
+
* {
|
|
1119
|
+
* id: 'unique-id',
|
|
1120
|
+
* position: new Position(lat, lng),
|
|
1121
|
+
* // POLYGON: paths 필수
|
|
1122
|
+
* paths: [[[lat, lng], [lat, lng], ...]],
|
|
1123
|
+
* // MARKER: boxWidth/boxHeight 권장 (Hit Test 정확도)
|
|
1124
|
+
* boxWidth: 60,
|
|
1125
|
+
* boxHeight: 75,
|
|
1126
|
+
* // 커스텀 데이터
|
|
1127
|
+
* ...customData
|
|
1128
|
+
* }
|
|
1129
|
+
* ];
|
|
1130
|
+
* ```
|
|
1131
|
+
*
|
|
1132
|
+
* ## ⚡ 성능 최적화 팁
|
|
1133
|
+
* 1. **동적 boxWidth 계산**: `measureText()`로 실제 너비 계산 후 전달
|
|
1134
|
+
* 2. **enableViewportCulling**: 대량 데이터 시 필수 (기본 true)
|
|
1135
|
+
* 3. **selectedItems 외부 관리**: 상태를 외부에서 관리하여 리렌더링 최소화
|
|
1136
|
+
* 4. **React.memo 최적화**: 컴포넌트가 자동으로 불필요한 리렌더링 방지
|
|
1137
|
+
*
|
|
1138
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
1139
|
+
*
|
|
1140
|
+
* @example
|
|
1141
|
+
* // 동적 boxWidth 계산 예시
|
|
1142
|
+
* const tempCtx = document.createElement('canvas').getContext('2d');
|
|
1143
|
+
* tempCtx.font = 'bold 15px Arial';
|
|
1144
|
+
* const boxWidth = Math.max(60, tempCtx.measureText(text).width + 20);
|
|
1145
|
+
*
|
|
1146
|
+
* @see {@link https://github.com/your-repo/docs/WoongCanvasLayer.md} 전체 문서
|
|
1084
1147
|
*/
|
|
1085
1148
|
|
|
1086
1149
|
|
|
1087
1150
|
var WoongCanvasLayer = React__default["default"].memo(WoongCanvasLayerComponent, function (prevProps, nextProps) {
|
|
1088
|
-
// 1.
|
|
1089
|
-
var
|
|
1090
|
-
var
|
|
1151
|
+
// 1. data 비교
|
|
1152
|
+
var prevData = prevProps.data;
|
|
1153
|
+
var nextData = nextProps.data; // 참조가 같으면 스킵
|
|
1091
1154
|
|
|
1092
|
-
if (
|
|
1155
|
+
if (prevData !== nextData) {
|
|
1093
1156
|
// 길이가 다르면 변경됨
|
|
1094
|
-
if (
|
|
1157
|
+
if (prevData.length !== nextData.length) return false; // 각 데이터의 ID 비교
|
|
1095
1158
|
|
|
1096
|
-
for (var i = 0; i <
|
|
1097
|
-
if (
|
|
1159
|
+
for (var i = 0; i < prevData.length; i++) {
|
|
1160
|
+
if (prevData[i].id !== nextData[i].id) {
|
|
1098
1161
|
return false; // 변경됨 → 리렌더링
|
|
1099
1162
|
}
|
|
1100
1163
|
}
|
|
@@ -1109,18 +1172,6 @@ var WoongCanvasLayer = React__default["default"].memo(WoongCanvasLayerComponent,
|
|
|
1109
1172
|
return false; // 변경됨 → 리렌더링
|
|
1110
1173
|
}
|
|
1111
1174
|
|
|
1112
|
-
if (prevProps.onClick !== nextProps.onClick) {
|
|
1113
|
-
return false; // 변경됨 → 리렌더링
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1116
|
-
if (prevProps.onMouseOver !== nextProps.onMouseOver) {
|
|
1117
|
-
return false; // 변경됨 → 리렌더링
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
if (prevProps.onMouseOut !== nextProps.onMouseOut) {
|
|
1121
|
-
return false; // 변경됨 → 리렌더링
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
1175
|
if (prevProps.disableInteraction !== nextProps.disableInteraction) {
|
|
1125
1176
|
return false; // 변경됨 → 리렌더링
|
|
1126
1177
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Offset } from "../../../../types";
|
|
3
|
-
import {
|
|
3
|
+
import { KonvaCanvasData } from "./types";
|
|
4
4
|
/**
|
|
5
5
|
* 다중 WoongKonvaMarker 인스턴스를 관리하기 위한 Context
|
|
6
6
|
*
|
|
@@ -12,12 +12,12 @@ import { KonvaCanvasMarkerData } from "./types";
|
|
|
12
12
|
export interface ComponentInstance<T> {
|
|
13
13
|
zIndex: number;
|
|
14
14
|
hitTest: (offset: Offset) => boolean;
|
|
15
|
-
onClick?: (payload:
|
|
16
|
-
onMouseOver?: (payload:
|
|
17
|
-
onMouseOut?: (payload:
|
|
18
|
-
findData: (offset: Offset) =>
|
|
19
|
-
setHovered: (data:
|
|
20
|
-
handleLocalClick: (data:
|
|
15
|
+
onClick?: (payload: KonvaCanvasData<T>, selectedIds: Set<string>) => void;
|
|
16
|
+
onMouseOver?: (payload: KonvaCanvasData<T>) => void;
|
|
17
|
+
onMouseOut?: (payload: KonvaCanvasData<T>) => void;
|
|
18
|
+
findData: (offset: Offset) => KonvaCanvasData<T> | null;
|
|
19
|
+
setHovered: (data: KonvaCanvasData<T> | null) => void;
|
|
20
|
+
handleLocalClick: (data: KonvaCanvasData<T>) => void;
|
|
21
21
|
getSelectedIds: () => Set<string>;
|
|
22
22
|
isInteractionDisabled: () => boolean;
|
|
23
23
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 이 파일은 폴리곤 렌더링을 위한 헬퍼 함수와 팩토리 함수를 제공합니다.
|
|
5
5
|
*/
|
|
6
|
-
import { CustomRenderBase, CustomRenderEvent,
|
|
6
|
+
import { CustomRenderBase, CustomRenderEvent, KonvaCanvasData } from "./types";
|
|
7
7
|
/**
|
|
8
8
|
* 폴리곤 그리기 헬퍼 함수 (도넛 폴리곤 지원)
|
|
9
9
|
*/
|
|
@@ -30,7 +30,7 @@ export declare const drawPolygon: ({ ctx, polygonOffsets, isDonutPolygon, fillCo
|
|
|
30
30
|
* 2
|
|
31
31
|
* );
|
|
32
32
|
*/
|
|
33
|
-
export declare const renderPolygonBase: <T = any>(baseFillColor: string, baseStrokeColor: string, baseLineWidth: number) => CustomRenderBase<
|
|
33
|
+
export declare const renderPolygonBase: <T = any>(baseFillColor: string, baseStrokeColor: string, baseLineWidth: number) => CustomRenderBase<KonvaCanvasData<T>, any>;
|
|
34
34
|
/**
|
|
35
35
|
* 폴리곤 Event 렌더링 함수
|
|
36
36
|
*
|
|
@@ -56,4 +56,4 @@ export declare const renderPolygonBase: <T = any>(baseFillColor: string, baseStr
|
|
|
56
56
|
* 'rgba(100, 150, 255, 0.8)'
|
|
57
57
|
* );
|
|
58
58
|
*/
|
|
59
|
-
export declare const renderPolygonEvent: <T = any>(selectedFillColor: string, selectedStrokeColor: string, selectedLineWidth: number, activeFillColor?: string, activeStrokeColor?: string, activeLineWidth?: number, hoveredFillColor?: string, hoveredStrokeColor?: string, hoveredLineWidth?: number) => CustomRenderEvent<
|
|
59
|
+
export declare const renderPolygonEvent: <T = any>(selectedFillColor: string, selectedStrokeColor: string, selectedLineWidth: number, activeFillColor?: string, activeStrokeColor?: string, activeLineWidth?: number, hoveredFillColor?: string, hoveredStrokeColor?: string, hoveredLineWidth?: number) => CustomRenderEvent<KonvaCanvasData<T>, any>;
|