@mint-ui/map 1.2.0-test.5 → 1.2.0-test.50
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/CLAUDE.md +0 -1
- package/dist/components/mint-map/core/MintMapCore.js +5 -6
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/CanvasMarkerLayer.d.ts +47 -0
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/CanvasMarkerLayer.js +634 -0
- package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/index.d.ts +3 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/CanvasPolygonLayer.d.ts +183 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/CanvasPolygonLayer.js +593 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/index.d.ts +3 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/renderer.d.ts +183 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/renderer.js +482 -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 +3 -1
- package/dist/components/mint-map/core/advanced/shared/context.d.ts +39 -0
- package/dist/components/mint-map/core/advanced/{woongCanvas/shared → shared}/context.js +62 -79
- package/dist/components/mint-map/core/advanced/shared/helpers.d.ts +20 -0
- package/dist/components/mint-map/core/advanced/shared/helpers.js +40 -0
- package/dist/components/mint-map/core/advanced/shared/hooks.d.ts +74 -0
- package/dist/components/mint-map/core/advanced/shared/hooks.js +189 -0
- package/dist/components/mint-map/core/advanced/{woongCanvas/shared → shared}/index.d.ts +3 -0
- package/dist/components/mint-map/core/advanced/shared/performance.d.ts +77 -0
- package/dist/components/mint-map/core/advanced/shared/performance.js +262 -0
- package/dist/components/mint-map/core/advanced/shared/types.d.ts +127 -0
- package/dist/components/mint-map/core/advanced/{woongCanvas/shared → shared}/types.js +5 -1
- package/dist/components/mint-map/core/advanced/shared/utils.d.ts +130 -0
- package/dist/components/mint-map/core/advanced/shared/utils.js +303 -0
- package/dist/components/mint-map/core/advanced/shared/viewport.d.ts +42 -0
- package/dist/components/mint-map/core/advanced/shared/viewport.js +51 -0
- package/dist/components/mint-map/google/GoogleMintMapController.js +5 -4
- package/dist/components/mint-map/kakao/KakaoMintMapController.js +5 -4
- package/dist/components/mint-map/naver/NaverMintMapController.js +5 -4
- package/dist/index.es.js +3064 -2682
- package/dist/index.js +25 -10
- package/dist/index.umd.js +3078 -2684
- package/package.json +1 -1
- 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 -50
- package/dist/components/mint-map/core/advanced/woongCanvas/WoongKonvaMarker.js +0 -1065
- 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/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/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
|
@@ -107,12 +107,12 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
|
|
|
107
107
|
var hoveredPolygonRef = React.useRef(null);
|
|
108
108
|
var clickedPolygonRef = React.useRef(null);
|
|
109
109
|
var hoveredMarkerRef = React.useRef(null);
|
|
110
|
-
var clickedMarkerRef = React.useRef(null); // 🚀
|
|
110
|
+
var clickedMarkerRef = React.useRef(null); // 🚀 CanvasMarker 방식: 단순한 data ref (geohash 제거)
|
|
111
111
|
|
|
112
112
|
var polygonsRef = React.useRef([]);
|
|
113
113
|
var markersRef = React.useRef([]); // 마커 경계 정보 저장 (hit-test용)
|
|
114
114
|
|
|
115
|
-
var markerBoundsRef = React.useRef(new Map()); // 🚀 드래그 추적용 (
|
|
115
|
+
var markerBoundsRef = React.useRef(new Map()); // 🚀 드래그 추적용 (CanvasMarker 방식)
|
|
116
116
|
|
|
117
117
|
var draggingRef = React.useRef(false);
|
|
118
118
|
var prevCenterOffsetRef = React.useRef(null);
|
|
@@ -172,7 +172,7 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
|
|
|
172
172
|
if (!baseContextRef.current || !polygonsRef.current || polygonsRef.current.length === 0) return;
|
|
173
173
|
canvasUtil.clearRect(baseCanvasRef.current, baseContextRef.current);
|
|
174
174
|
var cacheMissCount = 0; // 캐시 미스 카운트
|
|
175
|
-
// 🚀
|
|
175
|
+
// 🚀 CanvasMarker 방식: 전체 데이터 순회 (필터링 제거)
|
|
176
176
|
|
|
177
177
|
polygonsRef.current.forEach(function (polygon) {
|
|
178
178
|
if (polygon.visible === false) return; // 🚀 캐시 확인 (ID 기반으로 변경)
|
|
@@ -243,7 +243,7 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
|
|
|
243
243
|
if (!markersRef.current || markersRef.current.length === 0) return;
|
|
244
244
|
canvasUtil.clearRect(baseMarkerCanvasRef.current, baseMarkerContextRef.current); // 마커 경계 정보 초기화
|
|
245
245
|
|
|
246
|
-
markerBoundsRef.current.clear(); // 🚀
|
|
246
|
+
markerBoundsRef.current.clear(); // 🚀 CanvasMarker 방식: 전체 데이터 순회 (필터링 제거)
|
|
247
247
|
|
|
248
248
|
markersRef.current.forEach(function (marker) {
|
|
249
249
|
var _a, _b;
|
|
@@ -566,7 +566,7 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
|
|
|
566
566
|
}
|
|
567
567
|
|
|
568
568
|
return null;
|
|
569
|
-
}; // IDLE 이벤트 핸들러 (
|
|
569
|
+
}; // IDLE 이벤트 핸들러 (CanvasMarker 최적화 적용)
|
|
570
570
|
|
|
571
571
|
|
|
572
572
|
var handleIdle = function () {
|
|
@@ -632,7 +632,7 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
|
|
|
632
632
|
x: event.clientX - rect.left,
|
|
633
633
|
y: event.clientY - rect.top
|
|
634
634
|
};
|
|
635
|
-
}; // 🚀 지도 클릭 이벤트 핸들러 (
|
|
635
|
+
}; // 🚀 지도 클릭 이벤트 핸들러 (CanvasMarker 방식 - controller.addEventListener)
|
|
636
636
|
|
|
637
637
|
|
|
638
638
|
var handleMapClick = function (event) {
|
|
@@ -724,7 +724,7 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
|
|
|
724
724
|
var rafIdRef = React.useRef(); // 마우스 이벤트 핸들러 (requestAnimationFrame으로 최적화)
|
|
725
725
|
|
|
726
726
|
var handleMouseMove = function (e) {
|
|
727
|
-
// 🚀 드래그 중이면 호버 처리 스킵 (
|
|
727
|
+
// 🚀 드래그 중이면 호버 처리 스킵 (CanvasMarker 방식)
|
|
728
728
|
if (draggingRef.current) return; // 이미 RAF가 대기 중이면 스킵
|
|
729
729
|
|
|
730
730
|
if (rafIdRef.current) return;
|
|
@@ -2,4 +2,6 @@ export * from './shapes';
|
|
|
2
2
|
export * from './canvas';
|
|
3
3
|
export * from './MapBuildingProjection';
|
|
4
4
|
export * from './MapLoadingComponents';
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './shared';
|
|
6
|
+
export * from './CanvasMarkerLayer';
|
|
7
|
+
export * from './CanvasPolygonLayer';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Offset } from "../../../types";
|
|
3
|
+
import { CanvasData } from "./types";
|
|
4
|
+
/**
|
|
5
|
+
* Canvas 컴포넌트 인스턴스 인터페이스
|
|
6
|
+
*
|
|
7
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
8
|
+
*/
|
|
9
|
+
export interface ComponentInstance<T> {
|
|
10
|
+
zIndex: number;
|
|
11
|
+
hitTest: (offset: Offset) => boolean;
|
|
12
|
+
onClick?: (payload: CanvasData<T>, selectedIds: Set<string>) => void;
|
|
13
|
+
onMouseOver?: (payload: CanvasData<T>) => void;
|
|
14
|
+
onMouseOut?: (payload: CanvasData<T>) => void;
|
|
15
|
+
findData: (offset: Offset) => CanvasData<T> | null;
|
|
16
|
+
setHovered: (data: CanvasData<T> | null) => void;
|
|
17
|
+
handleLocalClick: (data: CanvasData<T>) => void;
|
|
18
|
+
getSelectedIds: () => Set<string>;
|
|
19
|
+
isInteractionDisabled: () => boolean;
|
|
20
|
+
}
|
|
21
|
+
interface CanvasContextValue {
|
|
22
|
+
registerComponent: <T>(instance: ComponentInstance<T>) => void;
|
|
23
|
+
unregisterComponent: <T>(instance: ComponentInstance<T>) => void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* CanvasProvider 컴포넌트
|
|
27
|
+
*
|
|
28
|
+
* 다중 Canvas 인스턴스를 관리하고 zIndex 기반 이벤트 우선순위를 처리합니다.
|
|
29
|
+
*/
|
|
30
|
+
export declare const CanvasProvider: React.FC<{
|
|
31
|
+
children: React.ReactNode;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Canvas Context Hook
|
|
35
|
+
*
|
|
36
|
+
* @returns CanvasContextValue 또는 null (Provider 없으면)
|
|
37
|
+
*/
|
|
38
|
+
export declare const useCanvasContext: () => CanvasContextValue | null;
|
|
39
|
+
export {};
|
|
@@ -3,38 +3,35 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
|
-
var MintMapProvider = require('
|
|
6
|
+
var MintMapProvider = require('../../provider/MintMapProvider.js');
|
|
7
7
|
|
|
8
8
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
9
9
|
|
|
10
10
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
11
11
|
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
var CanvasContext = React.createContext(null);
|
|
13
|
+
/**
|
|
14
|
+
* CanvasProvider 컴포넌트
|
|
15
|
+
*
|
|
16
|
+
* 다중 Canvas 인스턴스를 관리하고 zIndex 기반 이벤트 우선순위를 처리합니다.
|
|
17
|
+
*/
|
|
16
18
|
|
|
19
|
+
var CanvasProvider = function (_a) {
|
|
20
|
+
var children = _a.children;
|
|
21
|
+
var controller = MintMapProvider.useMintMapController();
|
|
17
22
|
var componentsRef = React.useRef([]);
|
|
18
23
|
var currentHoveredRef = React.useRef(null);
|
|
19
24
|
var currentHoveredDataRef = React.useRef(null);
|
|
20
|
-
var draggingRef = React.useRef(false);
|
|
21
|
-
/**
|
|
22
|
-
* 컴포넌트 등록 (zIndex 내림차순 정렬)
|
|
23
|
-
* 높은 zIndex가 먼저 처리됨
|
|
24
|
-
*/
|
|
25
|
+
var draggingRef = React.useRef(false); // 컴포넌트 등록 (zIndex 내림차순 정렬)
|
|
25
26
|
|
|
26
27
|
var registerComponent = React.useCallback(function (instance) {
|
|
27
28
|
componentsRef.current.push(instance);
|
|
28
29
|
componentsRef.current.sort(function (a, b) {
|
|
29
30
|
return b.zIndex - a.zIndex;
|
|
30
31
|
});
|
|
31
|
-
}, []);
|
|
32
|
-
/**
|
|
33
|
-
* 컴포넌트 등록 해제
|
|
34
|
-
*/
|
|
32
|
+
}, []); // 컴포넌트 등록 해제
|
|
35
33
|
|
|
36
34
|
var unregisterComponent = React.useCallback(function (instance) {
|
|
37
|
-
// Hover 중이던 컴포넌트면 초기화
|
|
38
35
|
if (currentHoveredRef.current === instance) {
|
|
39
36
|
currentHoveredRef.current = null;
|
|
40
37
|
currentHoveredDataRef.current = null;
|
|
@@ -43,95 +40,77 @@ var KonvaMarkerProvider = function (_a) {
|
|
|
43
40
|
componentsRef.current = componentsRef.current.filter(function (c) {
|
|
44
41
|
return c !== instance;
|
|
45
42
|
});
|
|
46
|
-
}, []);
|
|
47
|
-
/**
|
|
48
|
-
* 전역 클릭 핸들러 (zIndex 우선순위)
|
|
49
|
-
*/
|
|
43
|
+
}, []); // 전역 클릭 핸들러 (zIndex 우선순위)
|
|
50
44
|
|
|
51
45
|
var handleGlobalClick = React.useCallback(function (event) {
|
|
52
|
-
var _a;
|
|
46
|
+
var _a, _b;
|
|
53
47
|
|
|
54
48
|
if (!((_a = event === null || event === void 0 ? void 0 : event.param) === null || _a === void 0 ? void 0 : _a.position)) return;
|
|
55
|
-
var clickedOffset = controller.positionToOffset(event.param.position); // zIndex
|
|
49
|
+
var clickedOffset = controller.positionToOffset(event.param.position); // zIndex 내림차순으로 정렬된 컴포넌트 순회 (높은 zIndex가 먼저 처리)
|
|
56
50
|
|
|
57
|
-
for (var _i = 0,
|
|
58
|
-
var component =
|
|
51
|
+
for (var _i = 0, _c = componentsRef.current; _i < _c.length; _i++) {
|
|
52
|
+
var component = _c[_i];
|
|
53
|
+
if (component.isInteractionDisabled()) continue;
|
|
59
54
|
var data = component.findData(clickedOffset);
|
|
55
|
+
if (!data) continue; // 첫 번째로 찾은 항목만 처리하고 종료 (zIndex 우선순위)
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (component.onClick) {
|
|
65
|
-
component.onClick(data, component.getSelectedIds());
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return; // 첫 번째 히트만 처리
|
|
69
|
-
}
|
|
57
|
+
component.handleLocalClick(data);
|
|
58
|
+
(_b = component.onClick) === null || _b === void 0 ? void 0 : _b.call(component, data, component.getSelectedIds());
|
|
59
|
+
return;
|
|
70
60
|
}
|
|
71
|
-
}, [controller]);
|
|
72
|
-
/**
|
|
73
|
-
* 전역 마우스 이동 핸들러 (zIndex 우선순위)
|
|
74
|
-
*/
|
|
61
|
+
}, [controller]); // 전역 마우스 이동 핸들러 (zIndex 우선순위)
|
|
75
62
|
|
|
76
63
|
var handleGlobalMouseMove = React.useCallback(function (event) {
|
|
77
64
|
var _a;
|
|
78
65
|
|
|
79
66
|
if (draggingRef.current || !((_a = event === null || event === void 0 ? void 0 : event.param) === null || _a === void 0 ? void 0 : _a.position)) return;
|
|
80
|
-
var mouseOffset = controller.positionToOffset(event.param.position);
|
|
81
|
-
|
|
67
|
+
var mouseOffset = controller.positionToOffset(event.param.position);
|
|
82
68
|
var newHoveredComponent = null;
|
|
83
|
-
var newHoveredData = null;
|
|
69
|
+
var newHoveredData = null; // zIndex 내림차순으로 정렬된 컴포넌트 순회 (높은 zIndex가 먼저 처리)
|
|
84
70
|
|
|
85
71
|
for (var _i = 0, _b = componentsRef.current; _i < _b.length; _i++) {
|
|
86
72
|
var component = _b[_i];
|
|
73
|
+
if (component.isInteractionDisabled()) continue;
|
|
87
74
|
var data = component.findData(mouseOffset);
|
|
75
|
+
if (!data) continue; // 첫 번째로 찾은 항목만 hover 처리 (zIndex 우선순위)
|
|
88
76
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
} // Hover 상태 변경 감지 (최적화: 별도 ref로 직접 비교)
|
|
95
|
-
|
|
77
|
+
newHoveredComponent = component;
|
|
78
|
+
newHoveredData = data;
|
|
79
|
+
break;
|
|
80
|
+
} // hover 상태가 변경되지 않았으면 종료 (불필요한 렌더링 방지)
|
|
96
81
|
|
|
97
|
-
if (currentHoveredRef.current !== newHoveredComponent || currentHoveredDataRef.current !== newHoveredData) {
|
|
98
|
-
// 이전 hover 해제
|
|
99
|
-
if (currentHoveredRef.current) {
|
|
100
|
-
currentHoveredRef.current.setHovered(null);
|
|
101
82
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
} // 새 hover 설정
|
|
83
|
+
if (currentHoveredRef.current === newHoveredComponent && currentHoveredDataRef.current === newHoveredData) {
|
|
84
|
+
return;
|
|
85
|
+
} // 기존 hover 항목에 mouseOut 이벤트 발생
|
|
106
86
|
|
|
107
87
|
|
|
108
|
-
|
|
109
|
-
|
|
88
|
+
if (currentHoveredRef.current) {
|
|
89
|
+
currentHoveredRef.current.setHovered(null);
|
|
110
90
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
91
|
+
if (currentHoveredRef.current.onMouseOut && currentHoveredDataRef.current) {
|
|
92
|
+
currentHoveredRef.current.onMouseOut(currentHoveredDataRef.current);
|
|
114
93
|
}
|
|
94
|
+
} // 새 hover 항목에 mouseOver 이벤트 발생
|
|
95
|
+
|
|
115
96
|
|
|
116
|
-
|
|
117
|
-
|
|
97
|
+
if (newHoveredComponent && newHoveredData) {
|
|
98
|
+
newHoveredComponent.setHovered(newHoveredData);
|
|
99
|
+
|
|
100
|
+
if (newHoveredComponent.onMouseOver) {
|
|
101
|
+
newHoveredComponent.onMouseOver(newHoveredData);
|
|
102
|
+
}
|
|
118
103
|
}
|
|
119
|
-
}, [controller]);
|
|
120
|
-
/**
|
|
121
|
-
* 줌/드래그 시작 (마우스 이동 이벤트 무시)
|
|
122
|
-
*/
|
|
123
104
|
|
|
105
|
+
currentHoveredRef.current = newHoveredComponent;
|
|
106
|
+
currentHoveredDataRef.current = newHoveredData;
|
|
107
|
+
}, [controller]);
|
|
124
108
|
var handleZoomStart = React.useCallback(function () {
|
|
125
109
|
draggingRef.current = true;
|
|
126
110
|
}, []);
|
|
127
|
-
/**
|
|
128
|
-
* 지도 idle (마우스 이동 이벤트 재개)
|
|
129
|
-
*/
|
|
130
|
-
|
|
131
111
|
var handleIdle = React.useCallback(function () {
|
|
132
112
|
draggingRef.current = false;
|
|
133
|
-
}, []);
|
|
134
|
-
|
|
113
|
+
}, []);
|
|
135
114
|
React.useEffect(function () {
|
|
136
115
|
controller.addEventListener('CLICK', handleGlobalClick);
|
|
137
116
|
controller.addEventListener('MOUSEMOVE', handleGlobalMouseMove);
|
|
@@ -143,22 +122,26 @@ var KonvaMarkerProvider = function (_a) {
|
|
|
143
122
|
controller.removeEventListener('ZOOMSTART', handleZoomStart);
|
|
144
123
|
controller.removeEventListener('IDLE', handleIdle);
|
|
145
124
|
};
|
|
146
|
-
}, [controller, handleGlobalClick, handleGlobalMouseMove, handleZoomStart, handleIdle]);
|
|
147
|
-
|
|
125
|
+
}, [controller, handleGlobalClick, handleGlobalMouseMove, handleZoomStart, handleIdle]);
|
|
148
126
|
var contextValue = React.useMemo(function () {
|
|
149
127
|
return {
|
|
150
128
|
registerComponent: registerComponent,
|
|
151
129
|
unregisterComponent: unregisterComponent
|
|
152
130
|
};
|
|
153
131
|
}, [registerComponent, unregisterComponent]);
|
|
154
|
-
return React__default["default"].createElement(
|
|
132
|
+
return React__default["default"].createElement(CanvasContext.Provider, {
|
|
155
133
|
value: contextValue
|
|
156
134
|
}, children);
|
|
157
135
|
};
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Canvas Context Hook
|
|
138
|
+
*
|
|
139
|
+
* @returns CanvasContextValue 또는 null (Provider 없으면)
|
|
140
|
+
*/
|
|
141
|
+
|
|
142
|
+
var useCanvasContext = function () {
|
|
143
|
+
return React.useContext(CanvasContext);
|
|
161
144
|
};
|
|
162
145
|
|
|
163
|
-
exports.
|
|
164
|
-
exports.
|
|
146
|
+
exports.CanvasProvider = CanvasProvider;
|
|
147
|
+
exports.useCanvasContext = useCanvasContext;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { EventParam, MapUIEventParam } from "../../../types";
|
|
2
|
+
import type { MintMapController } from "../../MintMapController";
|
|
3
|
+
import type { Offset } from "../../../types";
|
|
4
|
+
/**
|
|
5
|
+
* 이벤트 유효성 검증 및 좌표 변환
|
|
6
|
+
*
|
|
7
|
+
* @param event 이벤트 파라미터
|
|
8
|
+
* @param context CanvasContext 인스턴스
|
|
9
|
+
* @param controller MintMapController 인스턴스
|
|
10
|
+
* @returns 유효한 화면 좌표 또는 null
|
|
11
|
+
*/
|
|
12
|
+
export declare const validateEvent: (event: EventParam<MapUIEventParam> | null | undefined, context: any, controller: MintMapController) => Offset | null;
|
|
13
|
+
/**
|
|
14
|
+
* Map의 values를 배열로 변환
|
|
15
|
+
*
|
|
16
|
+
* @template T Map 값의 타입
|
|
17
|
+
* @param map 변환할 Map
|
|
18
|
+
* @returns Map의 값 배열
|
|
19
|
+
*/
|
|
20
|
+
export declare const mapValuesToArray: <T>(map: Map<string, T>) => T[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 이벤트 유효성 검증 및 좌표 변환
|
|
7
|
+
*
|
|
8
|
+
* @param event 이벤트 파라미터
|
|
9
|
+
* @param context CanvasContext 인스턴스
|
|
10
|
+
* @param controller MintMapController 인스턴스
|
|
11
|
+
* @returns 유효한 화면 좌표 또는 null
|
|
12
|
+
*/
|
|
13
|
+
var validateEvent = function (event, context, controller) {
|
|
14
|
+
var _a;
|
|
15
|
+
|
|
16
|
+
if (context) return null;
|
|
17
|
+
if (!((_a = event === null || event === void 0 ? void 0 : event.param) === null || _a === void 0 ? void 0 : _a.position)) return null;
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
return controller.positionToOffset(event.param.position);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('[CanvasLayer] validateEvent error:', error);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Map의 values를 배열로 변환
|
|
28
|
+
*
|
|
29
|
+
* @template T Map 값의 타입
|
|
30
|
+
* @param map 변환할 Map
|
|
31
|
+
* @returns Map의 값 배열
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
var mapValuesToArray = function (map) {
|
|
35
|
+
if (map.size === 0) return [];
|
|
36
|
+
return Array.from(map.values());
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
exports.mapValuesToArray = mapValuesToArray;
|
|
40
|
+
exports.validateEvent = validateEvent;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { MutableRefObject } from "react";
|
|
2
|
+
import type { MintMapController } from "../../MintMapController";
|
|
3
|
+
import type { Marker, MarkerOptions } from "../../../types";
|
|
4
|
+
import type { CanvasData } from "./types";
|
|
5
|
+
import type { BoundingBox } from "./viewport";
|
|
6
|
+
import type { SpatialHashGrid } from "./performance";
|
|
7
|
+
/**
|
|
8
|
+
* 공통 이벤트 핸들러 의존성 인터페이스
|
|
9
|
+
*
|
|
10
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* 지도 이벤트 핸들러 생성 시 필요한 모든 의존성을 포함합니다.
|
|
14
|
+
*/
|
|
15
|
+
export interface EventHandlerDeps<T> {
|
|
16
|
+
controller: MintMapController;
|
|
17
|
+
containerRef: MutableRefObject<HTMLDivElement | null>;
|
|
18
|
+
markerRef: MutableRefObject<Marker | undefined>;
|
|
19
|
+
options: Pick<MarkerOptions, 'zIndex' | 'anchor' | 'visible'>;
|
|
20
|
+
prevCenterOffsetRef: MutableRefObject<{
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
} | null>;
|
|
24
|
+
accumTranslateRef: MutableRefObject<{
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
}>;
|
|
28
|
+
offsetCacheRef: MutableRefObject<any>;
|
|
29
|
+
boundingBoxCacheRef: MutableRefObject<Map<string, BoundingBox>>;
|
|
30
|
+
renderAllImmediate: () => void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 지도 이벤트 핸들러 생성 함수
|
|
34
|
+
*
|
|
35
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
36
|
+
* @param deps 이벤트 핸들러 생성에 필요한 의존성
|
|
37
|
+
* @returns 지도 이벤트 핸들러 객체
|
|
38
|
+
*/
|
|
39
|
+
export declare const createMapEventHandlers: <T>(deps: EventHandlerDeps<T>) => {
|
|
40
|
+
handleIdle: () => void;
|
|
41
|
+
handleZoomStart: () => void;
|
|
42
|
+
handleZoomEnd: () => void;
|
|
43
|
+
handleCenterChanged: () => void;
|
|
44
|
+
handleDragStart: () => void;
|
|
45
|
+
handleDragEnd: () => void;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* 공간 인덱스 빌드 (빠른 Hit Test를 위한 자료구조)
|
|
49
|
+
*
|
|
50
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
51
|
+
* @param data 공간 인덱스에 삽입할 데이터 배열
|
|
52
|
+
* @param spatialIndex Spatial Hash Grid 인스턴스
|
|
53
|
+
* @param computeBoundingBox 바운딩 박스 계산 함수
|
|
54
|
+
*/
|
|
55
|
+
export declare const buildSpatialIndex: <T>(data: CanvasData<T>[], spatialIndex: SpatialHashGrid<CanvasData<T>>, computeBoundingBox: (item: CanvasData<T>) => BoundingBox | null) => void;
|
|
56
|
+
/**
|
|
57
|
+
* 선택 상태 동기화 (화면 밖 데이터도 선택 상태 유지)
|
|
58
|
+
*
|
|
59
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
60
|
+
* @param data 최신 데이터 배열
|
|
61
|
+
* @param selectedIds 선택된 항목 ID Set
|
|
62
|
+
* @param selectedItemsMap 현재 선택된 항목 Map
|
|
63
|
+
* @returns 업데이트된 선택된 항목 Map
|
|
64
|
+
*/
|
|
65
|
+
export declare const syncSelectedItems: <T>(data: CanvasData<T>[], selectedIds: Set<string>, selectedItemsMap: Map<string, CanvasData<T>>) => Map<string, CanvasData<T>>;
|
|
66
|
+
/**
|
|
67
|
+
* 외부 selectedItems를 내부 상태로 동기화
|
|
68
|
+
*
|
|
69
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
70
|
+
* @param externalSelectedItems 외부에서 전달된 선택된 항목 배열
|
|
71
|
+
* @param selectedIdsRef 선택된 ID Set ref
|
|
72
|
+
* @param selectedItemsMapRef 선택된 항목 Map ref
|
|
73
|
+
*/
|
|
74
|
+
export declare const syncExternalSelectedItems: <T>(externalSelectedItems: CanvasData<T>[] | undefined, selectedIdsRef: MutableRefObject<Set<string>>, selectedItemsMapRef: MutableRefObject<Map<string, CanvasData<T>>>) => void;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tslib = require('tslib');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 지도 이벤트 핸들러 생성 함수
|
|
9
|
+
*
|
|
10
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
11
|
+
* @param deps 이벤트 핸들러 생성에 필요한 의존성
|
|
12
|
+
* @returns 지도 이벤트 핸들러 객체
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
var createMapEventHandlers = function (deps) {
|
|
16
|
+
var controller = deps.controller,
|
|
17
|
+
containerRef = deps.containerRef,
|
|
18
|
+
markerRef = deps.markerRef,
|
|
19
|
+
options = deps.options,
|
|
20
|
+
prevCenterOffsetRef = deps.prevCenterOffsetRef,
|
|
21
|
+
accumTranslateRef = deps.accumTranslateRef,
|
|
22
|
+
offsetCacheRef = deps.offsetCacheRef,
|
|
23
|
+
boundingBoxCacheRef = deps.boundingBoxCacheRef,
|
|
24
|
+
renderAllImmediate = deps.renderAllImmediate; // 지도 이동/줌 완료 시 처리 (캐시 초기화 및 렌더링)
|
|
25
|
+
|
|
26
|
+
var handleIdle = function () {
|
|
27
|
+
prevCenterOffsetRef.current = null;
|
|
28
|
+
accumTranslateRef.current = {
|
|
29
|
+
x: 0,
|
|
30
|
+
y: 0
|
|
31
|
+
}; // 캐시 정리 (지도 이동/줌으로 좌표 변환 결과가 바뀜)
|
|
32
|
+
|
|
33
|
+
offsetCacheRef.current.clear();
|
|
34
|
+
boundingBoxCacheRef.current.clear(); // 마커 위치 업데이트
|
|
35
|
+
|
|
36
|
+
var bounds = controller.getCurrBounds();
|
|
37
|
+
|
|
38
|
+
var markerOptions = tslib.__assign({
|
|
39
|
+
position: bounds.nw
|
|
40
|
+
}, options);
|
|
41
|
+
|
|
42
|
+
markerRef.current && controller.updateMarker(markerRef.current, markerOptions); // transform 제거 전에 새 데이터로 즉시 렌더링 (transform 제거 시 잠깐 빈 화면이 보이는 것 방지)
|
|
43
|
+
|
|
44
|
+
if (containerRef.current) {
|
|
45
|
+
containerRef.current.style.transform = '';
|
|
46
|
+
containerRef.current.style.visibility = '';
|
|
47
|
+
} // 새 위치에서 렌더링 (캐시는 이미 초기화됨)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
renderAllImmediate();
|
|
51
|
+
}; // 줌 시작 시 처리 (일시적으로 숨김)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
var handleZoomStart = function () {
|
|
55
|
+
if (!containerRef.current) return;
|
|
56
|
+
containerRef.current.style.visibility = 'hidden';
|
|
57
|
+
}; // 줌 종료 시 처리 (다시 표시)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
var handleZoomEnd = function () {
|
|
61
|
+
if (!containerRef.current) return;
|
|
62
|
+
containerRef.current.style.visibility = '';
|
|
63
|
+
}; // 지도 중심 변경 시 처리 (transform으로 이동 추적, 캐시 유지)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
var handleCenterChanged = function () {
|
|
67
|
+
var center = controller.getCurrBounds().getCenter();
|
|
68
|
+
var curr = controller.positionToOffset(center);
|
|
69
|
+
var prev = prevCenterOffsetRef.current; // 첫 번째 호출 시 이전 위치 저장만 하고 종료
|
|
70
|
+
|
|
71
|
+
if (!prev) {
|
|
72
|
+
prevCenterOffsetRef.current = {
|
|
73
|
+
x: curr.x,
|
|
74
|
+
y: curr.y
|
|
75
|
+
};
|
|
76
|
+
return;
|
|
77
|
+
} // 이전 위치와 현재 위치의 차이 계산 (이동 거리)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
var dx = prev.x - curr.x;
|
|
81
|
+
var dy = prev.y - curr.y; // 누적 이동 거리 저장 (transform으로 화면만 이동, 캐시는 유지하여 성능 최적화)
|
|
82
|
+
|
|
83
|
+
accumTranslateRef.current = {
|
|
84
|
+
x: accumTranslateRef.current.x + dx,
|
|
85
|
+
y: accumTranslateRef.current.y + dy
|
|
86
|
+
};
|
|
87
|
+
prevCenterOffsetRef.current = {
|
|
88
|
+
x: curr.x,
|
|
89
|
+
y: curr.y
|
|
90
|
+
}; // CSS transform으로 컨테이너 이동 (캐시된 좌표는 그대로 유지)
|
|
91
|
+
|
|
92
|
+
if (containerRef.current) {
|
|
93
|
+
containerRef.current.style.transform = "translate(".concat(accumTranslateRef.current.x, "px, ").concat(accumTranslateRef.current.y, "px)");
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
var handleDragStart = function () {// 커서는 각 컴포넌트에서 처리
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
var handleDragEnd = function () {// 커서는 각 컴포넌트에서 처리
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
handleIdle: handleIdle,
|
|
105
|
+
handleZoomStart: handleZoomStart,
|
|
106
|
+
handleZoomEnd: handleZoomEnd,
|
|
107
|
+
handleCenterChanged: handleCenterChanged,
|
|
108
|
+
handleDragStart: handleDragStart,
|
|
109
|
+
handleDragEnd: handleDragEnd
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* 공간 인덱스 빌드 (빠른 Hit Test를 위한 자료구조)
|
|
114
|
+
*
|
|
115
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
116
|
+
* @param data 공간 인덱스에 삽입할 데이터 배열
|
|
117
|
+
* @param spatialIndex Spatial Hash Grid 인스턴스
|
|
118
|
+
* @param computeBoundingBox 바운딩 박스 계산 함수
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
var buildSpatialIndex = function (data, spatialIndex, computeBoundingBox) {
|
|
122
|
+
spatialIndex.clear();
|
|
123
|
+
|
|
124
|
+
for (var _i = 0, data_1 = data; _i < data_1.length; _i++) {
|
|
125
|
+
var item = data_1[_i];
|
|
126
|
+
var bbox = computeBoundingBox(item);
|
|
127
|
+
|
|
128
|
+
if (bbox) {
|
|
129
|
+
spatialIndex.insert(item, bbox.minX, bbox.minY, bbox.maxX, bbox.maxY);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* 선택 상태 동기화 (화면 밖 데이터도 선택 상태 유지)
|
|
135
|
+
*
|
|
136
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
137
|
+
* @param data 최신 데이터 배열
|
|
138
|
+
* @param selectedIds 선택된 항목 ID Set
|
|
139
|
+
* @param selectedItemsMap 현재 선택된 항목 Map
|
|
140
|
+
* @returns 업데이트된 선택된 항목 Map
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
var syncSelectedItems = function (data, selectedIds, selectedItemsMap) {
|
|
144
|
+
var dataMap = new Map(data.map(function (m) {
|
|
145
|
+
return [m.id, m];
|
|
146
|
+
}));
|
|
147
|
+
var newSelectedItemsMap = new Map();
|
|
148
|
+
selectedIds.forEach(function (id) {
|
|
149
|
+
// 현재 data에 있으면 최신 데이터 사용
|
|
150
|
+
var currentItem = dataMap.get(id);
|
|
151
|
+
|
|
152
|
+
if (currentItem) {
|
|
153
|
+
newSelectedItemsMap.set(id, currentItem);
|
|
154
|
+
} else {
|
|
155
|
+
// 화면 밖이면 기존 데이터 유지
|
|
156
|
+
var prevItem = selectedItemsMap.get(id);
|
|
157
|
+
|
|
158
|
+
if (prevItem) {
|
|
159
|
+
newSelectedItemsMap.set(id, prevItem);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
return newSelectedItemsMap;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* 외부 selectedItems를 내부 상태로 동기화
|
|
167
|
+
*
|
|
168
|
+
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
169
|
+
* @param externalSelectedItems 외부에서 전달된 선택된 항목 배열
|
|
170
|
+
* @param selectedIdsRef 선택된 ID Set ref
|
|
171
|
+
* @param selectedItemsMapRef 선택된 항목 Map ref
|
|
172
|
+
*/
|
|
173
|
+
|
|
174
|
+
var syncExternalSelectedItems = function (externalSelectedItems, selectedIdsRef, selectedItemsMapRef) {
|
|
175
|
+
if (externalSelectedItems === undefined) return;
|
|
176
|
+
var newSelectedIds = new Set();
|
|
177
|
+
var newSelectedItemsMap = new Map();
|
|
178
|
+
externalSelectedItems.forEach(function (item) {
|
|
179
|
+
newSelectedIds.add(item.id);
|
|
180
|
+
newSelectedItemsMap.set(item.id, item);
|
|
181
|
+
});
|
|
182
|
+
selectedIdsRef.current = newSelectedIds;
|
|
183
|
+
selectedItemsMapRef.current = newSelectedItemsMap;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
exports.buildSpatialIndex = buildSpatialIndex;
|
|
187
|
+
exports.createMapEventHandlers = createMapEventHandlers;
|
|
188
|
+
exports.syncExternalSelectedItems = syncExternalSelectedItems;
|
|
189
|
+
exports.syncSelectedItems = syncSelectedItems;
|