@mint-ui/map 1.2.0-test.35 → 1.2.0-test.37

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.
Files changed (22) hide show
  1. package/dist/components/mint-map/core/advanced/shared/context.d.ts +9 -71
  2. package/dist/components/mint-map/core/advanced/shared/context.js +43 -137
  3. package/dist/components/mint-map/core/advanced/shared/helpers.d.ts +5 -13
  4. package/dist/components/mint-map/core/advanced/shared/helpers.js +8 -20
  5. package/dist/components/mint-map/core/advanced/shared/hooks.d.ts +6 -76
  6. package/dist/components/mint-map/core/advanced/shared/hooks.js +18 -112
  7. package/dist/components/mint-map/core/advanced/shared/performance.d.ts +9 -188
  8. package/dist/components/mint-map/core/advanced/shared/performance.js +53 -229
  9. package/dist/components/mint-map/core/advanced/shared/types.d.ts +22 -153
  10. package/dist/components/mint-map/core/advanced/shared/types.js +0 -1
  11. package/dist/components/mint-map/core/advanced/shared/utils.d.ts +21 -126
  12. package/dist/components/mint-map/core/advanced/shared/utils.js +46 -152
  13. package/dist/components/mint-map/core/advanced/shared/viewport.d.ts +4 -34
  14. package/dist/components/mint-map/core/advanced/shared/viewport.js +4 -34
  15. package/dist/components/mint-map/core/advanced/woongCanvasMarker/WoongCanvasMarker.d.ts +22 -74
  16. package/dist/components/mint-map/core/advanced/woongCanvasMarker/WoongCanvasMarker.js +128 -519
  17. package/dist/components/mint-map/core/advanced/woongCanvasPolygon/WoongCanvasPolygon.d.ts +26 -76
  18. package/dist/components/mint-map/core/advanced/woongCanvasPolygon/WoongCanvasPolygon.js +118 -432
  19. package/dist/components/mint-map/core/advanced/woongCanvasPolygon/renderer.d.ts +3 -3
  20. package/dist/index.es.js +419 -1637
  21. package/dist/index.umd.js +419 -1637
  22. package/package.json +1 -1
@@ -1,163 +1,58 @@
1
1
  import { Offset } from "../../../types";
2
2
  import { MintMapController } from "../../MintMapController";
3
- import { KonvaCanvasData } from "./types";
3
+ import { CanvasData } from "./types";
4
4
  /**
5
- * 폴리곤 offset 계산
5
+ * 폴리곤 좌표 변환 (위경도 → 화면 좌표)
6
6
  *
7
- * GeoJSON MultiPolygon 형식의 위경도 좌표를 화면 픽셀 좌표로 변환합니다.
8
- *
9
- * @param polygonData 폴리곤 데이터 (paths 필드 필수)
7
+ * @param polygonData 폴리곤 데이터
10
8
  * @param controller MintMapController 인스턴스
11
- * @returns 변환된 화면 좌표 배열 (4차원 배열) 또는 null (변환 실패 시)
12
- *
13
- * @remarks
14
- * - 반환 형식: [MultiPolygon][Polygon][Point][x/y]
15
- * - 성능: O(n), n은 폴리곤의 총 좌표 수
16
- * - GeoJSON MultiPolygon 형식 지원
17
- *
18
- * @example
19
- * ```typescript
20
- * const offsets = computePolygonOffsets(polygonData, controller);
21
- * if (!offsets) return; // 변환 실패
22
- *
23
- * // offsets 구조: [MultiPolygon][Polygon][Point][x/y]
24
- * for (const multiPolygon of offsets) {
25
- * for (const polygon of multiPolygon) {
26
- * // polygon은 [Point][x/y] 배열
27
- * }
28
- * }
29
- * ```
9
+ * @returns 변환된 화면 좌표 배열 (4차원 배열) 또는 null
30
10
  */
31
- export declare const computePolygonOffsets: (polygonData: KonvaCanvasData<any>, controller: MintMapController) => number[][][][] | null;
11
+ export declare const computePolygonOffsets: (polygonData: CanvasData<any>, controller: MintMapController) => number[][][][] | null;
32
12
  /**
33
- * 마커 offset 계산
34
- *
35
- * 마커의 위경도 좌표를 화면 픽셀 좌표로 변환합니다.
13
+ * 마커 좌표 변환 (위경도 → 화면 좌표)
36
14
  *
37
- * @param markerData 마커 데이터 (position 필드 필수)
15
+ * @param markerData 마커 데이터
38
16
  * @param controller MintMapController 인스턴스
39
- * @returns 변환된 화면 좌표 (Offset) 또는 null (변환 실패 시)
40
- *
41
- * @remarks
42
- * - 반환된 좌표는 마커의 중심점 (x, y)
43
- * - 성능: O(1) - 단일 좌표 변환
44
- *
45
- * @example
46
- * ```typescript
47
- * const offset = computeMarkerOffset(markerData, controller);
48
- * if (!offset) return; // 변환 실패
49
- * // offset.x, offset.y는 화면 픽셀 좌표
50
- * ```
17
+ * @returns 변환된 화면 좌표 또는 null
51
18
  */
