@mint-ui/map 1.2.0-test.16 → 1.2.0-test.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/mint-map/core/advanced/woongCanvas/WoongCanvasLayer.d.ts +7 -7
- package/dist/components/mint-map/core/advanced/woongCanvas/WoongCanvasLayer.js +117 -226
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/renderer.d.ts +13 -11
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/renderer.js +29 -21
- package/dist/components/mint-map/google/GoogleMintMapController.js +1 -1
- package/dist/components/mint-map/kakao/KakaoMintMapController.js +1 -1
- package/dist/components/mint-map/naver/NaverMintMapController.js +1 -1
- package/dist/index.es.js +146 -247
- package/dist/index.umd.js +146 -247
- package/package.json +1 -1
package/dist/index.umd.js
CHANGED
|
@@ -5539,9 +5539,12 @@
|
|
|
5539
5539
|
/**
|
|
5540
5540
|
* 폴리곤 Event 렌더링 함수
|
|
5541
5541
|
*
|
|
5542
|
-
* @param
|
|
5543
|
-
* @param
|
|
5544
|
-
* @param
|
|
5542
|
+
* @param baseFillColor 기본 폴리곤 채우기 색상 (필수, fallback용)
|
|
5543
|
+
* @param baseStrokeColor 기본 폴리곤 테두리 색상 (필수, fallback용)
|
|
5544
|
+
* @param baseLineWidth 기본 폴리곤 테두리 두께 (필수, fallback용)
|
|
5545
|
+
* @param selectedFillColor 선택된 폴리곤 채우기 색상 (선택, 기본값: baseFillColor)
|
|
5546
|
+
* @param selectedStrokeColor 선택된 폴리곤 테두리 색상 (선택, 기본값: baseStrokeColor)
|
|
5547
|
+
* @param selectedLineWidth 선택된 폴리곤 테두리 두께 (선택, 기본값: baseLineWidth)
|
|
5545
5548
|
* @param activeFillColor 마지막 선택된 폴리곤 채우기 색상 (선택, 기본값: selectedFillColor)
|
|
5546
5549
|
* @param activeStrokeColor 마지막 선택된 폴리곤 테두리 색상 (선택, 기본값: selectedStrokeColor)
|
|
5547
5550
|
* @param activeLineWidth 마지막 선택된 폴리곤 테두리 두께 (선택, 기본값: selectedLineWidth)
|
|
@@ -5552,29 +5555,34 @@
|
|
|
5552
5555
|
*
|
|
5553
5556
|
* @example
|
|
5554
5557
|
* const renderEvent = renderPolygonEvent(
|
|
5555
|
-
* 'rgba(255,
|
|
5556
|
-
* 'rgba(
|
|
5557
|
-
*
|
|
5558
|
-
* 'rgba(255,
|
|
5559
|
-
*
|
|
5560
|
-
*
|
|
5561
|
-
* 'rgba(100, 150, 255, 0.8)'
|
|
5558
|
+
* 'rgba(255, 100, 100, 0.5)', // baseFillColor
|
|
5559
|
+
* 'rgba(200, 50, 50, 0.8)', // baseStrokeColor
|
|
5560
|
+
* 2, // baseLineWidth
|
|
5561
|
+
* 'rgba(255, 193, 7, 0.7)', // selectedFillColor
|
|
5562
|
+
* 'rgba(255, 152, 0, 1)', // selectedStrokeColor
|
|
5563
|
+
* 4 // selectedLineWidth
|
|
5562
5564
|
* );
|
|
5563
5565
|
*/
|
|
5564
5566
|
|
|
5565
|
-
var renderPolygonEvent = function (selectedFillColor, selectedStrokeColor, selectedLineWidth, activeFillColor, activeStrokeColor, activeLineWidth, hoveredFillColor, hoveredStrokeColor, hoveredLineWidth) {
|
|
5566
|
-
// 기본값 설정 (
|
|
5567
|
-
var
|
|
5567
|
+
var renderPolygonEvent = function (baseFillColor, baseStrokeColor, baseLineWidth, selectedFillColor, selectedStrokeColor, selectedLineWidth, activeFillColor, activeStrokeColor, activeLineWidth, hoveredFillColor, hoveredStrokeColor, hoveredLineWidth) {
|
|
5568
|
+
// 기본값 설정 (base 기준)
|
|
5569
|
+
var _selectedFillColor = selectedFillColor || baseFillColor;
|
|
5568
5570
|
|
|
5569
|
-
var
|
|
5571
|
+
var _selectedStrokeColor = selectedStrokeColor || baseStrokeColor;
|
|
5570
5572
|
|
|
5571
|
-
var
|
|
5573
|
+
var _selectedLineWidth = selectedLineWidth || baseLineWidth;
|
|
5572
5574
|
|
|
5573
|
-
var
|
|
5575
|
+
var _activeFillColor = activeFillColor || _selectedFillColor;
|
|
5574
5576
|
|
|
5575
|
-
var
|
|
5577
|
+
var _activeStrokeColor = activeStrokeColor || _selectedStrokeColor;
|
|
5576
5578
|
|
|
5577
|
-
var
|
|
5579
|
+
var _activeLineWidth = activeLineWidth || _selectedLineWidth;
|
|
5580
|
+
|
|
5581
|
+
var _hoveredFillColor = hoveredFillColor || _selectedFillColor;
|
|
5582
|
+
|
|
5583
|
+
var _hoveredStrokeColor = hoveredStrokeColor || _selectedStrokeColor;
|
|
5584
|
+
|
|
5585
|
+
var _hoveredLineWidth = hoveredLineWidth || _selectedLineWidth;
|
|
5578
5586
|
|
|
5579
5587
|
return function (_a) {
|
|
5580
5588
|
var ctx = _a.ctx,
|
|
@@ -5595,9 +5603,9 @@
|
|
|
5595
5603
|
ctx: ctx,
|
|
5596
5604
|
polygonOffsets: polygonOffsets,
|
|
5597
5605
|
isDonutPolygon: item.isDonutPolygon || false,
|
|
5598
|
-
fillColor:
|
|
5599
|
-
strokeColor:
|
|
5600
|
-
lineWidth:
|
|
5606
|
+
fillColor: _selectedFillColor,
|
|
5607
|
+
strokeColor: _selectedStrokeColor,
|
|
5608
|
+
lineWidth: _selectedLineWidth
|
|
5601
5609
|
});
|
|
5602
5610
|
}
|
|
5603
5611
|
} // 2. 마지막 선택된 항목 그리기 (호버되지 않은 경우)
|
|
@@ -5640,7 +5648,7 @@
|
|
|
5640
5648
|
// 메인 컴포넌트
|
|
5641
5649
|
// ============================================================================
|
|
5642
5650
|
|
|
5643
|
-
var
|
|
5651
|
+
var WoongCanvasLayer = function (props) {
|
|
5644
5652
|
var data = props.data,
|
|
5645
5653
|
dataType = props.dataType,
|
|
5646
5654
|
onClick = props.onClick,
|
|
@@ -5782,55 +5790,11 @@
|
|
|
5782
5790
|
var bbox = boundingBoxCacheRef.current.get(item.id);
|
|
5783
5791
|
|
|
5784
5792
|
if (!bbox) {
|
|
5785
|
-
//
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
var minX = Infinity,
|
|
5791
|
-
minY = Infinity,
|
|
5792
|
-
maxX = -Infinity,
|
|
5793
|
-
maxY = -Infinity;
|
|
5794
|
-
|
|
5795
|
-
for (var _i = 0, offsets_1 = offsets; _i < offsets_1.length; _i++) {
|
|
5796
|
-
var multiPolygon = offsets_1[_i];
|
|
5797
|
-
|
|
5798
|
-
for (var _a = 0, multiPolygon_1 = multiPolygon; _a < multiPolygon_1.length; _a++) {
|
|
5799
|
-
var polygonGroup = multiPolygon_1[_a];
|
|
5800
|
-
|
|
5801
|
-
for (var _b = 0, polygonGroup_1 = polygonGroup; _b < polygonGroup_1.length; _b++) {
|
|
5802
|
-
var _c = polygonGroup_1[_b],
|
|
5803
|
-
x = _c[0],
|
|
5804
|
-
y = _c[1];
|
|
5805
|
-
if (x < minX) minX = x;
|
|
5806
|
-
if (y < minY) minY = y;
|
|
5807
|
-
if (x > maxX) maxX = x;
|
|
5808
|
-
if (y > maxY) maxY = y;
|
|
5809
|
-
}
|
|
5810
|
-
}
|
|
5811
|
-
}
|
|
5812
|
-
|
|
5813
|
-
bbox = {
|
|
5814
|
-
minX: minX,
|
|
5815
|
-
minY: minY,
|
|
5816
|
-
maxX: maxX,
|
|
5817
|
-
maxY: maxY
|
|
5818
|
-
};
|
|
5819
|
-
boundingBoxCacheRef.current.set(item.id, bbox);
|
|
5820
|
-
} // 마커인 경우
|
|
5821
|
-
else {
|
|
5822
|
-
var offset = getOrComputeMarkerOffset(item);
|
|
5823
|
-
if (!offset) return false;
|
|
5824
|
-
var boxWidth = item.boxWidth || 50;
|
|
5825
|
-
var boxHeight = item.boxHeight || 28;
|
|
5826
|
-
bbox = {
|
|
5827
|
-
minX: offset.x - boxWidth / 2,
|
|
5828
|
-
minY: offset.y - boxHeight - 6,
|
|
5829
|
-
maxX: offset.x + boxWidth / 2,
|
|
5830
|
-
maxY: offset.y
|
|
5831
|
-
};
|
|
5832
|
-
boundingBoxCacheRef.current.set(item.id, bbox);
|
|
5833
|
-
}
|
|
5793
|
+
// 바운딩 박스 계산 (공통 함수 사용)
|
|
5794
|
+
var computed = computeBoundingBox(item);
|
|
5795
|
+
if (!computed) return false;
|
|
5796
|
+
bbox = computed;
|
|
5797
|
+
boundingBoxCacheRef.current.set(item.id, bbox);
|
|
5834
5798
|
} // 바운딩 박스와 viewport 교차 체크
|
|
5835
5799
|
|
|
5836
5800
|
|
|
@@ -5876,6 +5840,65 @@
|
|
|
5876
5840
|
|
|
5877
5841
|
return result;
|
|
5878
5842
|
}; // --------------------------------------------------------------------------
|
|
5843
|
+
// 유틸리티 함수: 바운딩 박스 계산
|
|
5844
|
+
// --------------------------------------------------------------------------
|
|
5845
|
+
|
|
5846
|
+
/**
|
|
5847
|
+
* 아이템의 바운딩 박스 계산 (폴리곤/마커 공통)
|
|
5848
|
+
*
|
|
5849
|
+
* @param item 마커 또는 폴리곤 데이터
|
|
5850
|
+
* @returns 바운딩 박스 또는 null
|
|
5851
|
+
*/
|
|
5852
|
+
|
|
5853
|
+
|
|
5854
|
+
var computeBoundingBox = function (item) {
|
|
5855
|
+
if (dataType === exports.CanvasDataType.POLYGON) {
|
|
5856
|
+
// 폴리곤: 모든 좌표의 최소/최대값 계산
|
|
5857
|
+
var offsets = getOrComputePolygonOffsets(item);
|
|
5858
|
+
if (!offsets) return null;
|
|
5859
|
+
var minX = Infinity,
|
|
5860
|
+
minY = Infinity,
|
|
5861
|
+
maxX = -Infinity,
|
|
5862
|
+
maxY = -Infinity;
|
|
5863
|
+
|
|
5864
|
+
for (var _i = 0, offsets_1 = offsets; _i < offsets_1.length; _i++) {
|
|
5865
|
+
var multiPolygon = offsets_1[_i];
|
|
5866
|
+
|
|
5867
|
+
for (var _a = 0, multiPolygon_1 = multiPolygon; _a < multiPolygon_1.length; _a++) {
|
|
5868
|
+
var polygonGroup = multiPolygon_1[_a];
|
|
5869
|
+
|
|
5870
|
+
for (var _b = 0, polygonGroup_1 = polygonGroup; _b < polygonGroup_1.length; _b++) {
|
|
5871
|
+
var _c = polygonGroup_1[_b],
|
|
5872
|
+
x = _c[0],
|
|
5873
|
+
y = _c[1];
|
|
5874
|
+
if (x < minX) minX = x;
|
|
5875
|
+
if (y < minY) minY = y;
|
|
5876
|
+
if (x > maxX) maxX = x;
|
|
5877
|
+
if (y > maxY) maxY = y;
|
|
5878
|
+
}
|
|
5879
|
+
}
|
|
5880
|
+
}
|
|
5881
|
+
|
|
5882
|
+
return {
|
|
5883
|
+
minX: minX,
|
|
5884
|
+
minY: minY,
|
|
5885
|
+
maxX: maxX,
|
|
5886
|
+
maxY: maxY
|
|
5887
|
+
};
|
|
5888
|
+
} else {
|
|
5889
|
+
// 마커: 중심점 기준 박스 크기 계산
|
|
5890
|
+
var offset = getOrComputeMarkerOffset(item);
|
|
5891
|
+
if (!offset) return null;
|
|
5892
|
+
var boxWidth = item.boxWidth || 50;
|
|
5893
|
+
var boxHeight = item.boxHeight || 28;
|
|
5894
|
+
return {
|
|
5895
|
+
minX: offset.x - boxWidth / 2,
|
|
5896
|
+
minY: offset.y - boxHeight - 6,
|
|
5897
|
+
maxX: offset.x + boxWidth / 2,
|
|
5898
|
+
maxY: offset.y
|
|
5899
|
+
};
|
|
5900
|
+
}
|
|
5901
|
+
}; // --------------------------------------------------------------------------
|
|
5879
5902
|
// 유틸리티 함수: 공간 인덱싱
|
|
5880
5903
|
// --------------------------------------------------------------------------
|
|
5881
5904
|
|
|
@@ -5890,52 +5913,12 @@
|
|
|
5890
5913
|
var currentMarkers = markersRef.current;
|
|
5891
5914
|
|
|
5892
5915
|
for (var _i = 0, currentMarkers_1 = currentMarkers; _i < currentMarkers_1.length; _i++) {
|
|
5893
|
-
var item = currentMarkers_1[_i];
|
|
5916
|
+
var item = currentMarkers_1[_i]; // 바운딩 박스 계산 (공통 함수 사용)
|
|
5894
5917
|
|
|
5895
|
-
|
|
5896
|
-
// 폴리곤: 바운딩 박스 계산 (최적화: 직접 비교)
|
|
5897
|
-
var offsets = getOrComputePolygonOffsets(item);
|
|
5898
|
-
|
|
5899
|
-
if (offsets) {
|
|
5900
|
-
var minX = Infinity,
|
|
5901
|
-
minY = Infinity,
|
|
5902
|
-
maxX = -Infinity,
|
|
5903
|
-
maxY = -Infinity;
|
|
5904
|
-
|
|
5905
|
-
for (var _a = 0, offsets_2 = offsets; _a < offsets_2.length; _a++) {
|
|
5906
|
-
var multiPolygon = offsets_2[_a];
|
|
5907
|
-
|
|
5908
|
-
for (var _b = 0, multiPolygon_2 = multiPolygon; _b < multiPolygon_2.length; _b++) {
|
|
5909
|
-
var polygonGroup = multiPolygon_2[_b];
|
|
5910
|
-
|
|
5911
|
-
for (var _c = 0, polygonGroup_2 = polygonGroup; _c < polygonGroup_2.length; _c++) {
|
|
5912
|
-
var _d = polygonGroup_2[_c],
|
|
5913
|
-
x = _d[0],
|
|
5914
|
-
y = _d[1];
|
|
5915
|
-
if (x < minX) minX = x;
|
|
5916
|
-
if (y < minY) minY = y;
|
|
5917
|
-
if (x > maxX) maxX = x;
|
|
5918
|
-
if (y > maxY) maxY = y;
|
|
5919
|
-
}
|
|
5920
|
-
}
|
|
5921
|
-
}
|
|
5918
|
+
var bbox = computeBoundingBox(item);
|
|
5922
5919
|
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
} else {
|
|
5926
|
-
// 마커: 점 기반 바운딩 박스
|
|
5927
|
-
var offset = getOrComputeMarkerOffset(item);
|
|
5928
|
-
|
|
5929
|
-
if (offset) {
|
|
5930
|
-
var boxWidth = item.boxWidth || 50;
|
|
5931
|
-
var boxHeight = item.boxHeight || 28;
|
|
5932
|
-
var tailHeight = 6;
|
|
5933
|
-
var minX = offset.x - boxWidth / 2;
|
|
5934
|
-
var minY = offset.y - boxHeight - tailHeight;
|
|
5935
|
-
var maxX = offset.x + boxWidth / 2;
|
|
5936
|
-
var maxY = offset.y;
|
|
5937
|
-
spatial.insert(item, minX, minY, maxX, maxY);
|
|
5938
|
-
}
|
|
5920
|
+
if (bbox) {
|
|
5921
|
+
spatial.insert(item, bbox.minX, bbox.minY, bbox.maxX, bbox.maxY);
|
|
5939
5922
|
}
|
|
5940
5923
|
}
|
|
5941
5924
|
}; // --------------------------------------------------------------------------
|
|
@@ -5964,7 +5947,7 @@
|
|
|
5964
5947
|
var renderAnimation = dataType === exports.CanvasDataType.MARKER ? props.renderAnimation : undefined;
|
|
5965
5948
|
var renderEvent = dataType === exports.CanvasDataType.MARKER ? props.renderEvent : function () {
|
|
5966
5949
|
var polygonProps = props;
|
|
5967
|
-
return renderPolygonEvent(polygonProps.selectedFillColor, polygonProps.selectedStrokeColor, polygonProps.selectedLineWidth, polygonProps.activeFillColor, polygonProps.activeStrokeColor, polygonProps.activeLineWidth, polygonProps.hoveredFillColor, polygonProps.hoveredStrokeColor, polygonProps.hoveredLineWidth);
|
|
5950
|
+
return renderPolygonEvent(polygonProps.baseFillColor, polygonProps.baseStrokeColor, polygonProps.baseLineWidth, polygonProps.selectedFillColor, polygonProps.selectedStrokeColor, polygonProps.selectedLineWidth, polygonProps.activeFillColor, polygonProps.activeStrokeColor, polygonProps.activeLineWidth, polygonProps.hoveredFillColor, polygonProps.hoveredStrokeColor, polygonProps.hoveredLineWidth);
|
|
5968
5951
|
}();
|
|
5969
5952
|
/**
|
|
5970
5953
|
* Base 레이어 렌더링 (뷰포트 컬링 적용, 선택된 마커 제외)
|
|
@@ -5973,6 +5956,10 @@
|
|
|
5973
5956
|
* 1. Shape 재사용으로 객체 생성/파괴 오버헤드 제거
|
|
5974
5957
|
* 2. sceneFunc 한 번만 설정 (함수 재생성 제거)
|
|
5975
5958
|
* 3. 클로저로 최신 데이터 참조
|
|
5959
|
+
*
|
|
5960
|
+
* 🎯 topOnHover 지원:
|
|
5961
|
+
* - renderEvent가 없을 때 Base Layer에서 hover 처리 (fallback)
|
|
5962
|
+
* - renderEvent가 있으면 Event Layer에서 처리 (성능 최적화)
|
|
5976
5963
|
*/
|
|
5977
5964
|
|
|
5978
5965
|
var doRenderBase = function () {
|
|
@@ -5987,17 +5974,40 @@
|
|
|
5987
5974
|
shape = new Konva__default["default"].Shape({
|
|
5988
5975
|
name: 'base-render-shape',
|
|
5989
5976
|
sceneFunc: function (context, shape) {
|
|
5990
|
-
var ctx = context;
|
|
5977
|
+
var ctx = context;
|
|
5978
|
+
var hovered = hoveredItemRef.current; // 클로저로 최신 ref 값 참조
|
|
5991
5979
|
|
|
5992
5980
|
var visibleMarkers = enableViewportCulling ? markersRef.current.filter(function (item) {
|
|
5993
5981
|
return isInViewport(item);
|
|
5994
|
-
}) : markersRef.current;
|
|
5982
|
+
}) : markersRef.current; // topOnHover가 true이고 renderEvent가 없으면 Base Layer에서 hover 처리
|
|
5983
|
+
|
|
5984
|
+
if (topOnHover && !renderEvent && hovered) {
|
|
5985
|
+
// hover된 항목 제외하고 렌더링
|
|
5986
|
+
visibleMarkers = visibleMarkers.filter(function (item) {
|
|
5987
|
+
return item.id !== hovered.id;
|
|
5988
|
+
});
|
|
5989
|
+
} // 일반 항목 렌더링
|
|
5990
|
+
|
|
5991
|
+
|
|
5995
5992
|
renderBase({
|
|
5996
5993
|
ctx: ctx,
|
|
5997
5994
|
items: visibleMarkers,
|
|
5998
5995
|
selectedIds: selectedIdsRef.current,
|
|
5999
5996
|
utils: renderUtils
|
|
6000
|
-
});
|
|
5997
|
+
}); // hover된 항목을 최상단에 렌더링 (renderEvent가 없을 때만)
|
|
5998
|
+
|
|
5999
|
+
if (topOnHover && !renderEvent && hovered) {
|
|
6000
|
+
var isHoveredInViewport = enableViewportCulling ? isInViewport(hovered) : true;
|
|
6001
|
+
|
|
6002
|
+
if (isHoveredInViewport) {
|
|
6003
|
+
renderBase({
|
|
6004
|
+
ctx: ctx,
|
|
6005
|
+
items: [hovered],
|
|
6006
|
+
selectedIds: selectedIdsRef.current,
|
|
6007
|
+
utils: renderUtils
|
|
6008
|
+
});
|
|
6009
|
+
}
|
|
6010
|
+
}
|
|
6001
6011
|
},
|
|
6002
6012
|
perfectDrawEnabled: false,
|
|
6003
6013
|
listening: false,
|
|
@@ -6042,13 +6052,6 @@
|
|
|
6042
6052
|
var doRenderEvent = function () {
|
|
6043
6053
|
var layer = eventLayerRef.current;
|
|
6044
6054
|
if (!layer) return;
|
|
6045
|
-
|
|
6046
|
-
if (!onClick && !onMouseOver && !onMouseOut) {
|
|
6047
|
-
layer.destroyChildren();
|
|
6048
|
-
layer.batchDraw();
|
|
6049
|
-
return;
|
|
6050
|
-
}
|
|
6051
|
-
|
|
6052
6055
|
if (!renderEvent) return; // 🔥 Shape 재사용: 이미 존재하면 재사용, 없으면 생성
|
|
6053
6056
|
|
|
6054
6057
|
var shape = layer.findOne('.event-render-shape');
|
|
@@ -6237,17 +6240,19 @@
|
|
|
6237
6240
|
return null;
|
|
6238
6241
|
};
|
|
6239
6242
|
/**
|
|
6240
|
-
* Hover 상태 설정 및
|
|
6243
|
+
* Hover 상태 설정 및 레이어 렌더링
|
|
6241
6244
|
*
|
|
6242
6245
|
* @param data hover된 마커/폴리곤 데이터 또는 null
|
|
6243
6246
|
*
|
|
6244
6247
|
* 최적화: RAF 제거하여 즉시 렌더링 (16ms 지연 제거)
|
|
6245
|
-
*
|
|
6248
|
+
*
|
|
6249
|
+
* 🎯 topOnHover 지원:
|
|
6250
|
+
* - renderEvent가 있으면: Event Layer에서만 처리 (성능 최적화)
|
|
6251
|
+
* - renderEvent가 없고 topOnHover=true면: Base Layer에서 처리
|
|
6246
6252
|
*/
|
|
6247
6253
|
|
|
6248
6254
|
|
|
6249
6255
|
var setHovered = function (data) {
|
|
6250
|
-
if (!onMouseOver && !onMouseOut) return;
|
|
6251
6256
|
hoveredItemRef.current = data;
|
|
6252
6257
|
|
|
6253
6258
|
if (draggingRef.current) {
|
|
@@ -6255,10 +6260,15 @@
|
|
|
6255
6260
|
} else {
|
|
6256
6261
|
controller.setMapCursor(data ? 'pointer' : 'grab');
|
|
6257
6262
|
} // 즉시 렌더링 (RAF 없이)
|
|
6258
|
-
// topOnHover는 Event Layer에서만 처리 (Base Layer 재렌더링 제거로 성능 향상)
|
|
6259
6263
|
|
|
6260
6264
|
|
|
6261
|
-
|
|
6265
|
+
if (renderEvent) {
|
|
6266
|
+
// renderEvent가 있으면 Event Layer에서만 처리 (성능 최적화)
|
|
6267
|
+
doRenderEvent();
|
|
6268
|
+
} else if (topOnHover) {
|
|
6269
|
+
// renderEvent가 없고 topOnHover가 true면 Base Layer에서 처리
|
|
6270
|
+
doRenderBase();
|
|
6271
|
+
}
|
|
6262
6272
|
};
|
|
6263
6273
|
/**
|
|
6264
6274
|
* 클릭 처리 (단일/다중 선택)
|
|
@@ -6272,8 +6282,7 @@
|
|
|
6272
6282
|
|
|
6273
6283
|
|
|
6274
6284
|
var handleLocalClick = function (data) {
|
|
6275
|
-
|
|
6276
|
-
|
|
6285
|
+
// 1. 선택 상태 업데이트
|
|
6277
6286
|
if (enableMultiSelect) {
|
|
6278
6287
|
// 다중 선택: Set과 Map 동시 업데이트
|
|
6279
6288
|
var newSelected = new Set(selectedIdsRef.current);
|
|
@@ -6325,7 +6334,6 @@
|
|
|
6325
6334
|
|
|
6326
6335
|
if (disableInteractionRef.current) return; // 🚫 상호작용 비활성화 시 즉시 반환
|
|
6327
6336
|
|
|
6328
|
-
if (!onClick) return;
|
|
6329
6337
|
if (context || !((_a = event === null || event === void 0 ? void 0 : event.param) === null || _a === void 0 ? void 0 : _a.position)) return;
|
|
6330
6338
|
|
|
6331
6339
|
try {
|
|
@@ -6334,7 +6342,10 @@
|
|
|
6334
6342
|
|
|
6335
6343
|
if (data_1) {
|
|
6336
6344
|
handleLocalClick(data_1);
|
|
6337
|
-
|
|
6345
|
+
|
|
6346
|
+
if (onClick) {
|
|
6347
|
+
onClick(data_1, selectedIdsRef.current);
|
|
6348
|
+
}
|
|
6338
6349
|
}
|
|
6339
6350
|
} catch (error) {
|
|
6340
6351
|
console.error('[WoongKonvaMarker] handleClick error:', error);
|
|
@@ -6350,7 +6361,6 @@
|
|
|
6350
6361
|
|
|
6351
6362
|
if (disableInteractionRef.current) return; // 🚫 상호작용 비활성화 시 즉시 반환
|
|
6352
6363
|
|
|
6353
|
-
if (!onMouseOver && !onMouseOut) return;
|
|
6354
6364
|
if (context || !((_a = event === null || event === void 0 ? void 0 : event.param) === null || _a === void 0 ? void 0 : _a.position)) return;
|
|
6355
6365
|
|
|
6356
6366
|
try {
|
|
@@ -6393,7 +6403,6 @@
|
|
|
6393
6403
|
var handleMouseLeave = function () {
|
|
6394
6404
|
if (disableInteractionRef.current) return; // 🚫 상호작용 비활성화 시 즉시 반환
|
|
6395
6405
|
|
|
6396
|
-
if (!onMouseOver && !onMouseOut) return;
|
|
6397
6406
|
var prevHovered = hoveredItemRef.current;
|
|
6398
6407
|
|
|
6399
6408
|
if (prevHovered) {
|
|
@@ -6678,116 +6687,6 @@
|
|
|
6678
6687
|
}
|
|
6679
6688
|
}), divElement);
|
|
6680
6689
|
};
|
|
6681
|
-
/**
|
|
6682
|
-
* 🚀 WoongCanvasLayer - Konva 기반 초고성능 마커/폴리곤 렌더링 컴포넌트
|
|
6683
|
-
*
|
|
6684
|
-
* ## 📌 주요 특징
|
|
6685
|
-
* - **30,000개 이상의 폴리곤/마커를 60fps로 렌더링**
|
|
6686
|
-
* - **Multi-Layer 아키텍처**: Base/Animation/Event 레이어 분리
|
|
6687
|
-
* - **Spatial Hash Grid**: O(1) 수준의 빠른 Hit Test
|
|
6688
|
-
* - **LRU 캐시**: 좌표 변환 결과 캐싱으로 성능 최적화
|
|
6689
|
-
* - **Viewport Culling**: 화면에 보이는 영역만 렌더링
|
|
6690
|
-
* - **Discriminated Union Props**: 타입 안전한 MARKER/POLYGON 모드
|
|
6691
|
-
*
|
|
6692
|
-
* ## 🎯 사용 방법
|
|
6693
|
-
*
|
|
6694
|
-
* ### 1️⃣ POLYGON 모드 (자동 렌더링)
|
|
6695
|
-
* ```tsx
|
|
6696
|
-
* <WoongCanvasLayer
|
|
6697
|
-
* dataType={CanvasDataType.POLYGON}
|
|
6698
|
-
* data={polygons}
|
|
6699
|
-
* baseFillColor="rgba(255, 100, 100, 0.5)"
|
|
6700
|
-
* baseStrokeColor="rgba(200, 50, 50, 0.8)"
|
|
6701
|
-
* baseLineWidth={2}
|
|
6702
|
-
* selectedFillColor="rgba(255, 193, 7, 0.7)"
|
|
6703
|
-
* selectedStrokeColor="rgba(255, 152, 0, 1)"
|
|
6704
|
-
* selectedLineWidth={4}
|
|
6705
|
-
* hoveredFillColor="rgba(100, 150, 255, 0.8)" // optional
|
|
6706
|
-
* hoveredStrokeColor="rgba(0, 100, 200, 1)" // optional
|
|
6707
|
-
* hoveredLineWidth={3} // optional
|
|
6708
|
-
* enableMultiSelect={true}
|
|
6709
|
-
* onClick={handleClick}
|
|
6710
|
-
* />
|
|
6711
|
-
* ```
|
|
6712
|
-
*
|
|
6713
|
-
* ### 2️⃣ MARKER 모드 (커스텀 렌더링)
|
|
6714
|
-
* ```tsx
|
|
6715
|
-
* <WoongCanvasLayer
|
|
6716
|
-
* dataType={CanvasDataType.MARKER}
|
|
6717
|
-
* data={markers}
|
|
6718
|
-
* renderBase={renderMarkerBase} // required
|
|
6719
|
-
* renderAnimation={renderMarkerAnimation} // optional
|
|
6720
|
-
* renderEvent={renderMarkerEvent} // optional
|
|
6721
|
-
* topOnHover={true}
|
|
6722
|
-
* onClick={handleClick}
|
|
6723
|
-
* />
|
|
6724
|
-
* ```
|
|
6725
|
-
*
|
|
6726
|
-
* ## 📊 데이터 형식
|
|
6727
|
-
* ```typescript
|
|
6728
|
-
* const data: KonvaCanvasData<T>[] = [
|
|
6729
|
-
* {
|
|
6730
|
-
* id: 'unique-id',
|
|
6731
|
-
* position: new Position(lat, lng),
|
|
6732
|
-
* // POLYGON: paths 필수
|
|
6733
|
-
* paths: [[[lat, lng], [lat, lng], ...]],
|
|
6734
|
-
* // MARKER: boxWidth/boxHeight 권장 (Hit Test 정확도)
|
|
6735
|
-
* boxWidth: 60,
|
|
6736
|
-
* boxHeight: 75,
|
|
6737
|
-
* // 커스텀 데이터
|
|
6738
|
-
* ...customData
|
|
6739
|
-
* }
|
|
6740
|
-
* ];
|
|
6741
|
-
* ```
|
|
6742
|
-
*
|
|
6743
|
-
* ## ⚡ 성능 최적화 팁
|
|
6744
|
-
* 1. **동적 boxWidth 계산**: `measureText()`로 실제 너비 계산 후 전달
|
|
6745
|
-
* 2. **enableViewportCulling**: 대량 데이터 시 필수 (기본 true)
|
|
6746
|
-
* 3. **selectedItems 외부 관리**: 상태를 외부에서 관리하여 리렌더링 최소화
|
|
6747
|
-
* 4. **React.memo 최적화**: 컴포넌트가 자동으로 불필요한 리렌더링 방지
|
|
6748
|
-
*
|
|
6749
|
-
* @template T 마커/폴리곤 데이터의 추가 속성 타입
|
|
6750
|
-
*
|
|
6751
|
-
* @example
|
|
6752
|
-
* // 동적 boxWidth 계산 예시
|
|
6753
|
-
* const tempCtx = document.createElement('canvas').getContext('2d');
|
|
6754
|
-
* tempCtx.font = 'bold 15px Arial';
|
|
6755
|
-
* const boxWidth = Math.max(60, tempCtx.measureText(text).width + 20);
|
|
6756
|
-
*
|
|
6757
|
-
* @see {@link https://github.com/your-repo/docs/WoongCanvasLayer.md} 전체 문서
|
|
6758
|
-
*/
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
var WoongCanvasLayer = React__default["default"].memo(WoongCanvasLayerComponent, function (prevProps, nextProps) {
|
|
6762
|
-
// // 1. data 비교
|
|
6763
|
-
// const prevData = prevProps.data;
|
|
6764
|
-
// const nextData = nextProps.data;
|
|
6765
|
-
// // 참조가 같으면 스킵
|
|
6766
|
-
// if (prevData !== nextData) {
|
|
6767
|
-
// // 길이가 다르면 변경됨
|
|
6768
|
-
// if (prevData.length !== nextData.length) return false;
|
|
6769
|
-
// // 각 데이터의 ID 비교
|
|
6770
|
-
// for (let i = 0; i < prevData.length; i++) {
|
|
6771
|
-
// if (prevData[i].id !== nextData[i].id) {
|
|
6772
|
-
// return false; // 변경됨 → 리렌더링
|
|
6773
|
-
// }
|
|
6774
|
-
// }
|
|
6775
|
-
// }
|
|
6776
|
-
// 2. selectedItems 비교 (참조만 비교)
|
|
6777
|
-
if (prevProps.selectedItems !== nextProps.selectedItems) {
|
|
6778
|
-
return false; // 변경됨 → 리렌더링
|
|
6779
|
-
}
|
|
6780
|
-
|
|
6781
|
-
if (prevProps.selectedItem !== nextProps.selectedItem) {
|
|
6782
|
-
return false; // 변경됨 → 리렌더링
|
|
6783
|
-
}
|
|
6784
|
-
|
|
6785
|
-
if (prevProps.disableInteraction !== nextProps.disableInteraction) {
|
|
6786
|
-
return false; // 변경됨 → 리렌더링
|
|
6787
|
-
}
|
|
6788
|
-
|
|
6789
|
-
return true; // 같음 → 리렌더링 스킵
|
|
6790
|
-
});
|
|
6791
6690
|
|
|
6792
6691
|
var css_248z = ".MintMapWrapper-module_mint-map-control-wrapper-container__DONh7 {\n position: absolute;\n width: 100%;\n height: 100%;\n display: flex;\n pointer-events: none;\n z-index: 101;\n}\n\n.MintMapWrapper-module_mint-map-overlay-wrapper__Jn4wV {\n position: absolute;\n z-index: 1;\n}";
|
|
6793
6692
|
var styles = {"mint-map-control-wrapper-container":"MintMapWrapper-module_mint-map-control-wrapper-container__DONh7","mint-map-overlay-wrapper":"MintMapWrapper-module_mint-map-overlay-wrapper__Jn4wV"};
|