@mint-ui/map 1.2.0-test.8 → 1.2.0
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/.eslintrc.js +11 -4
- package/.vscode/settings.json +32 -9
- package/dist/components/mint-map/core/MintMapController.d.ts +1 -0
- package/dist/components/mint-map/core/MintMapCore.js +5 -6
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/CanvasMarkerLayer.d.ts +12 -0
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/CanvasMarkerLayer.js +962 -0
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/index.d.ts +4 -0
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/types.d.ts +280 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/CanvasPolygonLayer.d.ts +17 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/CanvasPolygonLayer.js +624 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/index.d.ts +4 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/renderer.d.ts +303 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/renderer.js +1091 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/types.d.ts +284 -0
- package/dist/components/mint-map/core/advanced/canvas/CanvasMarker.d.ts +7 -0
- package/dist/components/mint-map/core/advanced/canvas/CanvasMarkerClaude.js +7 -7
- package/dist/components/mint-map/core/advanced/canvas/index.d.ts +0 -1
- package/dist/components/mint-map/core/advanced/index.d.ts +4 -2
- package/dist/components/mint-map/core/advanced/shared/context.d.ts +44 -0
- package/dist/components/mint-map/core/advanced/shared/context.js +230 -0
- package/dist/components/mint-map/core/advanced/shared/helpers.d.ts +20 -0
- package/dist/components/mint-map/core/advanced/shared/helpers.js +41 -0
- package/dist/components/mint-map/core/advanced/shared/hooks.d.ts +74 -0
- package/dist/components/mint-map/core/advanced/shared/hooks.js +196 -0
- package/dist/components/mint-map/core/advanced/{woongCanvas/shared → shared}/index.d.ts +5 -2
- package/dist/components/mint-map/core/advanced/shared/performance.d.ts +82 -0
- package/dist/components/mint-map/core/advanced/shared/performance.js +288 -0
- package/dist/components/mint-map/core/advanced/shared/types.d.ts +150 -0
- package/dist/components/mint-map/core/advanced/shared/types.js +31 -0
- package/dist/components/mint-map/core/advanced/shared/utils.d.ts +173 -0
- package/dist/components/mint-map/core/advanced/shared/utils.js +382 -0
- package/dist/components/mint-map/core/advanced/shared/viewport.d.ts +42 -0
- package/dist/components/mint-map/core/advanced/shared/viewport.js +52 -0
- package/dist/components/mint-map/core/wrapper/MapMarkerWrapper.js +22 -1
- package/dist/components/mint-map/google/GoogleMintMapController.d.ts +1 -0
- package/dist/components/mint-map/google/GoogleMintMapController.js +13 -8
- package/dist/components/mint-map/kakao/KakaoMintMapController.d.ts +1 -0
- package/dist/components/mint-map/kakao/KakaoMintMapController.js +13 -8
- package/dist/components/mint-map/naver/NaverMintMapController.d.ts +3 -0
- package/dist/components/mint-map/naver/NaverMintMapController.js +46 -11
- package/dist/index.es.js +5605 -4056
- package/dist/index.js +47 -27
- package/dist/index.umd.js +5621 -4059
- package/package.json +1 -1
- package/CLAUDE.md +0 -100
- package/dist/components/mint-map/core/advanced/canvas/CanvasMarkerHanquf.d.ts +0 -22
- package/dist/components/mint-map/core/advanced/canvas/CanvasMarkerHanquf.js +0 -413
- package/dist/components/mint-map/core/advanced/woongCanvas/ClusterMarker.d.ts +0 -11
- package/dist/components/mint-map/core/advanced/woongCanvas/WoongKonvaMarker.d.ts +0 -53
- package/dist/components/mint-map/core/advanced/woongCanvas/WoongKonvaMarker.js +0 -1123
- package/dist/components/mint-map/core/advanced/woongCanvas/index.d.ts +0 -3
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/context.d.ts +0 -31
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/context.js +0 -164
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/performance.d.ts +0 -161
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/performance.js +0 -343
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/types.d.ts +0 -131
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/types.js +0 -14
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/utils.d.ts +0 -31
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/utils.js +0 -164
- package/dist/components/mint-map/core/util/geohash.js +0 -125
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tslib = require('tslib');
|
|
6
|
+
require('../../../types/MapDrawables.js');
|
|
7
|
+
var MapTypes = require('../../../types/MapTypes.js');
|
|
8
|
+
require('../../../types/MapEventTypes.js');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 폴리곤 좌표 변환 (위경도 → 화면 좌표)
|
|
12
|
+
*
|
|
13
|
+
* @param polygonData 폴리곤 데이터
|
|
14
|
+
* @param controller MintMapController 인스턴스
|
|
15
|
+
* @returns 변환된 화면 좌표 배열 (4차원 배열) 또는 null
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
var computePolygonOffsets = function ( // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
polygonData, controller) {
|
|
20
|
+
var paths = polygonData.paths;
|
|
21
|
+
|
|
22
|
+
if (!paths || paths.type !== 'MultiPolygon' || !paths.coordinates) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var result = []; // GeoJSON MultiPolygon 구조: [MultiPolygon][PolygonGroup][Coordinate][lng, lat]
|
|
27
|
+
|
|
28
|
+
for (var _i = 0, _a = paths.coordinates; _i < _a.length; _i++) {
|
|
29
|
+
var multiPolygon = _a[_i];
|
|
30
|
+
var multiPolygonOffsets = [];
|
|
31
|
+
|
|
32
|
+
for (var _b = 0, multiPolygon_1 = multiPolygon; _b < multiPolygon_1.length; _b++) {
|
|
33
|
+
var polygonGroup = multiPolygon_1[_b];
|
|
34
|
+
var polygonOffsets = [];
|
|
35
|
+
|
|
36
|
+
for (var _c = 0, polygonGroup_1 = polygonGroup; _c < polygonGroup_1.length; _c++) {
|
|
37
|
+
var coord = polygonGroup_1[_c]; // GeoJSON은 [lng, lat] 순서이지만 Position은 [lat, lng] 순서
|
|
38
|
+
|
|
39
|
+
var pos = new MapTypes.Position(coord[1], coord[0]);
|
|
40
|
+
var offset = controller.positionToOffset(pos);
|
|
41
|
+
polygonOffsets.push([offset.x, offset.y]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
multiPolygonOffsets.push(polygonOffsets);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
result.push(multiPolygonOffsets);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* 마커 좌표 변환 (위경도 → 화면 좌표)
|
|
54
|
+
*
|
|
55
|
+
* @param markerData 마커 데이터
|
|
56
|
+
* @param controller MintMapController 인스턴스
|
|
57
|
+
* @returns 변환된 화면 좌표 또는 null
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
var computeMarkerOffset = function ( // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
|
+
markerData, controller) {
|
|
62
|
+
if (!markerData.position) return null;
|
|
63
|
+
return controller.positionToOffset(markerData.position);
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Point-in-Polygon 알고리즘 (Ray Casting)
|
|
67
|
+
*
|
|
68
|
+
* @param point 확인할 점의 좌표
|
|
69
|
+
* @param polygon 폴리곤 좌표 배열
|
|
70
|
+
* @returns 점이 폴리곤 내부에 있으면 true
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
var isPointInPolygon = function (point, polygon) {
|
|
74
|
+
// Ray Casting 알고리즘: 점에서 오른쪽으로 무한히 뻗은 선과 폴리곤 변의 교차 횟수로 판단
|
|
75
|
+
var inside = false;
|
|
76
|
+
|
|
77
|
+
for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
|
78
|
+
var xi = polygon[i][0];
|
|
79
|
+
var yi = polygon[i][1];
|
|
80
|
+
var xj = polygon[j][0];
|
|
81
|
+
var yj = polygon[j][1]; // 점의 y 좌표가 변의 양 끝점 사이에 있고, 교차점의 x 좌표가 점의 x 좌표보다 큰지 확인
|
|
82
|
+
|
|
83
|
+
var intersect = yi > point.y !== yj > point.y && point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi;
|
|
84
|
+
if (intersect) inside = !inside; // 교차할 때마다 inside 상태 토글
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return inside;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* 폴리곤 히트 테스트 (도넛 폴리곤 지원)
|
|
91
|
+
*
|
|
92
|
+
* @param clickedOffset 클릭/마우스 위치 좌표
|
|
93
|
+
* @param polygonData 폴리곤 데이터
|
|
94
|
+
* @param getPolygonOffsets 폴리곤 좌표 변환 함수
|
|
95
|
+
* @returns 점이 폴리곤 내부에 있으면 true
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
var isPointInPolygonData = function (clickedOffset, // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
99
|
+
polygonData, // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
100
|
+
getPolygonOffsets) {
|
|
101
|
+
var polygonOffsets = getPolygonOffsets(polygonData);
|
|
102
|
+
if (!polygonOffsets) return false; // 도넛 폴리곤 처리: 외부 폴리곤 내부에 있으면서 구멍(hole) 내부에 있지 않아야 함
|
|
103
|
+
|
|
104
|
+
if (polygonData.isDonutPolygon) {
|
|
105
|
+
for (var _i = 0, polygonOffsets_1 = polygonOffsets; _i < polygonOffsets_1.length; _i++) {
|
|
106
|
+
var multiPolygon = polygonOffsets_1[_i];
|
|
107
|
+
if (multiPolygon.length === 0) continue; // 구멍이 없는 경우 일반 폴리곤과 동일
|
|
108
|
+
|
|
109
|
+
if (multiPolygon.length === 1) {
|
|
110
|
+
if (isPointInPolygon(clickedOffset, multiPolygon[0])) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
continue;
|
|
115
|
+
} // 외부 폴리곤 내부에 있는지 확인
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
var outerPolygon = multiPolygon[0];
|
|
119
|
+
|
|
120
|
+
if (!isPointInPolygon(clickedOffset, outerPolygon)) {
|
|
121
|
+
continue;
|
|
122
|
+
} // 구멍 내부에 있으면 false (도넛의 빈 공간)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
for (var i = 1; i < multiPolygon.length; i++) {
|
|
126
|
+
var hole = multiPolygon[i];
|
|
127
|
+
|
|
128
|
+
if (isPointInPolygon(clickedOffset, hole)) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
} // 외부 폴리곤 내부에 있으면서 모든 구멍 밖에 있으면 true
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return false;
|
|
138
|
+
} // 일반 폴리곤 처리
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
for (var _a = 0, polygonOffsets_2 = polygonOffsets; _a < polygonOffsets_2.length; _a++) {
|
|
142
|
+
var multiPolygon = polygonOffsets_2[_a];
|
|
143
|
+
|
|
144
|
+
for (var _b = 0, multiPolygon_2 = multiPolygon; _b < multiPolygon_2.length; _b++) {
|
|
145
|
+
var polygonGroup = multiPolygon_2[_b];
|
|
146
|
+
if (polygonGroup.length === 0) continue;
|
|
147
|
+
|
|
148
|
+
if (isPointInPolygon(clickedOffset, polygonGroup)) {
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return false;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* 마커 히트 테스트 (꼬리 제외, 오프셋 지원)
|
|
158
|
+
*
|
|
159
|
+
* @param clickedOffset 클릭/마우스 위치 좌표
|
|
160
|
+
* @param markerData 마커 데이터
|
|
161
|
+
* @param getMarkerOffset 마커 좌표 변환 함수
|
|
162
|
+
* @returns 점이 마커 영역 내부에 있으면 true
|
|
163
|
+
*/
|
|
164
|
+
|
|
165
|
+
var isPointInMarkerData = function (clickedOffset, // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
166
|
+
markerData, // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
167
|
+
getMarkerOffset) {
|
|
168
|
+
var markerOffset = getMarkerOffset(markerData);
|
|
169
|
+
if (!markerOffset) return false;
|
|
170
|
+
var boxWidth = markerData.boxWidth || 50;
|
|
171
|
+
var boxHeight = markerData.boxHeight || 28;
|
|
172
|
+
var tailHeight = markerData.tailHeight || 0;
|
|
173
|
+
var offsetX = markerData.offsetX || 0;
|
|
174
|
+
var offsetY = markerData.offsetY || 0; // 오프셋을 적용한 마커 중심점 기준으로 박스 영역 계산 (꼬리는 제외)
|
|
175
|
+
|
|
176
|
+
var x = markerOffset.x + offsetX - boxWidth / 2;
|
|
177
|
+
var y = markerOffset.y + offsetY - boxHeight - tailHeight; // 클릭 위치가 박스 영역 내부에 있는지 확인
|
|
178
|
+
|
|
179
|
+
return clickedOffset.x >= x && clickedOffset.x <= x + boxWidth && clickedOffset.y >= y && clickedOffset.y <= y + boxHeight;
|
|
180
|
+
}; // Hex 색상을 RGBA로 변환
|
|
181
|
+
|
|
182
|
+
var hexToRgba = function (hexColor, alpha) {
|
|
183
|
+
if (alpha === void 0) {
|
|
184
|
+
alpha = 1;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
var hex = hexColor.replace('#', '');
|
|
188
|
+
|
|
189
|
+
if (hex.length !== 6) {
|
|
190
|
+
throw new Error('Invalid hex color format');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
var r = parseInt(hex.substring(0, 2), 16);
|
|
194
|
+
var g = parseInt(hex.substring(2, 4), 16);
|
|
195
|
+
var b = parseInt(hex.substring(4, 6), 16);
|
|
196
|
+
return "rgba(".concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(alpha, ")");
|
|
197
|
+
};
|
|
198
|
+
var tempCanvas = document.createElement('canvas');
|
|
199
|
+
var tempCtx = tempCanvas.getContext('2d');
|
|
200
|
+
/**
|
|
201
|
+
* 텍스트 박스 너비 계산
|
|
202
|
+
*
|
|
203
|
+
* @param params 파라미터 객체
|
|
204
|
+
* @param params.text 측정할 텍스트
|
|
205
|
+
* @param params.fontConfig 폰트 설정
|
|
206
|
+
* @param params.padding 패딩 값 (px)
|
|
207
|
+
* @param params.minWidth 최소 너비 (px)
|
|
208
|
+
* @returns 계산된 텍스트 박스 너비 (px)
|
|
209
|
+
*/
|
|
210
|
+
|
|
211
|
+
var calculateTextBoxWidth = function (_a) {
|
|
212
|
+
var fontConfig = _a.fontConfig,
|
|
213
|
+
minWidth = _a.minWidth,
|
|
214
|
+
padding = _a.padding,
|
|
215
|
+
text = _a.text;
|
|
216
|
+
if (!tempCtx) return 0;
|
|
217
|
+
tempCtx.font = fontConfig;
|
|
218
|
+
var textWidth = tempCtx.measureText(text).width;
|
|
219
|
+
return Math.max(minWidth, textWidth + padding);
|
|
220
|
+
};
|
|
221
|
+
/**
|
|
222
|
+
* 서버 데이터를 CanvasData로 변환하는 헬퍼 함수
|
|
223
|
+
*
|
|
224
|
+
* 서버 데이터의 필드가 CanvasOption과 충돌하는 경우 (예: id, position 등),
|
|
225
|
+
* 이 함수를 사용하여 명시적으로 매핑할 수 있습니다.
|
|
226
|
+
*
|
|
227
|
+
* @template T 서버에서 받은 원본 데이터 타입
|
|
228
|
+
* @param serverData 서버에서 받은 원본 데이터
|
|
229
|
+
* @param canvasOptions CanvasOption 필드들 (충돌하는 필드는 여기서 명시적으로 지정)
|
|
230
|
+
* @returns CanvasData<T> 타입의 데이터
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```typescript
|
|
234
|
+
* interface ServerData {
|
|
235
|
+
* id: number; // CanvasOption의 id와 충돌
|
|
236
|
+
* name: string;
|
|
237
|
+
* }
|
|
238
|
+
*
|
|
239
|
+
* const serverData: ServerData = { id: 123, name: "Test" };
|
|
240
|
+
*
|
|
241
|
+
* // ✅ 올바른 사용
|
|
242
|
+
* const canvasData = createCanvasData(serverData, {
|
|
243
|
+
* id: String(serverData.id), // 명시적으로 변환
|
|
244
|
+
* position: new Position(37.5, 127.0)
|
|
245
|
+
* });
|
|
246
|
+
*
|
|
247
|
+
* // canvasData는 CanvasData<ServerData> 타입이며:
|
|
248
|
+
* // - id: string (CanvasOption의 id)
|
|
249
|
+
* // - name: string (서버 데이터의 name)
|
|
250
|
+
* // - position: Position (CanvasOption의 position)
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
254
|
+
|
|
255
|
+
function createCanvasData(serverData, canvasOptions) {
|
|
256
|
+
// 서버 데이터와 CanvasOption을 결합
|
|
257
|
+
// CanvasOption의 필드가 우선되므로 충돌하는 필드는 canvasOptions의 값이 사용됨
|
|
258
|
+
return tslib.__assign(tslib.__assign({}, serverData), canvasOptions);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* 서버 데이터 배열을 CanvasData 배열로 변환하는 헬퍼 함수
|
|
262
|
+
*
|
|
263
|
+
* 서버 데이터 배열의 각 항목을 CanvasData로 변환합니다.
|
|
264
|
+
* 각 항목마다 다른 CanvasOption을 적용할 수 있습니다.
|
|
265
|
+
*
|
|
266
|
+
* @template T 서버에서 받은 원본 데이터 타입
|
|
267
|
+
* @param serverDataArray 서버에서 받은 원본 데이터 배열
|
|
268
|
+
* @param getCanvasOptions 각 항목에 대해 CanvasOption을 생성하는 함수
|
|
269
|
+
* @returns CanvasData<T>[] 타입의 데이터 배열
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* ```typescript
|
|
273
|
+
* interface ServerData {
|
|
274
|
+
* id: number; // CanvasOption의 id와 충돌
|
|
275
|
+
* name: string;
|
|
276
|
+
* lat: number;
|
|
277
|
+
* lng: number;
|
|
278
|
+
* }
|
|
279
|
+
*
|
|
280
|
+
* const serverDataArray: ServerData[] = [
|
|
281
|
+
* { id: 1, name: "Item 1", lat: 37.5, lng: 127.0 },
|
|
282
|
+
* { id: 2, name: "Item 2", lat: 37.6, lng: 127.1 }
|
|
283
|
+
* ];
|
|
284
|
+
*
|
|
285
|
+
* // ✅ 올바른 사용
|
|
286
|
+
* const canvasDataArray = createCanvasDataArray(serverDataArray, (item, index) => ({
|
|
287
|
+
* id: String(item.id), // 각 항목마다 명시적으로 변환
|
|
288
|
+
* position: new Position(item.lat, item.lng)
|
|
289
|
+
* }));
|
|
290
|
+
*
|
|
291
|
+
* // canvasDataArray는 CanvasData<ServerData>[] 타입입니다
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
295
|
+
|
|
296
|
+
function createCanvasDataArray(serverDataArray, getCanvasOptions) {
|
|
297
|
+
return serverDataArray.map(function (serverData, index) {
|
|
298
|
+
var canvasOptions = getCanvasOptions(serverData, index);
|
|
299
|
+
return createCanvasData(serverData, canvasOptions);
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* 마커 바운딩 박스 좌표 계산 (위도/경도)
|
|
304
|
+
*
|
|
305
|
+
* 마커의 중심 좌표와 크기를 기반으로 현재 뷰포트에서의 바운딩 박스 좌표를 계산합니다.
|
|
306
|
+
*
|
|
307
|
+
* @param params 계산 파라미터
|
|
308
|
+
* @param params.lat 마커의 중심 위도
|
|
309
|
+
* @param params.lng 마커의 중심 경도
|
|
310
|
+
* @param params.width 마커의 너비 (픽셀 단위, boxWidth)
|
|
311
|
+
* @param params.height 마커의 높이 (픽셀 단위, boxHeight)
|
|
312
|
+
* @param params.controller MintMapController 인스턴스 (뷰포트 상태를 알기 위해 필요)
|
|
313
|
+
* @param params.tailHeight 마커 꼬리 높이 (픽셀 단위, 기본값: 0)
|
|
314
|
+
* @param params.offsetX 마커 오프셋 X (픽셀 단위, 기본값: 0)
|
|
315
|
+
* @param params.offsetY 마커 오프셋 Y (픽셀 단위, 기본값: 0)
|
|
316
|
+
* @returns 마커 바운딩 박스 좌표 (위도/경도) 또는 null
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```typescript
|
|
320
|
+
* const boundingBox = calculateMarkerBoundingBox({
|
|
321
|
+
* lat: 37.5665,
|
|
322
|
+
* lng: 126.9780,
|
|
323
|
+
* width: 100,
|
|
324
|
+
* height: 50,
|
|
325
|
+
* controller: mintMapController
|
|
326
|
+
* });
|
|
327
|
+
*
|
|
328
|
+
* if (boundingBox) {
|
|
329
|
+
* console.log('왼쪽 상단:', boundingBox.leftTop);
|
|
330
|
+
* console.log('우측 하단:', boundingBox.bottomRight);
|
|
331
|
+
* }
|
|
332
|
+
* ```
|
|
333
|
+
*/
|
|
334
|
+
|
|
335
|
+
var calculateMarkerBoundingBox = function (params) {
|
|
336
|
+
try {
|
|
337
|
+
var lat = params.lat,
|
|
338
|
+
lng = params.lng,
|
|
339
|
+
width = params.width,
|
|
340
|
+
height = params.height,
|
|
341
|
+
controller = params.controller,
|
|
342
|
+
_a = params.tailHeight,
|
|
343
|
+
tailHeight = _a === void 0 ? 0 : _a,
|
|
344
|
+
_b = params.offsetX,
|
|
345
|
+
offsetX = _b === void 0 ? 0 : _b,
|
|
346
|
+
_c = params.offsetY,
|
|
347
|
+
offsetY = _c === void 0 ? 0 : _c; // 마커의 중심 좌표를 화면 좌표로 변환
|
|
348
|
+
|
|
349
|
+
var markerPosition = new MapTypes.Position(lat, lng);
|
|
350
|
+
var markerOffset = controller.positionToOffset(markerPosition);
|
|
351
|
+
if (!markerOffset) return null; // 바운딩 박스의 화면 좌표 계산
|
|
352
|
+
|
|
353
|
+
var minX = markerOffset.x + offsetX - width / 2;
|
|
354
|
+
var minY = markerOffset.y + offsetY - height - tailHeight;
|
|
355
|
+
var maxX = markerOffset.x + offsetX + width / 2;
|
|
356
|
+
var maxY = markerOffset.y + offsetY; // 왼쪽 상단 좌표를 위도/경도로 변환
|
|
357
|
+
|
|
358
|
+
var leftTopOffset = new MapTypes.Offset(minX, minY);
|
|
359
|
+
var leftTop = controller.offsetToPosition(leftTopOffset); // 우측 하단 좌표를 위도/경도로 변환
|
|
360
|
+
|
|
361
|
+
var bottomRightOffset = new MapTypes.Offset(maxX, maxY);
|
|
362
|
+
var bottomRight = controller.offsetToPosition(bottomRightOffset);
|
|
363
|
+
return {
|
|
364
|
+
bottomRight: bottomRight,
|
|
365
|
+
leftTop: leftTop
|
|
366
|
+
};
|
|
367
|
+
} catch (error) {
|
|
368
|
+
console.error('[calculateMarkerBoundingBox] error:', error);
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
exports.calculateMarkerBoundingBox = calculateMarkerBoundingBox;
|
|
374
|
+
exports.calculateTextBoxWidth = calculateTextBoxWidth;
|
|
375
|
+
exports.computeMarkerOffset = computeMarkerOffset;
|
|
376
|
+
exports.computePolygonOffsets = computePolygonOffsets;
|
|
377
|
+
exports.createCanvasData = createCanvasData;
|
|
378
|
+
exports.createCanvasDataArray = createCanvasDataArray;
|
|
379
|
+
exports.hexToRgba = hexToRgba;
|
|
380
|
+
exports.isPointInMarkerData = isPointInMarkerData;
|
|
381
|
+
exports.isPointInPolygon = isPointInPolygon;
|
|
382
|
+
exports.isPointInPolygonData = isPointInPolygonData;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { MutableRefObject } from 'react';
|
|
2
|
+
import { CanvasData } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* 뷰포트 영역 (화면에 보이는 영역)
|
|
5
|
+
*/
|
|
6
|
+
export interface ViewportBounds {
|
|
7
|
+
minX: number;
|
|
8
|
+
maxX: number;
|
|
9
|
+
minY: number;
|
|
10
|
+
maxY: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 바운딩 박스 (마커/폴리곤의 최소/최대 좌표)
|
|
14
|
+
*/
|
|
15
|
+
export interface BoundingBox {
|
|
16
|
+
minX: number;
|
|
17
|
+
minY: number;
|
|
18
|
+
maxX: number;
|
|
19
|
+
maxY: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 현재 뷰포트 영역 계산
|
|
23
|
+
*
|
|
24
|
+
* @param stage Konva Stage 인스턴스
|
|
25
|
+
* @param cullingMargin 컬링 여유 공간 (px)
|
|
26
|
+
* @param viewportRef 뷰포트 경계를 저장할 ref
|
|
27
|
+
*/
|
|
28
|
+
export declare const updateViewport: (stage: {
|
|
29
|
+
height: () => number;
|
|
30
|
+
width: () => number;
|
|
31
|
+
} | null, cullingMargin: number, viewportRef: MutableRefObject<ViewportBounds | null>) => void;
|
|
32
|
+
/**
|
|
33
|
+
* 아이템이 현재 뷰포트 안에 있는지 확인 (바운딩 박스 캐싱)
|
|
34
|
+
*
|
|
35
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
36
|
+
* @param item 확인할 아이템
|
|
37
|
+
* @param viewportRef 뷰포트 경계 ref
|
|
38
|
+
* @param boundingBoxCacheRef 바운딩 박스 캐시 ref
|
|
39
|
+
* @param computeBoundingBox 바운딩 박스 계산 함수
|
|
40
|
+
* @returns 뷰포트 안에 있으면 true
|
|
41
|
+
*/
|
|
42
|
+
export declare const isInViewport: <T>(itemData: CanvasData<T>, viewportRef: MutableRefObject<ViewportBounds | null>, boundingBoxCacheRef: MutableRefObject<Map<string, BoundingBox>>, computeBoundingBox: (item: CanvasData<T>) => BoundingBox | null) => boolean;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 현재 뷰포트 영역 계산
|
|
7
|
+
*
|
|
8
|
+
* @param stage Konva Stage 인스턴스
|
|
9
|
+
* @param cullingMargin 컬링 여유 공간 (px)
|
|
10
|
+
* @param viewportRef 뷰포트 경계를 저장할 ref
|
|
11
|
+
*/
|
|
12
|
+
var updateViewport = function (stage, cullingMargin, viewportRef) {
|
|
13
|
+
if (!stage) return; // eslint-disable-next-line no-param-reassign
|
|
14
|
+
|
|
15
|
+
viewportRef.current = {
|
|
16
|
+
maxX: stage.width() + cullingMargin,
|
|
17
|
+
maxY: stage.height() + cullingMargin,
|
|
18
|
+
minX: -cullingMargin,
|
|
19
|
+
minY: -cullingMargin
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* 아이템이 현재 뷰포트 안에 있는지 확인 (바운딩 박스 캐싱)
|
|
24
|
+
*
|
|
25
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
26
|
+
* @param item 확인할 아이템
|
|
27
|
+
* @param viewportRef 뷰포트 경계 ref
|
|
28
|
+
* @param boundingBoxCacheRef 바운딩 박스 캐시 ref
|
|
29
|
+
* @param computeBoundingBox 바운딩 박스 계산 함수
|
|
30
|
+
* @returns 뷰포트 안에 있으면 true
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
var isInViewport = function (itemData, viewportRef, boundingBoxCacheRef, computeBoundingBox) {
|
|
34
|
+
if (!viewportRef.current) return true;
|
|
35
|
+
var viewport = viewportRef.current; // 캐시된 바운딩 박스 확인
|
|
36
|
+
|
|
37
|
+
var bbox = boundingBoxCacheRef.current.get(itemData.id);
|
|
38
|
+
|
|
39
|
+
if (!bbox) {
|
|
40
|
+
// 바운딩 박스 계산 (공통 함수 사용)
|
|
41
|
+
var computed = computeBoundingBox(itemData);
|
|
42
|
+
if (!computed) return false;
|
|
43
|
+
bbox = computed;
|
|
44
|
+
boundingBoxCacheRef.current.set(itemData.id, bbox);
|
|
45
|
+
} // 바운딩 박스와 viewport 교차 체크
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
return !(bbox.maxX < viewport.minX || bbox.minX > viewport.maxX || bbox.maxY < viewport.minY || bbox.minY > viewport.maxY);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
exports.isInViewport = isInViewport;
|
|
52
|
+
exports.updateViewport = updateViewport;
|
|
@@ -172,7 +172,7 @@ function MapMarkerWrapper(_a) {
|
|
|
172
172
|
var onMouseOverHandler = function (e) {
|
|
173
173
|
var _a;
|
|
174
174
|
|
|
175
|
-
var marker = markerRef.current;
|
|
175
|
+
var marker = markerRef.current;
|
|
176
176
|
|
|
177
177
|
if (marker) {
|
|
178
178
|
var mouseOverHandler = (_a = options === null || options === void 0 ? void 0 : options.event) === null || _a === void 0 ? void 0 : _a.get('mouseover');
|
|
@@ -185,6 +185,25 @@ function MapMarkerWrapper(_a) {
|
|
|
185
185
|
|
|
186
186
|
next && topOnHover && controller.markerToTheTop(marker);
|
|
187
187
|
}
|
|
188
|
+
}; // 20251014 | 장한별 | mouseleave 이벤트 추가, 마우스가 마커 위에서 떠날 때 원래 zindex 를 복구하기 위함
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
var onMouseLeaveHandler = function (e) {
|
|
192
|
+
var _a;
|
|
193
|
+
|
|
194
|
+
var marker = markerRef.current;
|
|
195
|
+
|
|
196
|
+
if (marker) {
|
|
197
|
+
var mouseOutHandler = (_a = options === null || options === void 0 ? void 0 : options.event) === null || _a === void 0 ? void 0 : _a.get('mouseout');
|
|
198
|
+
var next = true;
|
|
199
|
+
|
|
200
|
+
if (mouseOutHandler) {
|
|
201
|
+
var hasNext = mouseOutHandler(e);
|
|
202
|
+
hasNext !== undefined && (next = hasNext);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
next && topOnHover && controller.restoreMarkerZIndex(marker);
|
|
206
|
+
}
|
|
188
207
|
}; //create object
|
|
189
208
|
|
|
190
209
|
|
|
@@ -202,10 +221,12 @@ function MapMarkerWrapper(_a) {
|
|
|
202
221
|
}); //드래그 여부 초기화를 먼저 수행하기 위해 capture : true 처리
|
|
203
222
|
|
|
204
223
|
divElement.addEventListener('mouseover', onMouseOverHandler);
|
|
224
|
+
divElement.addEventListener('mouseleave', onMouseLeaveHandler);
|
|
205
225
|
return function () {
|
|
206
226
|
divElement.removeEventListener('click', onClickHandler);
|
|
207
227
|
divElement.removeEventListener('mousedown', onMousedownHandler);
|
|
208
228
|
divElement.removeEventListener('mouseover', onMouseOverHandler);
|
|
229
|
+
divElement.removeEventListener('mouseleave', onMouseLeaveHandler);
|
|
209
230
|
|
|
210
231
|
if (markerRef.current) {
|
|
211
232
|
controller.clearDrawable(markerRef.current);
|
|
@@ -28,6 +28,7 @@ export declare class GoogleMintMapController extends MintMapController {
|
|
|
28
28
|
private getMaxZIndex;
|
|
29
29
|
setMarkerZIndex(marker: Marker, zIndex: number): void;
|
|
30
30
|
markerToTheTop(marker: Marker): void;
|
|
31
|
+
restoreMarkerZIndex(marker: Marker): void;
|
|
31
32
|
clearDrawable(drawable: Drawable): boolean;
|
|
32
33
|
private dragged;
|
|
33
34
|
isMapDragged(): boolean;
|
|
@@ -11,19 +11,20 @@ var MapEventTypes = require('../types/MapEventTypes.js');
|
|
|
11
11
|
var MapTypes = require('../types/MapTypes.js');
|
|
12
12
|
require('../core/MintMapCore.js');
|
|
13
13
|
require('react');
|
|
14
|
-
require('../types/MapDrawables.js');
|
|
15
14
|
require('../core/provider/MintMapProvider.js');
|
|
15
|
+
require('../types/MapDrawables.js');
|
|
16
16
|
require('react-dom');
|
|
17
|
-
require('../core/
|
|
17
|
+
require('../core/advanced/canvas/CanvasMarkerClaude.js');
|
|
18
|
+
require('../core/advanced/shared/context.js');
|
|
19
|
+
require('../core/advanced/shared/performance.js');
|
|
20
|
+
require('../core/advanced/shared/types.js');
|
|
21
|
+
require('../core/advanced/shared/utils.js');
|
|
22
|
+
require('konva');
|
|
18
23
|
require('../core/util/geo.js');
|
|
24
|
+
require('../core/util/animation.js');
|
|
25
|
+
require('../core/advanced/MapLoadingComponents.js');
|
|
19
26
|
var polygon = require('../core/util/polygon.js');
|
|
20
27
|
require('../naver/NaverMintMapController.js');
|
|
21
|
-
require('../core/advanced/canvas/CanvasMarkerClaude.js');
|
|
22
|
-
require('../core/advanced/MapLoadingComponents.js');
|
|
23
|
-
require('../core/advanced/woongCanvas/WoongKonvaMarker.js');
|
|
24
|
-
require('../core/advanced/woongCanvas/shared/types.js');
|
|
25
|
-
require('../core/advanced/woongCanvas/shared/context.js');
|
|
26
|
-
require('../core/advanced/woongCanvas/shared/performance.js');
|
|
27
28
|
require('../core/wrapper/MapControlWrapper.js');
|
|
28
29
|
|
|
29
30
|
var GoogleMintMapController =
|
|
@@ -340,6 +341,10 @@ function (_super) {
|
|
|
340
341
|
}
|
|
341
342
|
};
|
|
342
343
|
|
|
344
|
+
GoogleMintMapController.prototype.restoreMarkerZIndex = function (marker) {// Google Maps에서는 restoreMarkerZIndex 기능을 지원하지 않습니다.
|
|
345
|
+
// 이 기능은 Naver Maps에서만 사용 가능합니다.
|
|
346
|
+
};
|
|
347
|
+
|
|
343
348
|
GoogleMintMapController.prototype.clearDrawable = function (drawable) {
|
|
344
349
|
if (drawable && drawable.native) {
|
|
345
350
|
if (drawable.native instanceof google.maps.Marker || drawable.native instanceof google.maps.Polygon || drawable.native instanceof google.maps.Polyline) {
|
|
@@ -31,6 +31,7 @@ export declare class KakaoMintMapController extends MintMapController {
|
|
|
31
31
|
private getMaxZIndex;
|
|
32
32
|
setMarkerZIndex(marker: Marker, zIndex: number): void;
|
|
33
33
|
markerToTheTop(marker: Marker): void;
|
|
34
|
+
restoreMarkerZIndex(marker: Marker): void;
|
|
34
35
|
clearDrawable(drawable: Drawable): boolean;
|
|
35
36
|
private dragged;
|
|
36
37
|
isMapDragged(): boolean;
|
|
@@ -12,19 +12,20 @@ var log = require('../core/util/log.js');
|
|
|
12
12
|
var status = require('../core/util/status.js');
|
|
13
13
|
require('../core/MintMapCore.js');
|
|
14
14
|
require('react');
|
|
15
|
-
require('../types/MapDrawables.js');
|
|
16
15
|
require('../core/provider/MintMapProvider.js');
|
|
16
|
+
require('../types/MapDrawables.js');
|
|
17
17
|
require('react-dom');
|
|
18
|
-
require('../core/
|
|
18
|
+
require('../core/advanced/canvas/CanvasMarkerClaude.js');
|
|
19
|
+
require('../core/advanced/shared/context.js');
|
|
20
|
+
require('../core/advanced/shared/performance.js');
|
|
21
|
+
require('../core/advanced/shared/types.js');
|
|
22
|
+
require('../core/advanced/shared/utils.js');
|
|
23
|
+
require('konva');
|
|
19
24
|
require('../core/util/geo.js');
|
|
25
|
+
require('../core/util/animation.js');
|
|
26
|
+
require('../core/advanced/MapLoadingComponents.js');
|
|
20
27
|
var polygon = require('../core/util/polygon.js');
|
|
21
28
|
require('../naver/NaverMintMapController.js');
|
|
22
|
-
require('../core/advanced/canvas/CanvasMarkerClaude.js');
|
|
23
|
-
require('../core/advanced/MapLoadingComponents.js');
|
|
24
|
-
require('../core/advanced/woongCanvas/WoongKonvaMarker.js');
|
|
25
|
-
require('../core/advanced/woongCanvas/shared/types.js');
|
|
26
|
-
require('../core/advanced/woongCanvas/shared/context.js');
|
|
27
|
-
require('../core/advanced/woongCanvas/shared/performance.js');
|
|
28
29
|
require('../core/wrapper/MapControlWrapper.js');
|
|
29
30
|
|
|
30
31
|
var KakaoMintMapController =
|
|
@@ -348,6 +349,10 @@ function (_super) {
|
|
|
348
349
|
}
|
|
349
350
|
};
|
|
350
351
|
|
|
352
|
+
KakaoMintMapController.prototype.restoreMarkerZIndex = function (marker) {// Kakao Maps에서는 restoreMarkerZIndex 기능을 지원하지 않습니다.
|
|
353
|
+
// 이 기능은 Naver Maps에서만 사용 가능합니다.
|
|
354
|
+
};
|
|
355
|
+
|
|
351
356
|
KakaoMintMapController.prototype.clearDrawable = function (drawable) {
|
|
352
357
|
var _this = this;
|
|
353
358
|
|
|
@@ -27,9 +27,12 @@ export declare class NaverMintMapController extends MintMapController {
|
|
|
27
27
|
createMarker(marker: Marker): void;
|
|
28
28
|
updateMarker(marker: Marker, options: MarkerOptions): void;
|
|
29
29
|
private markerMaxZIndex;
|
|
30
|
+
private markerOriginalZIndex;
|
|
30
31
|
private getMaxZIndex;
|
|
32
|
+
private getCurrentZIndex;
|
|
31
33
|
setMarkerZIndex(marker: Marker, zIndex: number): void;
|
|
32
34
|
markerToTheTop(marker: Marker): void;
|
|
35
|
+
restoreMarkerZIndex(marker: Marker): void;
|
|
33
36
|
clearDrawable(drawable: Drawable): boolean;
|
|
34
37
|
private dragged;
|
|
35
38
|
isMapDragged(): boolean;
|