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