@mint-ui/map 1.2.0-test.5 → 1.2.0-test.51
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 +252 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/CanvasPolygonLayer.js +596 -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 +237 -0
- package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/renderer.js +645 -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 +3233 -2687
- package/dist/index.js +25 -10
- package/dist/index.umd.js +3247 -2689
- 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
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tslib = require('tslib');
|
|
6
|
+
var React = require('react');
|
|
7
|
+
var Konva = require('konva');
|
|
8
|
+
var MintMapProvider = require('../../provider/MintMapProvider.js');
|
|
9
|
+
var MapDrawables = require('../../../types/MapDrawables.js');
|
|
10
|
+
require('../../../types/MapTypes.js');
|
|
11
|
+
require('../../../types/MapEventTypes.js');
|
|
12
|
+
var reactDom = require('react-dom');
|
|
13
|
+
require('../shared/types.js');
|
|
14
|
+
var utils = require('../shared/utils.js');
|
|
15
|
+
var context = require('../shared/context.js');
|
|
16
|
+
var performance = require('../shared/performance.js');
|
|
17
|
+
var viewport = require('../shared/viewport.js');
|
|
18
|
+
var hooks = require('../shared/hooks.js');
|
|
19
|
+
var helpers = require('../shared/helpers.js');
|
|
20
|
+
var renderer = require('./renderer.js');
|
|
21
|
+
|
|
22
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
23
|
+
|
|
24
|
+
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
25
|
+
var Konva__default = /*#__PURE__*/_interopDefaultLegacy(Konva);
|
|
26
|
+
|
|
27
|
+
var CanvasPolygonLayer = function (props) {
|
|
28
|
+
var data = props.data,
|
|
29
|
+
onClick = props.onClick,
|
|
30
|
+
_a = props.enableMultiSelect,
|
|
31
|
+
enableMultiSelect = _a === void 0 ? false : _a,
|
|
32
|
+
_b = props.enableViewportCulling,
|
|
33
|
+
enableViewportCulling = _b === void 0 ? false : _b,
|
|
34
|
+
_c = props.cullingMargin,
|
|
35
|
+
cullingMargin = _c === void 0 ? performance.DEFAULT_CULLING_MARGIN : _c,
|
|
36
|
+
_d = props.maxCacheSize,
|
|
37
|
+
maxCacheSize = _d === void 0 ? performance.DEFAULT_MAX_CACHE_SIZE : _d,
|
|
38
|
+
externalSelectedItems = props.selectedItems,
|
|
39
|
+
externalSelectedItem = props.selectedItem,
|
|
40
|
+
_e = props.disableInteraction,
|
|
41
|
+
disableInteraction = _e === void 0 ? false : _e,
|
|
42
|
+
options = tslib.__rest(props, ["data", "onClick", "enableMultiSelect", "enableViewportCulling", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction"]); // 세 가지 방식 중 하나만 선택: customStyle > renderStyle > 개별 props
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
var isCustomStyleMode = 'customStyle' in props && props.customStyle !== undefined;
|
|
46
|
+
var isObjectMode = !isCustomStyleMode && 'renderStyle' in props && props.renderStyle !== undefined;
|
|
47
|
+
var isIndividualMode = !isCustomStyleMode && !isObjectMode; // 각 방식별 props 추출
|
|
48
|
+
|
|
49
|
+
var customStyleProps = isCustomStyleMode ? props : undefined;
|
|
50
|
+
var objectProps = isObjectMode ? props : undefined;
|
|
51
|
+
var individualProps = isIndividualMode ? props : undefined; // --------------------------------------------------------------------------
|
|
52
|
+
// Hooks & Context
|
|
53
|
+
// --------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
var controller = MintMapProvider.useMintMapController();
|
|
56
|
+
var context$1 = context.useCanvasContext();
|
|
57
|
+
var currentZIndex = options.zIndex !== undefined ? options.zIndex : 0; // DOM Refs
|
|
58
|
+
|
|
59
|
+
var divRef = React.useRef(document.createElement('div'));
|
|
60
|
+
var divElement = divRef.current;
|
|
61
|
+
var containerRef = React.useRef(null);
|
|
62
|
+
var markerRef = React.useRef(); // Konva Refs
|
|
63
|
+
|
|
64
|
+
var stageRef = React.useRef(null);
|
|
65
|
+
var baseLayerRef = React.useRef(null);
|
|
66
|
+
var eventLayerRef = React.useRef(null); // 상태 관리 Refs (React 리렌더링 최소화)
|
|
67
|
+
|
|
68
|
+
var dataRef = React.useRef(data);
|
|
69
|
+
var disableInteractionRef = React.useRef(disableInteraction);
|
|
70
|
+
var enableViewportCullingRef = React.useRef(enableViewportCulling);
|
|
71
|
+
var hoveredItemRef = React.useRef(null);
|
|
72
|
+
var selectedItemRef = React.useRef(externalSelectedItem);
|
|
73
|
+
var selectedIdsRef = React.useRef(new Set());
|
|
74
|
+
var selectedItemsMapRef = React.useRef(new Map()); // 드래그 상태 Refs
|
|
75
|
+
|
|
76
|
+
var draggingRef = React.useRef(false);
|
|
77
|
+
var prevCenterOffsetRef = React.useRef(null);
|
|
78
|
+
var accumTranslateRef = React.useRef({
|
|
79
|
+
x: 0,
|
|
80
|
+
y: 0
|
|
81
|
+
}); // 드래그 시작 시점의 hover 상태 저장 (드래그 중 hover 고정용)
|
|
82
|
+
|
|
83
|
+
var dragStartHoveredItemRef = React.useRef(null); // 성능 최적화 Refs
|
|
84
|
+
|
|
85
|
+
var offsetCacheRef = React.useRef(new performance.LRUCache(maxCacheSize));
|
|
86
|
+
var spatialIndexRef = React.useRef(new performance.SpatialHashGrid(performance.SPATIAL_GRID_CELL_SIZE));
|
|
87
|
+
var boundingBoxCacheRef = React.useRef(new Map());
|
|
88
|
+
var viewportRef = React.useRef(null); // 뷰포트 영역 계산 (Viewport Culling용)
|
|
89
|
+
|
|
90
|
+
var updateViewport = function () {
|
|
91
|
+
viewport.updateViewport(stageRef.current, cullingMargin, viewportRef);
|
|
92
|
+
}; // 뷰포트 내부 여부 확인 (바운딩 박스 캐싱)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
var isInViewport = function (item) {
|
|
96
|
+
return viewport.isInViewport(item, viewportRef, boundingBoxCacheRef, computeBoundingBox);
|
|
97
|
+
}; // 폴리곤 좌표 변환 (위경도 → 화면 좌표, LRU 캐시 사용)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
var getOrComputePolygonOffsets = function (polygonData) {
|
|
101
|
+
var cached = offsetCacheRef.current.get(polygonData.id);
|
|
102
|
+
if (cached && Array.isArray(cached)) return cached;
|
|
103
|
+
var result = utils.computePolygonOffsets(polygonData, controller);
|
|
104
|
+
if (!result) return null;
|
|
105
|
+
offsetCacheRef.current.set(polygonData.id, result);
|
|
106
|
+
return result;
|
|
107
|
+
}; // 폴리곤 바운딩 박스 계산 (Viewport Culling 및 Hit Test용)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
var computeBoundingBox = function (item) {
|
|
111
|
+
var offsets = getOrComputePolygonOffsets(item);
|
|
112
|
+
if (!offsets) return null; // 모든 좌표를 순회하며 최소/최대값 찾기
|
|
113
|
+
|
|
114
|
+
var minX = Infinity,
|
|
115
|
+
minY = Infinity,
|
|
116
|
+
maxX = -Infinity,
|
|
117
|
+
maxY = -Infinity;
|
|
118
|
+
|
|
119
|
+
for (var _i = 0, offsets_1 = offsets; _i < offsets_1.length; _i++) {
|
|
120
|
+
var multiPolygon = offsets_1[_i];
|
|
121
|
+
|
|
122
|
+
for (var _a = 0, multiPolygon_1 = multiPolygon; _a < multiPolygon_1.length; _a++) {
|
|
123
|
+
var polygonGroup = multiPolygon_1[_a];
|
|
124
|
+
|
|
125
|
+
for (var _b = 0, polygonGroup_1 = polygonGroup; _b < polygonGroup_1.length; _b++) {
|
|
126
|
+
var _c = polygonGroup_1[_b],
|
|
127
|
+
x = _c[0],
|
|
128
|
+
y = _c[1];
|
|
129
|
+
if (x < minX) minX = x;
|
|
130
|
+
if (y < minY) minY = y;
|
|
131
|
+
if (x > maxX) maxX = x;
|
|
132
|
+
if (y > maxY) maxY = y;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
minX: minX,
|
|
139
|
+
minY: minY,
|
|
140
|
+
maxX: maxX,
|
|
141
|
+
maxY: maxY
|
|
142
|
+
};
|
|
143
|
+
}; // 공간 인덱스 빌드 (빠른 Hit Test용)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
var buildSpatialIndex = function () {
|
|
147
|
+
hooks.buildSpatialIndex(dataRef.current, spatialIndexRef.current, computeBoundingBox);
|
|
148
|
+
}; // 렌더링 유틸리티 객체
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
var renderUtils = {
|
|
152
|
+
getOrComputePolygonOffsets: getOrComputePolygonOffsets,
|
|
153
|
+
getOrComputeMarkerOffset: function () {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}; // 렌더링 함수 생성 (스타일 지정 방식에 따라 분기)
|
|
157
|
+
|
|
158
|
+
var renderBase = isCustomStyleMode && customStyleProps ? renderer.renderPolygonBaseWithCustomStyle(customStyleProps.customStyle) : isObjectMode && objectProps ? renderer.renderPolygonBaseWithObject(objectProps.renderStyle) : isIndividualMode && individualProps ? renderer.renderPolygonBase(individualProps.baseFillColor, individualProps.baseStrokeColor, individualProps.baseLineWidth) : function () {
|
|
159
|
+
throw new Error('Invalid props: one of customStyle, renderStyle, or individual style props must be provided');
|
|
160
|
+
}();
|
|
161
|
+
var renderEvent = isCustomStyleMode && customStyleProps ? renderer.renderPolygonEventWithCustomStyle(customStyleProps.customStyle) : isObjectMode && objectProps ? renderer.renderPolygonEventWithObject(objectProps.renderStyle) : isIndividualMode && individualProps ? renderer.renderPolygonEvent(individualProps.baseFillColor, individualProps.baseStrokeColor, individualProps.baseLineWidth, individualProps.selectedFillColor, individualProps.selectedStrokeColor, individualProps.selectedLineWidth, individualProps.activeFillColor, individualProps.activeStrokeColor, individualProps.activeLineWidth, individualProps.hoveredFillColor, individualProps.hoveredStrokeColor, individualProps.hoveredLineWidth) : function () {
|
|
162
|
+
throw new Error('Invalid props: one of customStyle, renderStyle, or individual style props must be provided');
|
|
163
|
+
}(); // Base Layer 렌더링 (뷰포트 컬링 적용)
|
|
164
|
+
|
|
165
|
+
var doRenderBase = function () {
|
|
166
|
+
var layer = baseLayerRef.current;
|
|
167
|
+
if (!layer) return;
|
|
168
|
+
var shape = layer.findOne('.base-render-shape');
|
|
169
|
+
|
|
170
|
+
if (!shape) {
|
|
171
|
+
shape = new Konva__default["default"].Shape({
|
|
172
|
+
name: 'base-render-shape',
|
|
173
|
+
sceneFunc: function (context, shape) {
|
|
174
|
+
var ctx = context;
|
|
175
|
+
var hovered = hoveredItemRef.current; // 뷰포트 컬링: 화면에 보이는 항목만 필터링
|
|
176
|
+
|
|
177
|
+
var visibleItems = enableViewportCullingRef.current ? dataRef.current.filter(function (item) {
|
|
178
|
+
return isInViewport(item);
|
|
179
|
+
}) : dataRef.current;
|
|
180
|
+
renderBase({
|
|
181
|
+
ctx: ctx,
|
|
182
|
+
items: visibleItems,
|
|
183
|
+
selectedIds: selectedIdsRef.current,
|
|
184
|
+
hoveredItem: hovered,
|
|
185
|
+
utils: renderUtils
|
|
186
|
+
});
|
|
187
|
+
},
|
|
188
|
+
perfectDrawEnabled: false,
|
|
189
|
+
listening: false,
|
|
190
|
+
hitStrokeWidth: 0
|
|
191
|
+
});
|
|
192
|
+
layer.add(shape);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
layer.batchDraw();
|
|
196
|
+
}; // Event Layer 렌더링 (hover 효과 및 선택 상태 표시)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
var doRenderEvent = function () {
|
|
200
|
+
var layer = eventLayerRef.current;
|
|
201
|
+
if (!layer) return;
|
|
202
|
+
var shape = layer.findOne('.event-render-shape');
|
|
203
|
+
|
|
204
|
+
if (!shape) {
|
|
205
|
+
shape = new Konva__default["default"].Shape({
|
|
206
|
+
name: 'event-render-shape',
|
|
207
|
+
sceneFunc: function (context, shape) {
|
|
208
|
+
var ctx = context;
|
|
209
|
+
var selectedItems = helpers.mapValuesToArray(selectedItemsMapRef.current);
|
|
210
|
+
var hovered = hoveredItemRef.current;
|
|
211
|
+
renderEvent({
|
|
212
|
+
ctx: ctx,
|
|
213
|
+
hoveredItem: hovered,
|
|
214
|
+
utils: renderUtils,
|
|
215
|
+
selectedItems: selectedItems,
|
|
216
|
+
selectedItem: selectedItemRef.current
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
perfectDrawEnabled: false,
|
|
220
|
+
listening: false,
|
|
221
|
+
hitStrokeWidth: 0
|
|
222
|
+
});
|
|
223
|
+
layer.add(shape);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
layer.batchDraw();
|
|
227
|
+
}; // 전체 즉시 렌더링
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
var renderAllImmediate = function () {
|
|
231
|
+
if (enableViewportCullingRef.current) {
|
|
232
|
+
updateViewport();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
buildSpatialIndex();
|
|
236
|
+
doRenderBase();
|
|
237
|
+
doRenderEvent();
|
|
238
|
+
}; // 지도 이벤트 핸들러 생성
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
var _f = hooks.createMapEventHandlers({
|
|
242
|
+
controller: controller,
|
|
243
|
+
containerRef: containerRef,
|
|
244
|
+
markerRef: markerRef,
|
|
245
|
+
options: options,
|
|
246
|
+
prevCenterOffsetRef: prevCenterOffsetRef,
|
|
247
|
+
accumTranslateRef: accumTranslateRef,
|
|
248
|
+
offsetCacheRef: offsetCacheRef,
|
|
249
|
+
boundingBoxCacheRef: boundingBoxCacheRef,
|
|
250
|
+
renderAllImmediate: renderAllImmediate
|
|
251
|
+
}),
|
|
252
|
+
handleIdle = _f.handleIdle,
|
|
253
|
+
handleZoomStart = _f.handleZoomStart,
|
|
254
|
+
handleZoomEnd = _f.handleZoomEnd,
|
|
255
|
+
handleCenterChanged = _f.handleCenterChanged,
|
|
256
|
+
handleDragStartShared = _f.handleDragStart,
|
|
257
|
+
handleDragEndShared = _f.handleDragEnd;
|
|
258
|
+
|
|
259
|
+
var handleDragStart = function () {
|
|
260
|
+
handleDragStartShared(); // 드래그 시작 시점의 hover 상태 저장
|
|
261
|
+
|
|
262
|
+
dragStartHoveredItemRef.current = hoveredItemRef.current;
|
|
263
|
+
draggingRef.current = true;
|
|
264
|
+
controller.setMapCursor('grabbing');
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
var handleDragEnd = function () {
|
|
268
|
+
handleDragEndShared();
|
|
269
|
+
draggingRef.current = false; // 드래그 종료 후 hover 상태 초기화 (다음 MOUSEMOVE에서 업데이트됨)
|
|
270
|
+
|
|
271
|
+
dragStartHoveredItemRef.current = null;
|
|
272
|
+
controller.setMapCursor('grab');
|
|
273
|
+
}; // Hit Test: 특정 좌표의 폴리곤 찾기
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
var findData = function (offset) {
|
|
277
|
+
// 공간 인덱스에서 후보 항목 조회 (O(1) 수준의 빠른 조회)
|
|
278
|
+
var candidates = spatialIndexRef.current.queryPoint(offset.x, offset.y); // 역순 순회: 나중에 추가된 항목(최상위)이 먼저 선택되도록
|
|
279
|
+
|
|
280
|
+
for (var i = candidates.length - 1; i >= 0; i--) {
|
|
281
|
+
var item = candidates[i]; // 정확한 Hit Test: Ray Casting 알고리즘으로 폴리곤 내부 여부 확인
|
|
282
|
+
|
|
283
|
+
if (utils.isPointInPolygonData(offset, item, getOrComputePolygonOffsets)) {
|
|
284
|
+
return item;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return null;
|
|
289
|
+
}; // Hover 상태 설정 및 렌더링
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
var setHovered = function (data) {
|
|
293
|
+
// 드래그 중에는 hover 상태 변경을 무시하고 드래그 시작 시점의 상태 유지
|
|
294
|
+
if (draggingRef.current) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
hoveredItemRef.current = data;
|
|
299
|
+
|
|
300
|
+
if (draggingRef.current) {
|
|
301
|
+
controller.setMapCursor('grabbing');
|
|
302
|
+
} else {
|
|
303
|
+
controller.setMapCursor(data ? 'pointer' : 'grab');
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
doRenderEvent();
|
|
307
|
+
}; // 클릭 처리: 선택 상태 업데이트
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
var handleLocalClick = function (data) {
|
|
311
|
+
if (enableMultiSelect) {
|
|
312
|
+
var newSelected = new Set(selectedIdsRef.current);
|
|
313
|
+
|
|
314
|
+
if (newSelected.has(data.id)) {
|
|
315
|
+
newSelected.delete(data.id);
|
|
316
|
+
selectedItemsMapRef.current.delete(data.id);
|
|
317
|
+
} else {
|
|
318
|
+
newSelected.add(data.id);
|
|
319
|
+
selectedItemsMapRef.current.set(data.id, data);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
selectedIdsRef.current = newSelected;
|
|
323
|
+
} else {
|
|
324
|
+
var newSelected = new Set();
|
|
325
|
+
|
|
326
|
+
if (!selectedIdsRef.current.has(data.id)) {
|
|
327
|
+
newSelected.add(data.id);
|
|
328
|
+
selectedItemsMapRef.current.clear();
|
|
329
|
+
selectedItemsMapRef.current.set(data.id, data);
|
|
330
|
+
} else {
|
|
331
|
+
selectedItemsMapRef.current.clear();
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
selectedIdsRef.current = newSelected;
|
|
335
|
+
} // Event Layer 업데이트 (선택된 항목 표시)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
doRenderEvent();
|
|
339
|
+
}; // 클릭 이벤트 핸들러
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
var handleClick = function (event) {
|
|
343
|
+
if (controller.isMapDragged()) return;
|
|
344
|
+
if (disableInteractionRef.current) return;
|
|
345
|
+
var clickedOffset = helpers.validateEvent(event, context$1, controller);
|
|
346
|
+
if (!clickedOffset) return;
|
|
347
|
+
var data = findData(clickedOffset);
|
|
348
|
+
if (!data) return;
|
|
349
|
+
handleLocalClick(data);
|
|
350
|
+
onClick === null || onClick === void 0 ? void 0 : onClick(data, selectedIdsRef.current);
|
|
351
|
+
}; // 마우스 이동 이벤트 핸들러 (hover 감지)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
var handleMouseMove = function (event) {
|
|
355
|
+
if (disableInteractionRef.current) return; // 드래그 중에는 hover 상태를 업데이트하지 않음 (드래그 시작 시점의 hover 상태 유지)
|
|
356
|
+
|
|
357
|
+
if (draggingRef.current) return;
|
|
358
|
+
var mouseOffset = helpers.validateEvent(event, context$1, controller);
|
|
359
|
+
if (!mouseOffset) return;
|
|
360
|
+
var hoveredItem = findData(mouseOffset);
|
|
361
|
+
var prevHovered = hoveredItemRef.current;
|
|
362
|
+
if (prevHovered === hoveredItem) return;
|
|
363
|
+
setHovered(hoveredItem);
|
|
364
|
+
}; // 마우스가 맵 영역을 벗어날 때 hover 상태 초기화
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
var handleMouseLeave = function () {
|
|
368
|
+
if (disableInteractionRef.current) return;
|
|
369
|
+
var prevHovered = hoveredItemRef.current;
|
|
370
|
+
if (!prevHovered) return;
|
|
371
|
+
hoveredItemRef.current = null;
|
|
372
|
+
controller.setMapCursor('grab');
|
|
373
|
+
doRenderEvent();
|
|
374
|
+
}; // DOM 초기화
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
React.useEffect(function () {
|
|
378
|
+
divElement.style.width = 'fit-content';
|
|
379
|
+
return function () {
|
|
380
|
+
if (!markerRef.current) return;
|
|
381
|
+
controller.clearDrawable(markerRef.current);
|
|
382
|
+
markerRef.current = undefined;
|
|
383
|
+
};
|
|
384
|
+
}, []); // 마커 생성/업데이트
|
|
385
|
+
|
|
386
|
+
React.useEffect(function () {
|
|
387
|
+
if (!options) return;
|
|
388
|
+
var bounds = controller.getCurrBounds();
|
|
389
|
+
|
|
390
|
+
var markerOptions = tslib.__assign({
|
|
391
|
+
position: bounds.nw
|
|
392
|
+
}, options);
|
|
393
|
+
|
|
394
|
+
if (markerRef.current) {
|
|
395
|
+
controller.updateMarker(markerRef.current, markerOptions);
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
markerRef.current = new MapDrawables.Marker(markerOptions);
|
|
400
|
+
markerRef.current.element = divElement;
|
|
401
|
+
controller.createMarker(markerRef.current);
|
|
402
|
+
|
|
403
|
+
if (divElement.parentElement) {
|
|
404
|
+
divElement.parentElement.style.pointerEvents = 'none';
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (options.zIndex !== undefined) {
|
|
408
|
+
controller.setMarkerZIndex(markerRef.current, options.zIndex);
|
|
409
|
+
}
|
|
410
|
+
}, [options]); // Konva 초기화 및 이벤트 리스너 등록
|
|
411
|
+
|
|
412
|
+
React.useEffect(function () {
|
|
413
|
+
var mapDiv = controller.mapDivElement;
|
|
414
|
+
var stage = new Konva__default["default"].Stage({
|
|
415
|
+
container: containerRef.current,
|
|
416
|
+
width: mapDiv.offsetWidth,
|
|
417
|
+
height: mapDiv.offsetHeight
|
|
418
|
+
});
|
|
419
|
+
stageRef.current = stage;
|
|
420
|
+
var baseLayer = new Konva__default["default"].Layer({
|
|
421
|
+
listening: false
|
|
422
|
+
});
|
|
423
|
+
var eventLayer = new Konva__default["default"].Layer({
|
|
424
|
+
listening: false
|
|
425
|
+
});
|
|
426
|
+
baseLayerRef.current = baseLayer;
|
|
427
|
+
eventLayerRef.current = eventLayer;
|
|
428
|
+
stage.add(baseLayer);
|
|
429
|
+
stage.add(eventLayer);
|
|
430
|
+
|
|
431
|
+
if (enableViewportCulling) {
|
|
432
|
+
updateViewport();
|
|
433
|
+
} // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
var resizeRafId = null;
|
|
437
|
+
var resizeObserver = new ResizeObserver(function () {
|
|
438
|
+
if (resizeRafId !== null) {
|
|
439
|
+
cancelAnimationFrame(resizeRafId);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
resizeRafId = requestAnimationFrame(function () {
|
|
443
|
+
stage.width(mapDiv.offsetWidth);
|
|
444
|
+
stage.height(mapDiv.offsetHeight);
|
|
445
|
+
offsetCacheRef.current.clear();
|
|
446
|
+
boundingBoxCacheRef.current.clear();
|
|
447
|
+
|
|
448
|
+
if (enableViewportCullingRef.current) {
|
|
449
|
+
updateViewport();
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
renderAllImmediate();
|
|
453
|
+
resizeRafId = null;
|
|
454
|
+
});
|
|
455
|
+
});
|
|
456
|
+
resizeObserver.observe(mapDiv);
|
|
457
|
+
controller.addEventListener('IDLE', handleIdle);
|
|
458
|
+
controller.addEventListener('ZOOMSTART', handleZoomStart);
|
|
459
|
+
controller.addEventListener('ZOOM_CHANGED', handleZoomEnd);
|
|
460
|
+
controller.addEventListener('CENTER_CHANGED', handleCenterChanged);
|
|
461
|
+
controller.addEventListener('CLICK', handleClick);
|
|
462
|
+
controller.addEventListener('MOUSEMOVE', handleMouseMove);
|
|
463
|
+
controller.addEventListener('DRAGSTART', handleDragStart);
|
|
464
|
+
controller.addEventListener('DRAGEND', handleDragEnd);
|
|
465
|
+
mapDiv.addEventListener('mouseleave', handleMouseLeave);
|
|
466
|
+
renderAllImmediate(); // Context 사용 시 컴포넌트 등록
|
|
467
|
+
|
|
468
|
+
var componentInstance = null;
|
|
469
|
+
|
|
470
|
+
if (context$1) {
|
|
471
|
+
componentInstance = {
|
|
472
|
+
zIndex: currentZIndex,
|
|
473
|
+
hitTest: function (offset) {
|
|
474
|
+
return findData(offset) !== null;
|
|
475
|
+
},
|
|
476
|
+
onClick: onClick,
|
|
477
|
+
findData: findData,
|
|
478
|
+
setHovered: setHovered,
|
|
479
|
+
handleLocalClick: handleLocalClick,
|
|
480
|
+
getSelectedIds: function () {
|
|
481
|
+
return selectedIdsRef.current;
|
|
482
|
+
},
|
|
483
|
+
isInteractionDisabled: function () {
|
|
484
|
+
return disableInteractionRef.current;
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
context$1.registerComponent(componentInstance);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return function () {
|
|
491
|
+
if (resizeRafId !== null) {
|
|
492
|
+
cancelAnimationFrame(resizeRafId);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
resizeObserver.disconnect();
|
|
496
|
+
controller.removeEventListener('IDLE', handleIdle);
|
|
497
|
+
controller.removeEventListener('ZOOMSTART', handleZoomStart);
|
|
498
|
+
controller.removeEventListener('ZOOM_CHANGED', handleZoomEnd);
|
|
499
|
+
controller.removeEventListener('CENTER_CHANGED', handleCenterChanged);
|
|
500
|
+
controller.removeEventListener('CLICK', handleClick);
|
|
501
|
+
controller.removeEventListener('MOUSEMOVE', handleMouseMove);
|
|
502
|
+
controller.removeEventListener('DRAGSTART', handleDragStart);
|
|
503
|
+
controller.removeEventListener('DRAGEND', handleDragEnd);
|
|
504
|
+
mapDiv.removeEventListener('mouseleave', handleMouseLeave);
|
|
505
|
+
|
|
506
|
+
if (context$1 && componentInstance) {
|
|
507
|
+
context$1.unregisterComponent(componentInstance);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
baseLayer.destroyChildren();
|
|
511
|
+
eventLayer.destroyChildren();
|
|
512
|
+
stage.destroy();
|
|
513
|
+
offsetCacheRef.current.clear();
|
|
514
|
+
boundingBoxCacheRef.current.clear();
|
|
515
|
+
spatialIndexRef.current.clear();
|
|
516
|
+
};
|
|
517
|
+
}, []); // disableInteraction 동기화
|
|
518
|
+
|
|
519
|
+
React.useEffect(function () {
|
|
520
|
+
disableInteractionRef.current = disableInteraction;
|
|
521
|
+
}, [disableInteraction]); // enableViewportCulling 동기화
|
|
522
|
+
|
|
523
|
+
React.useEffect(function () {
|
|
524
|
+
enableViewportCullingRef.current = enableViewportCulling;
|
|
525
|
+
|
|
526
|
+
if (stageRef.current) {
|
|
527
|
+
// 뷰포트 컬링 설정이 변경되면 shape 재생성 필요
|
|
528
|
+
var baseLayer = baseLayerRef.current;
|
|
529
|
+
|
|
530
|
+
if (baseLayer) {
|
|
531
|
+
var shape = baseLayer.findOne('.base-render-shape');
|
|
532
|
+
|
|
533
|
+
if (shape) {
|
|
534
|
+
shape.destroy();
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
var eventLayer = eventLayerRef.current;
|
|
539
|
+
|
|
540
|
+
if (eventLayer) {
|
|
541
|
+
var shape = eventLayer.findOne('.event-render-shape');
|
|
542
|
+
|
|
543
|
+
if (shape) {
|
|
544
|
+
shape.destroy();
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
renderAllImmediate();
|
|
549
|
+
}
|
|
550
|
+
}, [enableViewportCulling]); // 외부 selectedItems 동기화
|
|
551
|
+
|
|
552
|
+
React.useEffect(function () {
|
|
553
|
+
if (!stageRef.current) return;
|
|
554
|
+
hooks.syncExternalSelectedItems(externalSelectedItems, selectedIdsRef, selectedItemsMapRef);
|
|
555
|
+
doRenderBase();
|
|
556
|
+
doRenderEvent();
|
|
557
|
+
}, [externalSelectedItems]); // 외부 selectedItem 변경 시 Event Layer 리렌더링
|
|
558
|
+
|
|
559
|
+
React.useEffect(function () {
|
|
560
|
+
if (!stageRef.current) return;
|
|
561
|
+
selectedItemRef.current = externalSelectedItem;
|
|
562
|
+
doRenderEvent();
|
|
563
|
+
}, [externalSelectedItem]); // 데이터 변경 시 렌더링 (캐시 정리 및 선택 상태 동기화)
|
|
564
|
+
|
|
565
|
+
React.useEffect(function () {
|
|
566
|
+
if (!stageRef.current) return;
|
|
567
|
+
dataRef.current = data;
|
|
568
|
+
|
|
569
|
+
if (containerRef.current) {
|
|
570
|
+
containerRef.current.style.transform = '';
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
prevCenterOffsetRef.current = null;
|
|
574
|
+
accumTranslateRef.current = {
|
|
575
|
+
x: 0,
|
|
576
|
+
y: 0
|
|
577
|
+
};
|
|
578
|
+
offsetCacheRef.current.clear();
|
|
579
|
+
boundingBoxCacheRef.current.clear();
|
|
580
|
+
selectedItemsMapRef.current = hooks.syncSelectedItems(data, selectedIdsRef.current, selectedItemsMapRef.current);
|
|
581
|
+
renderAllImmediate();
|
|
582
|
+
}, [data]);
|
|
583
|
+
return reactDom.createPortal(React__default["default"].createElement("div", {
|
|
584
|
+
ref: containerRef,
|
|
585
|
+
style: {
|
|
586
|
+
position: 'absolute',
|
|
587
|
+
width: '100%',
|
|
588
|
+
height: '100%'
|
|
589
|
+
}
|
|
590
|
+
}), divElement);
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
exports.CanvasProvider = context.CanvasProvider;
|
|
594
|
+
exports.LRUCache = performance.LRUCache;
|
|
595
|
+
exports.SpatialHashGrid = performance.SpatialHashGrid;
|
|
596
|
+
exports["default"] = CanvasPolygonLayer;
|