@mint-ui/map 1.2.0-test.10 → 1.2.0-test.12
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/MintMapController.d.ts +1 -0
- package/dist/components/mint-map/core/MintMapCore.js +1 -2
- package/dist/components/mint-map/core/advanced/woongCanvas/WoongCanvasLayer.d.ts +162 -0
- package/dist/components/mint-map/core/advanced/woongCanvas/{WoongKonvaMarker.js → WoongCanvasLayer.js} +136 -82
- package/dist/components/mint-map/core/advanced/woongCanvas/index.d.ts +2 -2
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/renderer.d.ts +59 -0
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/renderer.js +226 -0
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/types.d.ts +95 -1
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/utils.d.ts +17 -0
- package/dist/components/mint-map/core/advanced/woongCanvas/shared/utils.js +42 -0
- package/dist/components/mint-map/core/wrapper/MapMarkerWrapper.js +22 -1
- package/dist/components/mint-map/google/GoogleMintMapController.d.ts +1 -0
- package/dist/components/mint-map/google/GoogleMintMapController.js +6 -1
- package/dist/components/mint-map/kakao/KakaoMintMapController.d.ts +1 -0
- package/dist/components/mint-map/kakao/KakaoMintMapController.js +6 -1
- package/dist/components/mint-map/naver/NaverMintMapController.d.ts +3 -0
- package/dist/components/mint-map/naver/NaverMintMapController.js +39 -4
- package/dist/index.es.js +458 -83
- package/dist/index.js +4 -2
- package/dist/index.umd.js +460 -83
- package/package.json +1 -1
- 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 -54
package/dist/index.umd.js
CHANGED
|
@@ -948,6 +948,46 @@
|
|
|
948
948
|
var y = markerOffset.y - boxHeight - tailHeight;
|
|
949
949
|
return clickedOffset.x >= x && clickedOffset.x <= x + boxWidth && clickedOffset.y >= y && clickedOffset.y <= y + boxHeight;
|
|
950
950
|
};
|
|
951
|
+
var hexToRgba = function (hexColor, alpha) {
|
|
952
|
+
if (alpha === void 0) {
|
|
953
|
+
alpha = 1;
|
|
954
|
+
} // NOTE: 입력된 hexColor에서 "#" 제거
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
var hex = hexColor.replace('#', ''); // NOTE: 6자리일 경우 알파 값은 사용자가 제공한 alpha 값으로 설정
|
|
958
|
+
|
|
959
|
+
if (hex.length === 6) {
|
|
960
|
+
var r = parseInt(hex.substring(0, 2), 16);
|
|
961
|
+
var g = parseInt(hex.substring(2, 4), 16);
|
|
962
|
+
var b = parseInt(hex.substring(4, 6), 16);
|
|
963
|
+
return "rgba(".concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(alpha, ")");
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
throw new Error('Invalid hex color format');
|
|
967
|
+
};
|
|
968
|
+
var tempCanvas = document.createElement('canvas');
|
|
969
|
+
var tempCtx = tempCanvas.getContext('2d');
|
|
970
|
+
/**
|
|
971
|
+
* 텍스트 박스의 너비를 계산합니다.
|
|
972
|
+
*
|
|
973
|
+
* @param {Object} params - 파라미터 객체
|
|
974
|
+
* @param {string} params.text - 측정할 텍스트
|
|
975
|
+
* @param {string} params.fontConfig - 폰트 설정 (예: 'bold 16px Arial')
|
|
976
|
+
* @param {number} params.padding - 텍스트 박스에 적용할 패딩 값
|
|
977
|
+
* @param {number} params.minWidth - 최소 너비
|
|
978
|
+
* @returns {number} 계산된 텍스트 박스의 너비
|
|
979
|
+
*/
|
|
980
|
+
|
|
981
|
+
var calculateTextBoxWidth = function (_a) {
|
|
982
|
+
var text = _a.text,
|
|
983
|
+
fontConfig = _a.fontConfig,
|
|
984
|
+
padding = _a.padding,
|
|
985
|
+
minWidth = _a.minWidth;
|
|
986
|
+
if (!tempCtx) return 0;
|
|
987
|
+
tempCtx.font = fontConfig;
|
|
988
|
+
var textWidth = tempCtx.measureText(text).width;
|
|
989
|
+
return Math.max(minWidth, textWidth + padding);
|
|
990
|
+
};
|
|
951
991
|
|
|
952
992
|
var KonvaMarkerContext = React.createContext(null);
|
|
953
993
|
var KonvaMarkerProvider = function (_a) {
|
|
@@ -2758,7 +2798,7 @@
|
|
|
2758
2798
|
var onMouseOverHandler = function (e) {
|
|
2759
2799
|
var _a;
|
|
2760
2800
|
|
|
2761
|
-
var marker = markerRef.current;
|
|
2801
|
+
var marker = markerRef.current;
|
|
2762
2802
|
|
|
2763
2803
|
if (marker) {
|
|
2764
2804
|
var mouseOverHandler = (_a = options === null || options === void 0 ? void 0 : options.event) === null || _a === void 0 ? void 0 : _a.get('mouseover');
|
|
@@ -2771,6 +2811,25 @@
|
|
|
2771
2811
|
|
|
2772
2812
|
next && topOnHover && controller.markerToTheTop(marker);
|
|
2773
2813
|
}
|
|
2814
|
+
}; // 20251014 | 장한별 | mouseleave 이벤트 추가, 마우스가 마커 위에서 떠날 때 원래 zindex 를 복구하기 위함
|
|
2815
|
+
|
|
2816
|
+
|
|
2817
|
+
var onMouseLeaveHandler = function (e) {
|
|
2818
|
+
var _a;
|
|
2819
|
+
|
|
2820
|
+
var marker = markerRef.current;
|
|
2821
|
+
|
|
2822
|
+
if (marker) {
|
|
2823
|
+
var mouseOutHandler = (_a = options === null || options === void 0 ? void 0 : options.event) === null || _a === void 0 ? void 0 : _a.get('mouseout');
|
|
2824
|
+
var next = true;
|
|
2825
|
+
|
|
2826
|
+
if (mouseOutHandler) {
|
|
2827
|
+
var hasNext = mouseOutHandler(e);
|
|
2828
|
+
hasNext !== undefined && (next = hasNext);
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
next && topOnHover && controller.restoreMarkerZIndex(marker);
|
|
2832
|
+
}
|
|
2774
2833
|
}; //create object
|
|
2775
2834
|
|
|
2776
2835
|
|
|
@@ -2788,10 +2847,12 @@
|
|
|
2788
2847
|
}); //드래그 여부 초기화를 먼저 수행하기 위해 capture : true 처리
|
|
2789
2848
|
|
|
2790
2849
|
divElement.addEventListener('mouseover', onMouseOverHandler);
|
|
2850
|
+
divElement.addEventListener('mouseleave', onMouseLeaveHandler);
|
|
2791
2851
|
return function () {
|
|
2792
2852
|
divElement.removeEventListener('click', onClickHandler);
|
|
2793
2853
|
divElement.removeEventListener('mousedown', onMousedownHandler);
|
|
2794
2854
|
divElement.removeEventListener('mouseover', onMouseOverHandler);
|
|
2855
|
+
divElement.removeEventListener('mouseleave', onMouseLeaveHandler);
|
|
2795
2856
|
|
|
2796
2857
|
if (markerRef.current) {
|
|
2797
2858
|
controller.clearDrawable(markerRef.current);
|
|
@@ -5357,45 +5418,249 @@
|
|
|
5357
5418
|
}))));
|
|
5358
5419
|
}
|
|
5359
5420
|
|
|
5360
|
-
|
|
5361
|
-
|
|
5421
|
+
/**
|
|
5422
|
+
* 폴리곤 렌더링 유틸리티
|
|
5423
|
+
*
|
|
5424
|
+
* 이 파일은 폴리곤 렌더링을 위한 헬퍼 함수와 팩토리 함수를 제공합니다.
|
|
5425
|
+
*/
|
|
5362
5426
|
|
|
5363
5427
|
/**
|
|
5364
|
-
*
|
|
5428
|
+
* 폴리곤 그리기 헬퍼 함수 (도넛 폴리곤 지원)
|
|
5429
|
+
*/
|
|
5430
|
+
var drawPolygon = function (_a) {
|
|
5431
|
+
var ctx = _a.ctx,
|
|
5432
|
+
polygonOffsets = _a.polygonOffsets,
|
|
5433
|
+
isDonutPolygon = _a.isDonutPolygon,
|
|
5434
|
+
fillColor = _a.fillColor,
|
|
5435
|
+
strokeColor = _a.strokeColor,
|
|
5436
|
+
lineWidth = _a.lineWidth;
|
|
5437
|
+
|
|
5438
|
+
for (var _i = 0, polygonOffsets_1 = polygonOffsets; _i < polygonOffsets_1.length; _i++) {
|
|
5439
|
+
var multiPolygon = polygonOffsets_1[_i];
|
|
5440
|
+
|
|
5441
|
+
if (isDonutPolygon) {
|
|
5442
|
+
ctx.beginPath(); // 1. 외부 폴리곤 그리기
|
|
5443
|
+
|
|
5444
|
+
if (multiPolygon[0] && multiPolygon[0].length > 0) {
|
|
5445
|
+
ctx.moveTo(multiPolygon[0][0][0], multiPolygon[0][0][1]);
|
|
5446
|
+
|
|
5447
|
+
for (var i = 1; i < multiPolygon[0].length; i++) {
|
|
5448
|
+
ctx.lineTo(multiPolygon[0][i][0], multiPolygon[0][i][1]);
|
|
5449
|
+
}
|
|
5450
|
+
|
|
5451
|
+
ctx.closePath();
|
|
5452
|
+
} // 2. 내부 폴리곤 (구멍들) 그리기 - 같은 path에 추가
|
|
5453
|
+
|
|
5454
|
+
|
|
5455
|
+
for (var j = 1; j < multiPolygon.length; j++) {
|
|
5456
|
+
var innerPolygon = multiPolygon[j];
|
|
5457
|
+
if (innerPolygon.length === 0) continue;
|
|
5458
|
+
ctx.moveTo(innerPolygon[0][0], innerPolygon[0][1]);
|
|
5459
|
+
|
|
5460
|
+
for (var i = 1; i < innerPolygon.length; i++) {
|
|
5461
|
+
ctx.lineTo(innerPolygon[i][0], innerPolygon[i][1]);
|
|
5462
|
+
}
|
|
5463
|
+
|
|
5464
|
+
ctx.closePath();
|
|
5465
|
+
} // 3. evenodd fill rule로 구멍 뚫기
|
|
5466
|
+
|
|
5467
|
+
|
|
5468
|
+
ctx.fillStyle = fillColor;
|
|
5469
|
+
ctx.fill('evenodd'); // 4. 외곽선 그리기
|
|
5470
|
+
|
|
5471
|
+
ctx.strokeStyle = strokeColor;
|
|
5472
|
+
ctx.lineWidth = lineWidth;
|
|
5473
|
+
ctx.stroke();
|
|
5474
|
+
} else {
|
|
5475
|
+
// 일반 폴리곤
|
|
5476
|
+
for (var _b = 0, multiPolygon_1 = multiPolygon; _b < multiPolygon_1.length; _b++) {
|
|
5477
|
+
var polygonGroup = multiPolygon_1[_b];
|
|
5478
|
+
if (!polygonGroup.length) continue;
|
|
5479
|
+
ctx.beginPath();
|
|
5480
|
+
var firstPoint = polygonGroup[0];
|
|
5481
|
+
ctx.moveTo(firstPoint[0], firstPoint[1]);
|
|
5482
|
+
|
|
5483
|
+
for (var i = 1; i < polygonGroup.length; i++) {
|
|
5484
|
+
var point = polygonGroup[i];
|
|
5485
|
+
ctx.lineTo(point[0], point[1]);
|
|
5486
|
+
}
|
|
5487
|
+
|
|
5488
|
+
ctx.closePath();
|
|
5489
|
+
ctx.fillStyle = fillColor;
|
|
5490
|
+
ctx.strokeStyle = strokeColor;
|
|
5491
|
+
ctx.lineWidth = lineWidth;
|
|
5492
|
+
ctx.fill();
|
|
5493
|
+
ctx.stroke();
|
|
5494
|
+
}
|
|
5495
|
+
}
|
|
5496
|
+
}
|
|
5497
|
+
};
|
|
5498
|
+
/**
|
|
5499
|
+
* 폴리곤 Base 렌더링 함수
|
|
5365
5500
|
*
|
|
5366
|
-
*
|
|
5367
|
-
*
|
|
5368
|
-
*
|
|
5369
|
-
*
|
|
5370
|
-
* - Viewport Culling으로 보이는 영역만 렌더링
|
|
5501
|
+
* @param baseFillColor 기본 폴리곤 채우기 색상
|
|
5502
|
+
* @param baseStrokeColor 기본 폴리곤 테두리 색상
|
|
5503
|
+
* @param baseLineWidth 기본 폴리곤 테두리 두께
|
|
5504
|
+
* @returns Base Layer 렌더링 함수
|
|
5371
5505
|
*
|
|
5372
|
-
* @
|
|
5506
|
+
* @example
|
|
5507
|
+
* const renderBase = renderPolygonBase(
|
|
5508
|
+
* 'rgba(255, 100, 100, 0.5)',
|
|
5509
|
+
* 'rgba(200, 50, 50, 0.8)',
|
|
5510
|
+
* 2
|
|
5511
|
+
* );
|
|
5373
5512
|
*/
|
|
5374
5513
|
|
|
5375
|
-
var
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5514
|
+
var renderPolygonBase = function (baseFillColor, baseStrokeColor, baseLineWidth) {
|
|
5515
|
+
return function (_a) {
|
|
5516
|
+
var ctx = _a.ctx,
|
|
5517
|
+
items = _a.items,
|
|
5518
|
+
selectedIds = _a.selectedIds,
|
|
5519
|
+
utils = _a.utils;
|
|
5520
|
+
|
|
5521
|
+
for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
|
|
5522
|
+
var item = items_1[_i]; // 선택된 항목은 Event Layer에서 그림
|
|
5523
|
+
|
|
5524
|
+
if (selectedIds.has(item.id)) continue;
|
|
5525
|
+
if (!item.paths) continue;
|
|
5526
|
+
var polygonOffsets = utils.getOrComputePolygonOffsets(item);
|
|
5527
|
+
if (!polygonOffsets) continue;
|
|
5528
|
+
drawPolygon({
|
|
5529
|
+
ctx: ctx,
|
|
5530
|
+
polygonOffsets: polygonOffsets,
|
|
5531
|
+
isDonutPolygon: item.isDonutPolygon || false,
|
|
5532
|
+
fillColor: baseFillColor,
|
|
5533
|
+
strokeColor: baseStrokeColor,
|
|
5534
|
+
lineWidth: baseLineWidth
|
|
5535
|
+
});
|
|
5536
|
+
}
|
|
5537
|
+
};
|
|
5538
|
+
};
|
|
5539
|
+
/**
|
|
5540
|
+
* 폴리곤 Event 렌더링 함수
|
|
5541
|
+
*
|
|
5542
|
+
* @param selectedFillColor 선택된 폴리곤 채우기 색상
|
|
5543
|
+
* @param selectedStrokeColor 선택된 폴리곤 테두리 색상
|
|
5544
|
+
* @param selectedLineWidth 선택된 폴리곤 테두리 두께
|
|
5545
|
+
* @param activeFillColor 마지막 선택된 폴리곤 채우기 색상 (선택, 기본값: selectedFillColor)
|
|
5546
|
+
* @param activeStrokeColor 마지막 선택된 폴리곤 테두리 색상 (선택, 기본값: selectedStrokeColor)
|
|
5547
|
+
* @param activeLineWidth 마지막 선택된 폴리곤 테두리 두께 (선택, 기본값: selectedLineWidth)
|
|
5548
|
+
* @param hoveredFillColor Hover 시 폴리곤 채우기 색상 (선택, 기본값: selectedFillColor)
|
|
5549
|
+
* @param hoveredStrokeColor Hover 시 폴리곤 테두리 색상 (선택, 기본값: selectedStrokeColor)
|
|
5550
|
+
* @param hoveredLineWidth Hover 시 폴리곤 테두리 두께 (선택, 기본값: selectedLineWidth)
|
|
5551
|
+
* @returns Event Layer 렌더링 함수
|
|
5552
|
+
*
|
|
5553
|
+
* @example
|
|
5554
|
+
* const renderEvent = renderPolygonEvent(
|
|
5555
|
+
* 'rgba(255, 193, 7, 0.7)',
|
|
5556
|
+
* 'rgba(255, 152, 0, 1)',
|
|
5557
|
+
* 4,
|
|
5558
|
+
* 'rgba(255, 0, 0, 0.8)',
|
|
5559
|
+
* undefined,
|
|
5560
|
+
* undefined,
|
|
5561
|
+
* 'rgba(100, 150, 255, 0.8)'
|
|
5562
|
+
* );
|
|
5563
|
+
*/
|
|
5564
|
+
|
|
5565
|
+
var renderPolygonEvent = function (selectedFillColor, selectedStrokeColor, selectedLineWidth, activeFillColor, activeStrokeColor, activeLineWidth, hoveredFillColor, hoveredStrokeColor, hoveredLineWidth) {
|
|
5566
|
+
// 기본값 설정 (selected 기준)
|
|
5567
|
+
var _activeFillColor = activeFillColor || selectedFillColor;
|
|
5568
|
+
|
|
5569
|
+
var _activeStrokeColor = activeStrokeColor || selectedStrokeColor;
|
|
5570
|
+
|
|
5571
|
+
var _activeLineWidth = activeLineWidth || selectedLineWidth;
|
|
5572
|
+
|
|
5573
|
+
var _hoveredFillColor = hoveredFillColor || selectedFillColor;
|
|
5574
|
+
|
|
5575
|
+
var _hoveredStrokeColor = hoveredStrokeColor || selectedStrokeColor;
|
|
5576
|
+
|
|
5577
|
+
var _hoveredLineWidth = hoveredLineWidth || selectedLineWidth;
|
|
5578
|
+
|
|
5579
|
+
return function (_a) {
|
|
5580
|
+
var ctx = _a.ctx,
|
|
5581
|
+
hoveredItem = _a.hoveredItem,
|
|
5582
|
+
utils = _a.utils,
|
|
5583
|
+
selectedItems = _a.selectedItems,
|
|
5584
|
+
selectedItem = _a.selectedItem; // 1. 선택된 항목들 그리기 (마지막 선택 항목과 호버된 항목 제외)
|
|
5585
|
+
|
|
5586
|
+
if (selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length) {
|
|
5587
|
+
for (var _i = 0, selectedItems_1 = selectedItems; _i < selectedItems_1.length; _i++) {
|
|
5588
|
+
var item = selectedItems_1[_i]; // 마지막 선택 항목과 호버된 항목은 나중에 따로 그림
|
|
5589
|
+
|
|
5590
|
+
if (item.id === (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id) || (hoveredItem === null || hoveredItem === void 0 ? void 0 : hoveredItem.id) === item.id) continue;
|
|
5591
|
+
if (!item.paths) continue;
|
|
5592
|
+
var polygonOffsets = utils.getOrComputePolygonOffsets(item);
|
|
5593
|
+
if (!polygonOffsets) continue;
|
|
5594
|
+
drawPolygon({
|
|
5595
|
+
ctx: ctx,
|
|
5596
|
+
polygonOffsets: polygonOffsets,
|
|
5597
|
+
isDonutPolygon: item.isDonutPolygon || false,
|
|
5598
|
+
fillColor: selectedFillColor,
|
|
5599
|
+
strokeColor: selectedStrokeColor,
|
|
5600
|
+
lineWidth: selectedLineWidth
|
|
5601
|
+
});
|
|
5602
|
+
}
|
|
5603
|
+
} // 2. 마지막 선택된 항목 그리기 (호버되지 않은 경우)
|
|
5604
|
+
|
|
5605
|
+
|
|
5606
|
+
if ((selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.paths) && (hoveredItem === null || hoveredItem === void 0 ? void 0 : hoveredItem.id) !== selectedItem.id) {
|
|
5607
|
+
var polygonOffsets = utils.getOrComputePolygonOffsets(selectedItem);
|
|
5608
|
+
|
|
5609
|
+
if (polygonOffsets) {
|
|
5610
|
+
drawPolygon({
|
|
5611
|
+
ctx: ctx,
|
|
5612
|
+
polygonOffsets: polygonOffsets,
|
|
5613
|
+
isDonutPolygon: selectedItem.isDonutPolygon || false,
|
|
5614
|
+
fillColor: _activeFillColor,
|
|
5615
|
+
strokeColor: _activeStrokeColor,
|
|
5616
|
+
lineWidth: _activeLineWidth
|
|
5617
|
+
});
|
|
5618
|
+
}
|
|
5619
|
+
} // 3. 호버된 항목 그리기 (가장 위에 표시)
|
|
5620
|
+
|
|
5621
|
+
|
|
5622
|
+
if (hoveredItem === null || hoveredItem === void 0 ? void 0 : hoveredItem.paths) {
|
|
5623
|
+
var polygonOffsets = utils.getOrComputePolygonOffsets(hoveredItem);
|
|
5624
|
+
if (!polygonOffsets) return;
|
|
5625
|
+
var isSelected = selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.some(function (item) {
|
|
5626
|
+
return item.id === hoveredItem.id;
|
|
5627
|
+
});
|
|
5628
|
+
drawPolygon({
|
|
5629
|
+
ctx: ctx,
|
|
5630
|
+
polygonOffsets: polygonOffsets,
|
|
5631
|
+
isDonutPolygon: hoveredItem.isDonutPolygon || false,
|
|
5632
|
+
fillColor: isSelected ? _activeFillColor : _hoveredFillColor,
|
|
5633
|
+
strokeColor: isSelected ? _activeStrokeColor : _hoveredStrokeColor,
|
|
5634
|
+
lineWidth: isSelected ? _activeLineWidth : _hoveredLineWidth
|
|
5635
|
+
});
|
|
5636
|
+
}
|
|
5637
|
+
};
|
|
5638
|
+
};
|
|
5639
|
+
|
|
5640
|
+
// 메인 컴포넌트
|
|
5641
|
+
// ============================================================================
|
|
5642
|
+
|
|
5643
|
+
var WoongCanvasLayerComponent = function (props) {
|
|
5644
|
+
var data = props.data,
|
|
5645
|
+
dataType = props.dataType,
|
|
5646
|
+
onClick = props.onClick,
|
|
5647
|
+
onMouseOver = props.onMouseOver,
|
|
5648
|
+
onMouseOut = props.onMouseOut,
|
|
5649
|
+
_a = props.enableMultiSelect,
|
|
5650
|
+
enableMultiSelect = _a === void 0 ? false : _a,
|
|
5651
|
+
_b = props.topOnHover,
|
|
5652
|
+
topOnHover = _b === void 0 ? false : _b,
|
|
5653
|
+
_c = props.enableViewportCulling,
|
|
5654
|
+
enableViewportCulling = _c === void 0 ? true : _c,
|
|
5655
|
+
_d = props.cullingMargin,
|
|
5656
|
+
cullingMargin = _d === void 0 ? DEFAULT_CULLING_MARGIN : _d,
|
|
5657
|
+
_e = props.maxCacheSize,
|
|
5658
|
+
maxCacheSize = _e === void 0 ? DEFAULT_MAX_CACHE_SIZE : _e,
|
|
5659
|
+
externalSelectedItems = props.selectedItems,
|
|
5660
|
+
externalSelectedItem = props.selectedItem,
|
|
5661
|
+
_f = props.disableInteraction,
|
|
5662
|
+
disableInteraction = _f === void 0 ? false : _f,
|
|
5663
|
+
options = tslib.__rest(props, ["data", "dataType", "onClick", "onMouseOver", "onMouseOut", "enableMultiSelect", "topOnHover", "enableViewportCulling", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction"]); // --------------------------------------------------------------------------
|
|
5399
5664
|
// Hooks & Context
|
|
5400
5665
|
// --------------------------------------------------------------------------
|
|
5401
5666
|
|
|
@@ -5420,9 +5685,9 @@
|
|
|
5420
5685
|
// Data Refs - 선택 및 Hover 상태 관리
|
|
5421
5686
|
// --------------------------------------------------------------------------
|
|
5422
5687
|
|
|
5423
|
-
/**
|
|
5688
|
+
/** data prop을 ref로 추적 (stale closure 방지, useEffect에서 동기화) */
|
|
5424
5689
|
|
|
5425
|
-
var markersRef = React.useRef(
|
|
5690
|
+
var markersRef = React.useRef(data); // --------------------------------------------------------------------------
|
|
5426
5691
|
// State Refs - 선택 및 Hover 상태 관리
|
|
5427
5692
|
// --------------------------------------------------------------------------
|
|
5428
5693
|
|
|
@@ -5594,6 +5859,7 @@
|
|
|
5594
5859
|
};
|
|
5595
5860
|
/**
|
|
5596
5861
|
* 마커 좌표 변환 결과를 캐시하고 반환
|
|
5862
|
+
*
|
|
5597
5863
|
* @param markerData 마커 데이터
|
|
5598
5864
|
* @returns 변환된 좌표 또는 null
|
|
5599
5865
|
*/
|
|
@@ -5673,7 +5939,7 @@
|
|
|
5673
5939
|
}
|
|
5674
5940
|
}
|
|
5675
5941
|
}; // --------------------------------------------------------------------------
|
|
5676
|
-
// 렌더링 함수
|
|
5942
|
+
// 렌더링 함수 결정 (dataType에 따라)
|
|
5677
5943
|
// --------------------------------------------------------------------------
|
|
5678
5944
|
|
|
5679
5945
|
/**
|
|
@@ -5688,6 +5954,18 @@
|
|
|
5688
5954
|
/** Base Layer에서 사용할 빈 Set (재사용) */
|
|
5689
5955
|
|
|
5690
5956
|
React.useRef(new Set());
|
|
5957
|
+
/**
|
|
5958
|
+
* 실제 사용할 렌더링 함수 결정
|
|
5959
|
+
* - MARKER: 외부에서 전달받은 renderBase 사용 (필수)
|
|
5960
|
+
* - POLYGON: renderer.ts의 팩토리 함수로 생성 (props 기반)
|
|
5961
|
+
*/
|
|
5962
|
+
|
|
5963
|
+
var renderBase = dataType === exports.CanvasDataType.MARKER ? props.renderBase : renderPolygonBase(props.baseFillColor, props.baseStrokeColor, props.baseLineWidth);
|
|
5964
|
+
var renderAnimation = dataType === exports.CanvasDataType.MARKER ? props.renderAnimation : undefined;
|
|
5965
|
+
var renderEvent = dataType === exports.CanvasDataType.MARKER ? props.renderEvent : function () {
|
|
5966
|
+
var polygonProps = props;
|
|
5967
|
+
return renderPolygonEvent(polygonProps.selectedFillColor, polygonProps.selectedStrokeColor, polygonProps.selectedLineWidth, polygonProps.activeFillColor, polygonProps.activeStrokeColor, polygonProps.activeLineWidth, polygonProps.hoveredFillColor, polygonProps.hoveredStrokeColor, polygonProps.hoveredLineWidth);
|
|
5968
|
+
}();
|
|
5691
5969
|
/**
|
|
5692
5970
|
* Base 레이어 렌더링 (뷰포트 컬링 적용, 선택된 마커 제외)
|
|
5693
5971
|
*
|
|
@@ -6052,11 +6330,11 @@
|
|
|
6052
6330
|
|
|
6053
6331
|
try {
|
|
6054
6332
|
var clickedOffset = controller.positionToOffset(event.param.position);
|
|
6055
|
-
var
|
|
6333
|
+
var data_1 = findData(clickedOffset);
|
|
6056
6334
|
|
|
6057
|
-
if (
|
|
6058
|
-
handleLocalClick(
|
|
6059
|
-
onClick(
|
|
6335
|
+
if (data_1) {
|
|
6336
|
+
handleLocalClick(data_1);
|
|
6337
|
+
onClick(data_1, selectedIdsRef.current);
|
|
6060
6338
|
}
|
|
6061
6339
|
} catch (error) {
|
|
6062
6340
|
console.error('[WoongKonvaMarker] handleClick error:', error);
|
|
@@ -6333,13 +6611,13 @@
|
|
|
6333
6611
|
|
|
6334
6612
|
doRenderEvent();
|
|
6335
6613
|
}, [externalSelectedItem]); // --------------------------------------------------------------------------
|
|
6336
|
-
// Lifecycle:
|
|
6614
|
+
// Lifecycle: 데이터 변경 시 렌더링
|
|
6337
6615
|
// --------------------------------------------------------------------------
|
|
6338
6616
|
|
|
6339
6617
|
React.useEffect(function () {
|
|
6340
6618
|
if (!stageRef.current) return; // markersRef 동기화
|
|
6341
6619
|
|
|
6342
|
-
markersRef.current =
|
|
6620
|
+
markersRef.current = data; // 데이터 변경 시 즉시 transform 제거 및 캐시 정리 (겹침 방지)
|
|
6343
6621
|
|
|
6344
6622
|
if (containerRef.current) {
|
|
6345
6623
|
containerRef.current.style.transform = '';
|
|
@@ -6356,18 +6634,18 @@
|
|
|
6356
6634
|
/**
|
|
6357
6635
|
* 선택 상태 동기화 (최적화 버전)
|
|
6358
6636
|
*
|
|
6359
|
-
*
|
|
6637
|
+
* data가 변경되면 selectedItemsMapRef도 업데이트 필요
|
|
6360
6638
|
* (참조가 바뀌므로 기존 Map의 데이터는 stale 상태)
|
|
6361
6639
|
*
|
|
6362
|
-
* 🔥 중요: 화면 밖
|
|
6363
|
-
* - 현재
|
|
6640
|
+
* 🔥 중요: 화면 밖 데이터도 선택 상태 유지!
|
|
6641
|
+
* - 현재 data에 있으면 최신 데이터로 업데이트
|
|
6364
6642
|
* - 없으면 기존 selectedItemsMapRef의 데이터 유지
|
|
6365
6643
|
*
|
|
6366
|
-
* 최적화:
|
|
6367
|
-
* - O(전체
|
|
6644
|
+
* 최적화: data를 Map으로 먼저 변환하여 find() 순회 제거
|
|
6645
|
+
* - O(전체 데이터 수 + 선택된 개수) - 매우 효율적
|
|
6368
6646
|
*/
|
|
6369
6647
|
|
|
6370
|
-
var markersMap = new Map(
|
|
6648
|
+
var markersMap = new Map(data.map(function (m) {
|
|
6371
6649
|
return [m.id, m];
|
|
6372
6650
|
}));
|
|
6373
6651
|
var newSelectedItemsMap = new Map();
|
|
@@ -6390,40 +6668,107 @@
|
|
|
6390
6668
|
selectedItemsMapRef.current = newSelectedItemsMap; // 즉시 렌더링
|
|
6391
6669
|
|
|
6392
6670
|
renderAllImmediate();
|
|
6393
|
-
}, [
|
|
6671
|
+
}, [data]);
|
|
6394
6672
|
return reactDom.createPortal(React__default["default"].createElement("div", {
|
|
6395
6673
|
ref: containerRef,
|
|
6396
|
-
style:
|
|
6674
|
+
style: {
|
|
6397
6675
|
position: 'absolute',
|
|
6398
6676
|
width: '100%',
|
|
6399
6677
|
height: '100%'
|
|
6400
|
-
}
|
|
6401
|
-
pointerEvents: 'none'
|
|
6402
|
-
})
|
|
6678
|
+
}
|
|
6403
6679
|
}), divElement);
|
|
6404
6680
|
};
|
|
6405
6681
|
/**
|
|
6406
|
-
*
|
|
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
|
+
* ```
|
|
6407
6725
|
*
|
|
6408
|
-
*
|
|
6409
|
-
*
|
|
6410
|
-
*
|
|
6726
|
+
* ## 📊 데이터 형식
|
|
6727
|
+
* ```typescript
|
|
6728
|
+
* const data: KonvaCanvasMarkerData<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
|
+
* ```
|
|
6411
6742
|
*
|
|
6412
|
-
*
|
|
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} 전체 문서
|
|
6413
6758
|
*/
|
|
6414
6759
|
|
|
6415
6760
|
|
|
6416
|
-
var
|
|
6417
|
-
// 1.
|
|
6418
|
-
var
|
|
6419
|
-
var
|
|
6761
|
+
var WoongCanvasLayer = React__default["default"].memo(WoongCanvasLayerComponent, function (prevProps, nextProps) {
|
|
6762
|
+
// 1. data 비교
|
|
6763
|
+
var prevData = prevProps.data;
|
|
6764
|
+
var nextData = nextProps.data; // 참조가 같으면 스킵
|
|
6420
6765
|
|
|
6421
|
-
if (
|
|
6766
|
+
if (prevData !== nextData) {
|
|
6422
6767
|
// 길이가 다르면 변경됨
|
|
6423
|
-
if (
|
|
6768
|
+
if (prevData.length !== nextData.length) return false; // 각 데이터의 ID 비교
|
|
6424
6769
|
|
|
6425
|
-
for (var i = 0; i <
|
|
6426
|
-
if (
|
|
6770
|
+
for (var i = 0; i < prevData.length; i++) {
|
|
6771
|
+
if (prevData[i].id !== nextData[i].id) {
|
|
6427
6772
|
return false; // 변경됨 → 리렌더링
|
|
6428
6773
|
}
|
|
6429
6774
|
}
|
|
@@ -6438,18 +6783,6 @@
|
|
|
6438
6783
|
return false; // 변경됨 → 리렌더링
|
|
6439
6784
|
}
|
|
6440
6785
|
|
|
6441
|
-
if (prevProps.onClick !== nextProps.onClick) {
|
|
6442
|
-
return false; // 변경됨 → 리렌더링
|
|
6443
|
-
}
|
|
6444
|
-
|
|
6445
|
-
if (prevProps.onMouseOver !== nextProps.onMouseOver) {
|
|
6446
|
-
return false; // 변경됨 → 리렌더링
|
|
6447
|
-
}
|
|
6448
|
-
|
|
6449
|
-
if (prevProps.onMouseOut !== nextProps.onMouseOut) {
|
|
6450
|
-
return false; // 변경됨 → 리렌더링
|
|
6451
|
-
}
|
|
6452
|
-
|
|
6453
6786
|
if (prevProps.disableInteraction !== nextProps.disableInteraction) {
|
|
6454
6787
|
return false; // 변경됨 → 리렌더링
|
|
6455
6788
|
}
|
|
@@ -7197,20 +7530,54 @@
|
|
|
7197
7530
|
}
|
|
7198
7531
|
};
|
|
7199
7532
|
|
|
7200
|
-
NaverMintMapController.prototype.
|
|
7533
|
+
NaverMintMapController.prototype.getCurrentZIndex = function (marker) {
|
|
7201
7534
|
if (this.map && marker.element && marker.element instanceof HTMLElement) {
|
|
7202
7535
|
var parent_1 = marker.element.parentElement;
|
|
7203
7536
|
|
|
7204
|
-
if (parent_1) {
|
|
7205
|
-
|
|
7537
|
+
if (parent_1 && parent_1.style.zIndex) {
|
|
7538
|
+
var zIndex = Number(parent_1.style.zIndex);
|
|
7539
|
+
return isNaN(zIndex) ? undefined : zIndex;
|
|
7540
|
+
}
|
|
7541
|
+
}
|
|
7542
|
+
|
|
7543
|
+
return undefined;
|
|
7544
|
+
};
|
|
7545
|
+
|
|
7546
|
+
NaverMintMapController.prototype.setMarkerZIndex = function (marker, zIndex) {
|
|
7547
|
+
if (this.map && marker.element && marker.element instanceof HTMLElement) {
|
|
7548
|
+
var parent_2 = marker.element.parentElement;
|
|
7549
|
+
|
|
7550
|
+
if (parent_2) {
|
|
7551
|
+
parent_2.style.zIndex = String(zIndex);
|
|
7206
7552
|
}
|
|
7207
7553
|
}
|
|
7208
7554
|
};
|
|
7209
7555
|
|
|
7210
7556
|
NaverMintMapController.prototype.markerToTheTop = function (marker) {
|
|
7557
|
+
// 이미 최상위로 올라간 상태면 (원래 zIndex가 이미 저장됨) 중복 실행 방지
|
|
7558
|
+
if (this.markerOriginalZIndex !== undefined) {
|
|
7559
|
+
return;
|
|
7560
|
+
}
|
|
7561
|
+
|
|
7562
|
+
var currentZIndex = this.getCurrentZIndex(marker); // undefined면 null로 저장 (원래 zIndex가 없었음을 표시)
|
|
7563
|
+
|
|
7564
|
+
this.markerOriginalZIndex = currentZIndex !== undefined ? currentZIndex : null;
|
|
7211
7565
|
this.setMarkerZIndex(marker, this.getMaxZIndex(1));
|
|
7212
7566
|
};
|
|
7213
7567
|
|
|
7568
|
+
NaverMintMapController.prototype.restoreMarkerZIndex = function (marker) {
|
|
7569
|
+
if (this.markerOriginalZIndex !== undefined) {
|
|
7570
|
+
if (this.markerOriginalZIndex === null) {
|
|
7571
|
+
// 원래 zIndex가 없었으면 제거 (또는 초기값 0으로)
|
|
7572
|
+
this.setMarkerZIndex(marker, 0);
|
|
7573
|
+
} else {
|
|
7574
|
+
this.setMarkerZIndex(marker, this.markerOriginalZIndex);
|
|
7575
|
+
}
|
|
7576
|
+
|
|
7577
|
+
this.markerOriginalZIndex = undefined;
|
|
7578
|
+
}
|
|
7579
|
+
};
|
|
7580
|
+
|
|
7214
7581
|
NaverMintMapController.prototype.clearDrawable = function (drawable) {
|
|
7215
7582
|
var _a;
|
|
7216
7583
|
|
|
@@ -7965,6 +8332,10 @@
|
|
|
7965
8332
|
}
|
|
7966
8333
|
};
|
|
7967
8334
|
|
|
8335
|
+
GoogleMintMapController.prototype.restoreMarkerZIndex = function (marker) {// Google Maps에서는 restoreMarkerZIndex 기능을 지원하지 않습니다.
|
|
8336
|
+
// 이 기능은 Naver Maps에서만 사용 가능합니다.
|
|
8337
|
+
};
|
|
8338
|
+
|
|
7968
8339
|
GoogleMintMapController.prototype.clearDrawable = function (drawable) {
|
|
7969
8340
|
if (drawable && drawable.native) {
|
|
7970
8341
|
if (drawable.native instanceof google.maps.Marker || drawable.native instanceof google.maps.Polygon || drawable.native instanceof google.maps.Polyline) {
|
|
@@ -8687,6 +9058,10 @@
|
|
|
8687
9058
|
}
|
|
8688
9059
|
};
|
|
8689
9060
|
|
|
9061
|
+
KakaoMintMapController.prototype.restoreMarkerZIndex = function (marker) {// Kakao Maps에서는 restoreMarkerZIndex 기능을 지원하지 않습니다.
|
|
9062
|
+
// 이 기능은 Naver Maps에서만 사용 가능합니다.
|
|
9063
|
+
};
|
|
9064
|
+
|
|
8690
9065
|
KakaoMintMapController.prototype.clearDrawable = function (drawable) {
|
|
8691
9066
|
var _this = this;
|
|
8692
9067
|
|
|
@@ -9290,11 +9665,13 @@
|
|
|
9290
9665
|
exports.Spacing = Spacing;
|
|
9291
9666
|
exports.SpatialHashGrid = SpatialHashGrid;
|
|
9292
9667
|
exports.Status = Status;
|
|
9293
|
-
exports.
|
|
9668
|
+
exports.WoongCanvasLayer = WoongCanvasLayer;
|
|
9669
|
+
exports.calculateTextBoxWidth = calculateTextBoxWidth;
|
|
9294
9670
|
exports.computeMarkerOffset = computeMarkerOffset;
|
|
9295
9671
|
exports.computePolygonOffsets = computePolygonOffsets;
|
|
9296
9672
|
exports.getClusterInfo = getClusterInfo;
|
|
9297
9673
|
exports.getMapOfType = getMapOfType;
|
|
9674
|
+
exports.hexToRgba = hexToRgba;
|
|
9298
9675
|
exports.isPointInMarkerData = isPointInMarkerData;
|
|
9299
9676
|
exports.isPointInPolygon = isPointInPolygon;
|
|
9300
9677
|
exports.isPointInPolygonData = isPointInPolygonData;
|