@wenle_2523097/agri-map 2.0.2 → 2.0.3

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.
@@ -5090,6 +5090,148 @@ var ClusterView = function ClusterView(_ref) {
5090
5090
  };
5091
5091
  var ClusterView$1 = /*#__PURE__*/React.memo(ClusterView);
5092
5092
 
5093
+ var DEFAULT_LABEL_CONFIG = {
5094
+ show: false,
5095
+ field: 'title',
5096
+ color: '#2c3e50',
5097
+ fontSize: 14,
5098
+ fontWeight: 'bold',
5099
+ offset: [0, 40],
5100
+ className: '',
5101
+ animation: false,
5102
+ animationDuration: 2
5103
+ };
5104
+ /**
5105
+ * Label3D - 3D 立体文字标签组件
5106
+ * 使用原生 Leaflet SVG 渲染,支持竖排立体字效果
5107
+ */
5108
+ var Label3D = function Label3D(_ref) {
5109
+ var labelConfig = _ref.labelConfig,
5110
+ _ref$labelField = _ref.labelField,
5111
+ labelField = _ref$labelField === void 0 ? 'title' : _ref$labelField,
5112
+ data = _ref.data;
5113
+ var map = useMap();
5114
+ var markersRef = useRef([]);
5115
+ var retryRafRef = useRef(null);
5116
+ // 合并配置
5117
+ var config = useMemo(function () {
5118
+ return _objectSpread2(_objectSpread2({}, DEFAULT_LABEL_CONFIG), labelConfig);
5119
+ }, [labelConfig]);
5120
+ // 获取标签文本
5121
+ var getLabelText = useCallback(function (item) {
5122
+ var field = config.field || labelField;
5123
+ var value = item[field];
5124
+ if (!value && value !== 0) return null;
5125
+ return String(value);
5126
+ }, [config.field, labelField]);
5127
+ // 创建标签
5128
+ var createLabels = useCallback(function () {
5129
+ // 清理旧的标签
5130
+ markersRef.current.forEach(function (marker) {
5131
+ return marker.remove();
5132
+ });
5133
+ markersRef.current = [];
5134
+ if (!map || !config.show || !(data !== null && data !== void 0 && data.length)) return;
5135
+ // 过滤有效数据并获取标签文本
5136
+ var labelsToCreate = data.map(function (item) {
5137
+ return {
5138
+ item: item,
5139
+ text: getLabelText(item)
5140
+ };
5141
+ }).filter(function (label) {
5142
+ return label.text;
5143
+ });
5144
+ if (labelsToCreate.length === 0) return;
5145
+ // 创建标签
5146
+ labelsToCreate.forEach(function (_ref2) {
5147
+ var item = _ref2.item,
5148
+ text = _ref2.text;
5149
+ var _config$offset = _slicedToArray(config.offset, 2),
5150
+ offsetX = _config$offset[0],
5151
+ offsetY = _config$offset[1];
5152
+ // 处理颜色(支持单色或渐变数组)
5153
+ var isGradient = Array.isArray(config.color);
5154
+ var gradientColors = isGradient ? config.color : [config.color];
5155
+ var firstColor = gradientColors[0];
5156
+ // 动画样式
5157
+ var getAnimationClass = function getAnimationClass() {
5158
+ if (config.animation === 'pulse') return 'label-animated-pulse';
5159
+ if (config.animation === 'gradient') return 'label-animated-gradient';
5160
+ if (config.animation === 'scale') return 'label-animated-scale';
5161
+ if (config.animation === 'flip') return 'label-animated-flip';
5162
+ if (config.animation === 'flicker') return 'label-animated-flicker';
5163
+ if (config.animation === 'rotate') return 'label-animated-rotate';
5164
+ if (config.animation === 'wobble') return 'label-animated-wobble';
5165
+ if (config.animation === 'bounce') return 'label-animated-bounce';
5166
+ if (config.animation === 'float') return 'label-animated-float';
5167
+ if (config.animation === 'neon') return 'label-animated-neon';
5168
+ if (config.animation === 'rainbow') return 'label-animated-rainbow';
5169
+ if (config.animation === 'shadow') return 'label-animated-shadow';
5170
+ return '';
5171
+ };
5172
+ var isShadow = config.animation === 'shadow';
5173
+ var animationDurationVar = config.animation ? "--label-animation-duration: ".concat(config.animationDuration, "s;") : '';
5174
+ // 渐变颜色 CSS 变量
5175
+ var gradientColorsVar = isGradient && config.animation === 'gradient' ? "--label-gradient-colors: ".concat(gradientColors.join(', '), ";") : '';
5176
+ // 竖起立体字样式 - 参照 CSND 示例的 transform 效果
5177
+ var labelHtml = "\n <div class=\"marker-label-3d ".concat(config.className, " ").concat(getAnimationClass(), "\" style=\"\n position: relative;\n display: inline-block;\n transform: translate(-50%, 0);\n font-size: ").concat(config.fontSize, "px;\n font-weight: bold;\n color: ").concat(firstColor, ";\n letter-spacing: 3px;\n margin: 0;\n ").concat(animationDurationVar, "\n ").concat(gradientColorsVar, "\n ").concat(isShadow ? '' : "\n text-shadow:\n -1px 0 0 #000,\n -2px 0 0 #000,\n -3px 0 0 #000,\n -4px 0 0 #000,\n -5px 0 0 #000;\n ", "\n \">").concat(text, "\n <span class=\"").concat(isShadow ? 'label-shadow-anim' : '', "\" style=\"\n position: absolute;\n top: 0;\n left: 0;\n color: #000;\n font-weight: bolder;\n transform: translateX(-15px) translateY(4px) scaleY(.5) skew(55deg);\n z-index: -1;\n filter: blur(1px);\n mask: linear-gradient(transparent, #000);\n pointer-events: none;\n ").concat(isShadow ? "animation: label-shadow-move var(--label-animation-duration, 2s) ease-in-out infinite;" : '', "\n \">").concat(text, "</span>\n </div>\n ");
5178
+ var labelIcon = L.divIcon({
5179
+ className: 'marker-label-container',
5180
+ html: labelHtml,
5181
+ iconSize: [100, 100],
5182
+ iconAnchor: [50 + offsetX, offsetY]
5183
+ });
5184
+ // item.position 格式为 [lat, lng]
5185
+ var marker = L.marker(item.position, {
5186
+ icon: labelIcon,
5187
+ interactive: false,
5188
+ zIndexOffset: 1000
5189
+ }).addTo(map);
5190
+ markersRef.current.push(marker);
5191
+ });
5192
+ }, [map, config, data, getLabelText]);
5193
+ // 初始化创建标签(带 RAF 重试)
5194
+ useEffect(function () {
5195
+ if (!map) {
5196
+ // 地图未准备好,延迟重试
5197
+ retryRafRef.current = requestAnimationFrame(function () {
5198
+ createLabels();
5199
+ });
5200
+ return;
5201
+ }
5202
+ createLabels();
5203
+ return function () {
5204
+ if (retryRafRef.current) {
5205
+ cancelAnimationFrame(retryRafRef.current);
5206
+ retryRafRef.current = null;
5207
+ }
5208
+ };
5209
+ }, [map, createLabels]);
5210
+ // 清理
5211
+ useEffect(function () {
5212
+ return function () {
5213
+ markersRef.current.forEach(function (marker) {
5214
+ return marker.remove();
5215
+ });
5216
+ markersRef.current = [];
5217
+ };
5218
+ }, []);
5219
+ // 地图移动/缩放时重建标签
5220
+ useEffect(function () {
5221
+ if (!map || !config.show) return;
5222
+ var handleMapChange = function handleMapChange() {
5223
+ createLabels();
5224
+ };
5225
+ map.on('moveend', handleMapChange);
5226
+ map.on('zoomend', handleMapChange);
5227
+ return function () {
5228
+ map.off('moveend', handleMapChange);
5229
+ map.off('zoomend', handleMapChange);
5230
+ };
5231
+ }, [map, config.show, createLabels]);
5232
+ return null;
5233
+ };
5234
+
5093
5235
  /**
5094
5236
  * 保持 ref 始终指向最新值的 Hook
5095
5237
  * @description 用于在回调中访问最新值,避免闭包陷阱
@@ -8837,6 +8979,7 @@ var Marker = /*#__PURE__*/forwardRef(function (_ref2, ref) {
8837
8979
  displayMode = _ref2.displayMode,
8838
8980
  onClusterClick = _ref2.onClusterClick,
8839
8981
  onRow = _ref2.onRow,
8982
+ label = _ref2.label,
8840
8983
  _ref2$loading = _ref2.loading,
8841
8984
  loading = _ref2$loading === void 0 ? false : _ref2$loading,
8842
8985
  loadingMask = _ref2.loadingMask,
@@ -9339,6 +9482,10 @@ var Marker = /*#__PURE__*/forwardRef(function (_ref2, ref) {
9339
9482
  onCancel: edit.handleCancel,
9340
9483
  onSave: edit.handleSave,
9341
9484
  children: customToolbar
9485
+ }), jsx(Label3D, {
9486
+ labelConfig: label,
9487
+ data: normalizedData,
9488
+ selectedId: value
9342
9489
  }), loadingOverlay]
9343
9490
  });
9344
9491
  });