52
- export declare const computeMarkerOffset: (markerData: KonvaCanvasData<any>, controller: MintMapController) => Offset | null;
19
+ export declare const computeMarkerOffset: (markerData: CanvasData<any>, controller: MintMapController) => Offset | null;
53
20
  /**
54
- * Point-in-Polygon 알고리즘
55
- *
56
- * Ray Casting 알고리즘을 사용하여 점이 폴리곤 내부에 있는지 확인합니다.
21
+ * Point-in-Polygon 알고리즘 (Ray Casting)
57
22
  *
58
23
  * @param point 확인할 점의 좌표
59
- * @param polygon 폴리곤 좌표 배열 (각 요소는 [x, y] 형식)
60
- * @returns 점이 폴리곤 내부에 있으면 true, 아니면 false
61
- *
62
- * @remarks
63
- * - **알고리즘**: Ray Casting (Ray Crossing)
64
- * - **성능**: O(n), n은 폴리곤의 좌표 수
65
- * - **경계 처리**: 경계선 위의 점은 내부로 간주
66
- *
67
- * @example
68
- * ```typescript
69
- * const point = { x: 100, y: 200 };
70
- * const polygon = [[0, 0], [100, 0], [100, 100], [0, 100]];
71
- * const isInside = isPointInPolygon(point, polygon);
72
- * ```
24
+ * @param polygon 폴리곤 좌표 배열
25
+ * @returns 점이 폴리곤 내부에 있으면 true
73
26
  */
74
27
  export declare const isPointInPolygon: (point: Offset, polygon: number[][]) => boolean;
75
28
  /**
76
29
  * 폴리곤 히트 테스트 (도넛 폴리곤 지원)
77
30
  *
78
- * 점이 폴리곤 내부에 있는지 확인합니다. 도넛 폴리곤(구멍이 있는 폴리곤)을 지원합니다.
79
- *
80
31
  * @param clickedOffset 클릭/마우스 위치 좌표
81
32
  * @param polygonData 폴리곤 데이터
82
33
  * @param getPolygonOffsets 폴리곤 좌표 변환 함수
83
- * @returns 점이 폴리곤 내부에 있으면 true, 아니면 false
84
- *
85
- * @remarks
86
- * - **도넛 폴리곤 처리** (isDonutPolygon === true):
87
- * 1. 외부 폴리곤(첫 번째): 내부에 있어야 함
88
- * 2. 내부 구멍들(나머지): 내부에 있으면 안 됨 (evenodd 규칙)
89
- * - **일반 폴리곤 처리**: Point-in-Polygon 알고리즘 사용
90
- * - **성능**: O(n), n은 폴리곤의 총 좌표 수
91
- *
92
- * **중요**: 도넛 폴리곤과 내부 폴리곤은 별개의 polygonData로 처리됩니다.
93
- * - 도넛 폴리곤 A: isDonutPolygon=true
94
- * - 내부 폴리곤 B: isDonutPolygon=false (별도 데이터)
95
- *
96
- * @example
97
- * ```typescript
98
- * const isHit = isPointInPolygonData(
99
- * clickedOffset,
100
- * polygonData,
101
- * getOrComputePolygonOffsets
102
- * );
103
- * ```
34
+ * @returns 점이 폴리곤 내부에 있으면 true
104
35
  */
105
- export declare const isPointInPolygonData: (clickedOffset: Offset, polygonData: KonvaCanvasData<any>, getPolygonOffsets: (data: KonvaCanvasData<any>) => number[][][][] | null) => boolean;
36
+ export declare const isPointInPolygonData: (clickedOffset: Offset, polygonData: CanvasData<any>, getPolygonOffsets: (data: CanvasData<any>) => number[][][][] | null) => boolean;
106
37
  /**
107
- * 마커 히트 테스트 (클릭/hover 영역 체크)
108
- *
109
- * 점이 마커의 클릭/호버 영역 내부에 있는지 확인합니다.
110
- * 마커의 꼬리(tail)는 Hit Test 영역에서 제외됩니다.
38
+ * 마커 히트 테스트 (꼬리 제외, 오프셋 지원)
111
39
  *
112
40
  * @param clickedOffset 클릭/마우스 위치 좌표
113
41
  * @param markerData 마커 데이터
114
42
  * @param getMarkerOffset 마커 좌표 변환 함수
115
- * @returns 점이 마커 영역 내부에 있으면 true, 아니면 false
116
- *
117
- * @remarks
118
- * - **꼬리 제외**: 꼬리(tail)는 Hit Test 영역에서 제외됩니다
119
- * - markerOffset.y는 마커 최하단(꼬리 끝) 좌표
120
- * - boxHeight는 마커 본체만 포함 (꼬리 제외)
121
- * - tailHeight만큼 위로 올려서 본체만 Hit Test 영역으로 사용
122
- * - **성능**: O(1) - 단순 사각형 영역 체크
123
- *
124
- * @example
125
- * ```typescript
126
- * const isHit = isPointInMarkerData(
127
- * clickedOffset,
128
- * markerData,
129
- * getOrComputeMarkerOffset
130
- * );
131
- * ```
43
+ * @returns 점이 마커 영역 내부에 있으면 true
132
44
  */
133
- export declare const isPointInMarkerData: (clickedOffset: Offset, markerData: KonvaCanvasData<any>, getMarkerOffset: (data: KonvaCanvasData<any>) => Offset | null) => boolean;
45
+ export declare const isPointInMarkerData: (clickedOffset: Offset, markerData: CanvasData<any>, getMarkerOffset: (data: CanvasData<any>) => Offset | null) => boolean;
134
46
  export declare const hexToRgba: (hexColor: string, alpha?: number) => string;
135
47
  /**
136
- * 텍스트 박스의 너비를 계산합니다.
137
- *
138
- * Canvas 2D Context의 measureText()를 사용하여 텍스트의 실제 너비를 계산하고,
139
- * 패딩과 최소 너비를 고려하여 최종 너비를 반환합니다.
48
+ * 텍스트 박스 너비 계산
140
49
  *
141
50
  * @param params 파라미터 객체
142
51
  * @param params.text 측정할 텍스트
143
- * @param params.fontConfig 폰트 설정 (예: 'bold 16px Arial')
144
- * @param params.padding 텍스트 박스에 적용할 패딩 값 (px)
52
+ * @param params.fontConfig 폰트 설정
53
+ * @param params.padding 패딩 값 (px)
145
54
  * @param params.minWidth 최소 너비 (px)
146
- * @returns 계산된 텍스트 박스의 너비 (px)
147
- *
148
- * @remarks
149
- * - 성능: O(1) - 단일 텍스트 측정
150
- * - 임시 Canvas를 사용하여 정확한 너비 측정
151
- *
152
- * @example
153
- * ```typescript
154
- * const width = calculateTextBoxWidth({
155
- * text: "Hello World",
156
- * fontConfig: 'bold 16px Arial',
157
- * padding: 20,
158
- * minWidth: 60
159
- * });
160
- * ```
55
+ * @returns 계산된 텍스트 박스 너비 (px)
161
56
  */
162
57
  export declare const calculateTextBoxWidth: ({ text, fontConfig, padding, minWidth, }: {
163
58
  text: string;
@@ -7,31 +7,11 @@ var MapTypes = require('../../../types/MapTypes.js');
7
7
  require('../../../types/MapEventTypes.js');
8
8
 
9
9
  /**
10
- * 폴리곤 offset 계산
10
+ * 폴리곤 좌표 변환 (위경도 → 화면 좌표)
11
11
  *
12
- * GeoJSON MultiPolygon 형식의 위경도 좌표를 화면 픽셀 좌표로 변환합니다.
13
- *
14
- * @param polygonData 폴리곤 데이터 (paths 필드 필수)
12
+ * @param polygonData 폴리곤 데이터
15
13
  * @param controller MintMapController 인스턴스
16
- * @returns 변환된 화면 좌표 배열 (4차원 배열) 또는 null (변환 실패 시)
17
- *
18
- * @remarks
19
- * - 반환 형식: [MultiPolygon][Polygon][Point][x/y]
20
- * - 성능: O(n), n은 폴리곤의 총 좌표 수
21
- * - GeoJSON MultiPolygon 형식 지원
22
- *
23
- * @example
24
- * ```typescript
25
- * const offsets = computePolygonOffsets(polygonData, controller);
26
- * if (!offsets) return; // 변환 실패
27
- *
28
- * // offsets 구조: [MultiPolygon][Polygon][Point][x/y]
29
- * for (const multiPolygon of offsets) {
30
- * for (const polygon of multiPolygon) {
31
- * // polygon은 [Point][x/y] 배열
32
- * }
33
- * }
34
- * ```
14
+ * @returns 변환된 화면 좌표 배열 (4차원 배열) 또는 null
35
15
  */
36
16
 
37
17
  var computePolygonOffsets = function (polygonData, controller) {
@@ -41,7 +21,7 @@ var computePolygonOffsets = function (polygonData, controller) {
41
21
  return null;
42
22
  }
43
23
 
44
- var result = [];
24
+ var result = []; // GeoJSON MultiPolygon 구조: [MultiPolygon][PolygonGroup][Coordinate][lng, lat]
45
25
 
46
26
  for (var _i = 0, _a = paths.coordinates; _i < _a.length; _i++) {
47
27
  var multiPolygon = _a[_i];
@@ -52,7 +32,8 @@ var computePolygonOffsets = function (polygonData, controller) {
52
32
  var polygonOffsets = [];
53
33
 
54
34
  for (var _c = 0, polygonGroup_1 = polygonGroup; _c < polygonGroup_1.length; _c++) {
55
- var coord = polygonGroup_1[_c];
35
+ var coord = polygonGroup_1[_c]; // GeoJSON은 [lng, lat] 순서이지만 Position은 [lat, lng] 순서
36
+
56
37
  var pos = new MapTypes.Position(coord[1], coord[0]);
57
38
  var offset = controller.positionToOffset(pos);
58
39
  polygonOffsets.push([offset.x, offset.y]);
@@ -67,65 +48,37 @@ var computePolygonOffsets = function (polygonData, controller) {
67
48
  return result;
68
49
  };
69
50
  /**
70
- * 마커 offset 계산
51
+ * 마커 좌표 변환 (위경도 → 화면 좌표)
71
52
  *
72
- * 마커의 위경도 좌표를 화면 픽셀 좌표로 변환합니다.
73
- *
74
- * @param markerData 마커 데이터 (position 필드 필수)
53
+ * @param markerData 마커 데이터
75
54
  * @param controller MintMapController 인스턴스
76
- * @returns 변환된 화면 좌표 (Offset) 또는 null (변환 실패 시)
77
- *
78
- * @remarks
79
- * - 반환된 좌표는 마커의 중심점 (x, y)
80
- * - 성능: O(1) - 단일 좌표 변환
81
- *
82
- * @example
83
- * ```typescript
84
- * const offset = computeMarkerOffset(markerData, controller);
85
- * if (!offset) return; // 변환 실패
86
- * // offset.x, offset.y는 화면 픽셀 좌표
87
- * ```
55
+ * @returns 변환된 화면 좌표 또는 null
88
56
  */
89
57
 
90
58
  var computeMarkerOffset = function (markerData, controller) {
91
- if (!markerData.position) {
92
- return null;
93
- }
94
-
59
+ if (!markerData.position) return null;
95
60
  return controller.positionToOffset(markerData.position);
96
61
  };
97
62
  /**
98
- * Point-in-Polygon 알고리즘
99
- *
100
- * Ray Casting 알고리즘을 사용하여 점이 폴리곤 내부에 있는지 확인합니다.
63
+ * Point-in-Polygon 알고리즘 (Ray Casting)
101
64
  *
102
65
  * @param point 확인할 점의 좌표
103
- * @param polygon 폴리곤 좌표 배열 (각 요소는 [x, y] 형식)
104
- * @returns 점이 폴리곤 내부에 있으면 true, 아니면 false
105
- *
106
- * @remarks
107
- * - **알고리즘**: Ray Casting (Ray Crossing)
108
- * - **성능**: O(n), n은 폴리곤의 좌표 수
109
- * - **경계 처리**: 경계선 위의 점은 내부로 간주
110
- *
111
- * @example
112
- * ```typescript
113
- * const point = { x: 100, y: 200 };
114
- * const polygon = [[0, 0], [100, 0], [100, 100], [0, 100]];
115
- * const isInside = isPointInPolygon(point, polygon);
116
- * ```
66
+ * @param polygon 폴리곤 좌표 배열
67
+ * @returns 점이 폴리곤 내부에 있으면 true
117
68
  */
118
69
 
119
70
  var isPointInPolygon = function (point, polygon) {
71
+ // Ray Casting 알고리즘: 점에서 오른쪽으로 무한히 뻗은 선과 폴리곤 변의 교차 횟수로 판단
120
72
  var inside = false;
121
73
 
122
74
  for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
123
75
  var xi = polygon[i][0],
124
76
  yi = polygon[i][1];
125
77
  var xj = polygon[j][0],
126
- yj = polygon[j][1];
78
+ yj = polygon[j][1]; // 점의 y 좌표가 변의 양 끝점 사이에 있고, 교차점의 x 좌표가 점의 x 좌표보다 큰지 확인
79
+
127
80
  var intersect = yi > point.y !== yj > point.y && point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi;
128
- if (intersect) inside = !inside;
81
+ if (intersect) inside = !inside; // 교차할 때마다 inside 상태 토글
129
82
  }
130
83
 
131
84
  return inside;
@@ -133,42 +86,20 @@ var isPointInPolygon = function (point, polygon) {
133
86
  /**
134
87
  * 폴리곤 히트 테스트 (도넛 폴리곤 지원)
135
88
  *
136
- * 점이 폴리곤 내부에 있는지 확인합니다. 도넛 폴리곤(구멍이 있는 폴리곤)을 지원합니다.
137
- *
138
89
  * @param clickedOffset 클릭/마우스 위치 좌표
139
90
  * @param polygonData 폴리곤 데이터
140
91
  * @param getPolygonOffsets 폴리곤 좌표 변환 함수
141
- * @returns 점이 폴리곤 내부에 있으면 true, 아니면 false
142
- *
143
- * @remarks
144
- * - **도넛 폴리곤 처리** (isDonutPolygon === true):
145
- * 1. 외부 폴리곤(첫 번째): 내부에 있어야 함
146
- * 2. 내부 구멍들(나머지): 내부에 있으면 안 됨 (evenodd 규칙)
147
- * - **일반 폴리곤 처리**: Point-in-Polygon 알고리즘 사용
148
- * - **성능**: O(n), n은 폴리곤의 총 좌표 수
149
- *
150
- * **중요**: 도넛 폴리곤과 내부 폴리곤은 별개의 polygonData로 처리됩니다.
151
- * - 도넛 폴리곤 A: isDonutPolygon=true
152
- * - 내부 폴리곤 B: isDonutPolygon=false (별도 데이터)
153
- *
154
- * @example
155
- * ```typescript
156
- * const isHit = isPointInPolygonData(
157
- * clickedOffset,
158
- * polygonData,
159
- * getOrComputePolygonOffsets
160
- * );
161
- * ```
92
+ * @returns 점이 폴리곤 내부에 있으면 true
162
93
  */
163
94
 
164
95
  var isPointInPolygonData = function (clickedOffset, polygonData, getPolygonOffsets) {
165
96
  var polygonOffsets = getPolygonOffsets(polygonData);
166
- if (!polygonOffsets) return false; // 🍩 도넛 폴리곤 처리 (isDonutPolygon === true)
97
+ if (!polygonOffsets) return false; // 도넛 폴리곤 처리: 외부 폴리곤 내부에 있으면서 구멍(hole) 내부에 있지 않아야 함
167
98
 
168
99
  if (polygonData.isDonutPolygon) {
169
100
  for (var _i = 0, polygonOffsets_1 = polygonOffsets; _i < polygonOffsets_1.length; _i++) {
170
101
  var multiPolygon = polygonOffsets_1[_i];
171
- if (multiPolygon.length === 0) continue; // 외부 폴리곤만 있는 경우 (구멍 없음) - 일반 폴리곤처럼 처리
102
+ if (multiPolygon.length === 0) continue; // 구멍이 없는 경우 일반 폴리곤과 동일
172
103
 
173
104
  if (multiPolygon.length === 1) {
174
105
  if (isPointInPolygon(clickedOffset, multiPolygon[0])) {
@@ -176,33 +107,30 @@ var isPointInPolygonData = function (clickedOffset, polygonData, getPolygonOffse
176
107
  }
177
108
 
178
109
  continue;
179
- } // 1. 외부 폴리곤(첫 번째)에 포함되는지 확인
110
+ } // 외부 폴리곤 내부에 있는지 확인
180
111
 
181
112
 
182
113
  var outerPolygon = multiPolygon[0];
183
114
 
184
115
  if (!isPointInPolygon(clickedOffset, outerPolygon)) {
185
- continue; // 외부 폴리곤 밖이면 다음 multiPolygon 확인
186
- } // 2. 내부 구멍들(나머지)에 포함되는지 확인
116
+ continue;
117
+ } // 구멍 내부에 있으면 false (도넛의 공간)
187
118
 
188
119
 
189
120
  for (var i = 1; i < multiPolygon.length; i++) {
190
121
  var hole = multiPolygon[i];
191
122
 
192
123
  if (isPointInPolygon(clickedOffset, hole)) {
193
- // ❌ 구멍 안에 있음 → 이 도넛 폴리곤은 히트 안 됨
194
- // 다른 multiPolygon 체크하지 않고 바로 false 반환
195
- // (도넛 폴리곤의 구멍 안은 무조건 클릭 불가)
196
124
  return false;
197
125
  }
198
- } // 외부 폴리곤 + 구멍 = 히트!
126
+ } // 외부 폴리곤 내부에 있으면서 모든 구멍 밖에 있으면 true
199
127
 
200
128
 
201
129
  return true;
202
130
  }
203
131
 
204
132
  return false;
205
- } // 일반 폴리곤 처리 (isDonutPolygon === false 또는 undefined)
133
+ } // 일반 폴리곤 처리
206
134
 
207
135
 
208
136
  for (var _a = 0, polygonOffsets_2 = polygonOffsets; _a < polygonOffsets_2.length; _a++) {
@@ -221,31 +149,12 @@ var isPointInPolygonData = function (clickedOffset, polygonData, getPolygonOffse
221
149
  return false;
222
150
  };
223
151
  /**
224
- * 마커 히트 테스트 (클릭/hover 영역 체크)
225
- *
226
- * 점이 마커의 클릭/호버 영역 내부에 있는지 확인합니다.
227
- * 마커의 꼬리(tail)는 Hit Test 영역에서 제외됩니다.
152
+ * 마커 히트 테스트 (꼬리 제외, 오프셋 지원)
228
153
  *
229
154
  * @param clickedOffset 클릭/마우스 위치 좌표
230
155
  * @param markerData 마커 데이터
231
156
  * @param getMarkerOffset 마커 좌표 변환 함수
232
- * @returns 점이 마커 영역 내부에 있으면 true, 아니면 false
233
- *
234
- * @remarks
235
- * - **꼬리 제외**: 꼬리(tail)는 Hit Test 영역에서 제외됩니다
236
- * - markerOffset.y는 마커 최하단(꼬리 끝) 좌표
237
- * - boxHeight는 마커 본체만 포함 (꼬리 제외)
238
- * - tailHeight만큼 위로 올려서 본체만 Hit Test 영역으로 사용
239
- * - **성능**: O(1) - 단순 사각형 영역 체크
240
- *
241
- * @example
242
- * ```typescript
243
- * const isHit = isPointInMarkerData(
244
- * clickedOffset,
245
- * markerData,
246
- * getOrComputeMarkerOffset
247
- * );
248
- * ```
157
+ * @returns 점이 마커 영역 내부에 있으면 true
249
158
  */
250
159
 
251
160
  var isPointInMarkerData = function (clickedOffset, markerData, getMarkerOffset) {
@@ -253,58 +162,43 @@ var isPointInMarkerData = function (clickedOffset, markerData, getMarkerOffset)
253
162
  if (!markerOffset) return false;
254
163
  var boxWidth = markerData.boxWidth || 50;
255
164
  var boxHeight = markerData.boxHeight || 28;
256
- var tailHeight = markerData.tailHeight || 0; // 🎯 tailHeight 사용!
165
+ var tailHeight = markerData.tailHeight || 0;
166
+ var offsetX = markerData.offsetX || 0;
167
+ var offsetY = markerData.offsetY || 0; // 오프셋을 적용한 마커 중심점 기준으로 박스 영역 계산 (꼬리는 제외)
257
168
 
258
- var x = markerOffset.x - boxWidth / 2;
259
- var y = markerOffset.y - boxHeight - tailHeight; // 🔥 꼬리만큼 위로!
169
+ var x = markerOffset.x + offsetX - boxWidth / 2;
170
+ var y = markerOffset.y + offsetY - boxHeight - tailHeight; // 클릭 위치가 박스 영역 내부에 있는지 확인
260
171
 
261
172
  return clickedOffset.x >= x && clickedOffset.x <= x + boxWidth && clickedOffset.y >= y && clickedOffset.y <= y + boxHeight;
262
- };
173
+ }; // Hex 색상을 RGBA로 변환
174
+
263
175
  var hexToRgba = function (hexColor, alpha) {
264
176
  if (alpha === void 0) {
265
177
  alpha = 1;
266
- } // NOTE: 입력된 hexColor에서 "#" 제거
267
-
178
+ }
268
179
 
269
- var hex = hexColor.replace('#', ''); // NOTE: 6자리일 경우 알파 값은 사용자가 제공한 alpha 값으로 설정
180
+ var hex = hexColor.replace('#', '');
270
181
 
271
- if (hex.length === 6) {
272
- var r = parseInt(hex.substring(0, 2), 16);
273
- var g = parseInt(hex.substring(2, 4), 16);
274
- var b = parseInt(hex.substring(4, 6), 16);
275
- return "rgba(".concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(alpha, ")");
182
+ if (hex.length !== 6) {
183
+ throw new Error('Invalid hex color format');
276
184
  }
277
185
 
278
- throw new Error('Invalid hex color format');
186
+ var r = parseInt(hex.substring(0, 2), 16);
187
+ var g = parseInt(hex.substring(2, 4), 16);
188
+ var b = parseInt(hex.substring(4, 6), 16);
189
+ return "rgba(".concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(alpha, ")");
279
190
  };
280
191
  var tempCanvas = document.createElement('canvas');
281
192
  var tempCtx = tempCanvas.getContext('2d');
282
193
  /**
283
- * 텍스트 박스의 너비를 계산합니다.
284
- *
285
- * Canvas 2D Context의 measureText()를 사용하여 텍스트의 실제 너비를 계산하고,
286
- * 패딩과 최소 너비를 고려하여 최종 너비를 반환합니다.
194
+ * 텍스트 박스 너비 계산
287
195
  *
288
196
  * @param params 파라미터 객체
289
197
  * @param params.text 측정할 텍스트
290
- * @param params.fontConfig 폰트 설정 (예: 'bold 16px Arial')
291
- * @param params.padding 텍스트 박스에 적용할 패딩 값 (px)
198
+ * @param params.fontConfig 폰트 설정
199
+ * @param params.padding 패딩 값 (px)
292
200
  * @param params.minWidth 최소 너비 (px)
293
- * @returns 계산된 텍스트 박스의 너비 (px)
294
- *
295
- * @remarks
296
- * - 성능: O(1) - 단일 텍스트 측정
297
- * - 임시 Canvas를 사용하여 정확한 너비 측정
298
- *
299
- * @example
300
- * ```typescript
301
- * const width = calculateTextBoxWidth({
302
- * text: "Hello World",
303
- * fontConfig: 'bold 16px Arial',
304
- * padding: 20,
305
- * minWidth: 60
306
- * });
307
- * ```
201
+ * @returns 계산된 텍스트 박스 너비 (px)
308
202
  */
309
203
 
310
204
  var calculateTextBoxWidth = function (_a) {
@@ -1,5 +1,5 @@
1
1
  import { MutableRefObject } from "react";
2
- import { KonvaCanvasData } from "./types";
2
+ import { CanvasData } from "./types";
3
3
  /**
4
4
  * 뷰포트 영역 (화면에 보이는 영역)
5
5
  */
@@ -21,20 +21,9 @@ export interface BoundingBox {
21
21
  /**
22
22
  * 현재 뷰포트 영역 계산
23
23
  *
24
- * Konva Stage 크기와 컬링 마진을 기반으로 뷰포트 경계를 계산합니다.
25
- *
26
- * @param stage Konva Stage 인스턴스 (width, height 메서드 제공)
24
+ * @param stage Konva Stage 인스턴스
27
25
  * @param cullingMargin 컬링 여유 공간 (px)
28
26
  * @param viewportRef 뷰포트 경계를 저장할 ref
29
- *
30
- * @remarks
31
- * - 화면 밖 cullingMargin만큼의 영역까지 포함하여 계산
32
- * - 스크롤 시 부드러운 전환을 위해 여유 공간 포함
33
- *
34
- * @example
35
- * ```typescript
36
- * updateViewport(stageRef.current, cullingMargin, viewportRef);
37
- * ```
38
27
  */
39
28
  export declare const updateViewport: (stage: {
40
29
  width: () => number;
@@ -43,30 +32,11 @@ export declare const updateViewport: (stage: {
43
32
  /**
44
33
  * 아이템이 현재 뷰포트 안에 있는지 확인 (바운딩 박스 캐싱)
45
34
  *
46
- * 뷰포트 컬링을 위한 함수입니다. 바운딩 박스와 뷰포트 경계의 교차를 확인합니다.
47
- * 바운딩 박스는 캐시되어 성능을 최적화합니다.
48
- *
49
35
  * @template T 마커/폴리곤 데이터의 추가 속성 타입
50
36
  * @param item 확인할 아이템
51
- * @param enableViewportCulling 뷰포트 컬링 활성화 여부
52
37
  * @param viewportRef 뷰포트 경계 ref
53
38
  * @param boundingBoxCacheRef 바운딩 박스 캐시 ref
54
39
  * @param computeBoundingBox 바운딩 박스 계산 함수
55
- * @returns 뷰포트 안에 있으면 true, 아니면 false
56
- *
57
- * @remarks
58
- * - 성능: O(1) (캐시 히트 시) 또는 O(바운딩 박스 계산 비용) (캐시 미스 시)
59
- * - 바운딩 박스는 자동으로 캐시되어 재사용됨
60
- *
61
- * @example
62
- * ```typescript
63
- * const isVisible = isInViewport(
64
- * item,
65
- * enableViewportCulling,
66
- * viewportRef,
67
- * boundingBoxCacheRef,
68
- * computeBoundingBox
69
- * );
70
- * ```
40
+ * @returns 뷰포트 안에 있으면 true
71
41
  */
72
- export declare const isInViewport: <T>(item: KonvaCanvasData<T>, enableViewportCulling: boolean, viewportRef: MutableRefObject<ViewportBounds | null>, boundingBoxCacheRef: MutableRefObject<Map<string, BoundingBox>>, computeBoundingBox: (item: KonvaCanvasData<T>) => BoundingBox | null) => boolean;
42
+ export declare const isInViewport: <T>(item: CanvasData<T>, viewportRef: MutableRefObject<ViewportBounds | null>, boundingBoxCacheRef: MutableRefObject<Map<string, BoundingBox>>, computeBoundingBox: (item: CanvasData<T>) => BoundingBox | null) => boolean;
@@ -5,20 +5,9 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  /**
6
6
  * 현재 뷰포트 영역 계산
7
7
  *
8
- * Konva Stage 크기와 컬링 마진을 기반으로 뷰포트 경계를 계산합니다.
9
- *
10
- * @param stage Konva Stage 인스턴스 (width, height 메서드 제공)
8
+ * @param stage Konva Stage 인스턴스
11
9
  * @param cullingMargin 컬링 여유 공간 (px)
12
10
  * @param viewportRef 뷰포트 경계를 저장할 ref
13
- *
14
- * @remarks
15
- * - 화면 밖 cullingMargin만큼의 영역까지 포함하여 계산
16
- * - 스크롤 시 부드러운 전환을 위해 여유 공간 포함
17
- *
18
- * @example
19
- * ```typescript
20
- * updateViewport(stageRef.current, cullingMargin, viewportRef);
21
- * ```
22
11
  */
23
12
  var updateViewport = function (stage, cullingMargin, viewportRef) {
24
13
  if (!stage) return;
@@ -32,35 +21,16 @@ var updateViewport = function (stage, cullingMargin, viewportRef) {
32
21
  /**
33
22
  * 아이템이 현재 뷰포트 안에 있는지 확인 (바운딩 박스 캐싱)
34
23
  *
35
- * 뷰포트 컬링을 위한 함수입니다. 바운딩 박스와 뷰포트 경계의 교차를 확인합니다.
36
- * 바운딩 박스는 캐시되어 성능을 최적화합니다.
37
- *
38
24
  * @template T 마커/폴리곤 데이터의 추가 속성 타입
39
25
  * @param item 확인할 아이템
40
- * @param enableViewportCulling 뷰포트 컬링 활성화 여부
41
26
  * @param viewportRef 뷰포트 경계 ref
42
27
  * @param boundingBoxCacheRef 바운딩 박스 캐시 ref
43
28
  * @param computeBoundingBox 바운딩 박스 계산 함수
44
- * @returns 뷰포트 안에 있으면 true, 아니면 false
45
- *
46
- * @remarks
47
- * - 성능: O(1) (캐시 히트 시) 또는 O(바운딩 박스 계산 비용) (캐시 미스 시)
48
- * - 바운딩 박스는 자동으로 캐시되어 재사용됨
49
- *
50
- * @example
51
- * ```typescript
52
- * const isVisible = isInViewport(
53
- * item,
54
- * enableViewportCulling,
55
- * viewportRef,
56
- * boundingBoxCacheRef,
57
- * computeBoundingBox
58
- * );
59
- * ```
29
+ * @returns 뷰포트 안에 있으면 true
60
30
  */
61
31
 
62
- var isInViewport = function (item, enableViewportCulling, viewportRef, boundingBoxCacheRef, computeBoundingBox) {
63
- if (!enableViewportCulling || !viewportRef.current) return true;
32
+ var isInViewport = function (item, viewportRef, boundingBoxCacheRef, computeBoundingBox) {
33
+ if (!viewportRef.current) return true;
64
34
  var viewport = viewportRef.current; // 캐시된 바운딩 박스 확인
65
35
 
66
36
  var bbox = boundingBoxCacheRef.current.get(item.id);