13404089107
2026-04-16 23efbd347b2d3be3fc624b4ba0632c0ab92ee1d8
feat(路线选择): 增加地图点击选路和路线气泡展示

- 新增 `saveRoutePreference` API 用于保存路线偏好
- 为 `BeginRouteView` 组件添加 `onMapTap` 属性,支持地图点击选路
- 在 `use-route-manager` 中实现 `handleMapTap` 逻辑,作为 `handlePolylineTap` 的降级方案
- 在路线中点添加路线摘要气泡,显示时长和距离信息
- 在 `release-route` 组件中同步路线偏好选择,并展示"运营免费"标签
- 优化路线索引解析逻辑,提高点击匹配精度
10个文件已修改
320 ■■■■■ 已修改文件
src/robotaxi/api/begin-route.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/begin-route-view.tsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/css-folder/release-route.less 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/release-route.tsx 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/route-preference-popup/index.tsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/hooks/use-order-actions.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/hooks/use-route-manager.ts 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/hooks/use-view-delegates.tsx 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/index.less 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/index.tsx 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/api/begin-route.ts
@@ -19,6 +19,15 @@
    }, true);
}
// 导航-设置路线偏好
export const saveRoutePreference = async (payload) => {
    return request({
        url: _ROBOTAXI_HOST + '/itinerary/base/v1/mini-program/navigation/route-preference',
        method: 'POST',
        payload
    }, true);
}
// 保存订单
export const saveOrder = async (payload) => {
    return request({
src/robotaxi/pages/begin-route/components/begin-route-view.tsx
@@ -20,6 +20,7 @@
  handleCalloutTap: (e: any) => void;
  handleRegionChange: (e: any) => void;
  onPolylineTap?: (e: any) => void;
  onMapTap?: (e: any) => void;
  renderMapOverlays: () => JSX.Element;
  toBack: () => void;
  backIcon: string;
@@ -79,6 +80,7 @@
    handleCalloutTap,
    handleRegionChange,
    onPolylineTap,
    onMapTap,
    renderMapOverlays,
    toBack,
    backIcon,
@@ -139,6 +141,7 @@
        onCalloutTap={handleCalloutTap}
        onRegionChange={handleRegionChange}
        onPolylineTap={onPolylineTap}
        onTap={onMapTap}
        style={{ width: '100%', height: '87vh' }}
      >
        {renderMapOverlays()}
src/robotaxi/pages/begin-route/components/css-folder/release-route.less
@@ -306,6 +306,12 @@
        .money-box {
            margin-top: 8px;
            .route-operate-free {
                font-size: 28px;
                line-height: 40px;
                color: #F58900;
            }
            .route-content-top-money {
                display: flex;
                align-items: center;
@@ -392,4 +398,4 @@
            background: rgba(255, 255, 255, 0.4);
        }
    }
}
}
src/robotaxi/pages/begin-route/components/release-route.tsx
@@ -8,6 +8,7 @@
import selectLineIcon from '../../../assets/select-line.png'
import trafficSignalIcon from '../../../assets/traffic-signal.png'
import RoutePreferencePopup, { RoutePreferenceOption } from './route-preference-popup';
import { saveRoutePreference, queryRoutePreferences } from '../../../api/begin-route';
import { formatDurationDisplay, formatTripDistance } from '../../../../utils/Robotaxi-public-method';
type Props = {
@@ -36,8 +37,66 @@
    const pendingHeight = useRef<number | null>(null);
    const [showPreferencePopup, setShowPreferencePopup] = useState(false);
    const [preference, setPreference] = useState<RoutePreferenceOption>({ label: '智能推荐', value: '智能推荐' });
    const [preference, setPreference] = useState<RoutePreferenceOption>({ label: '智能推荐', value: '智能推荐', code: '智能推荐' });
    const [preferenceOptions, setPreferenceOptions] = useState<RoutePreferenceOption[]>([]);
    const openCityId = Number(Taro.getStorageSync('selectedCity')?.id || 0);
    const selectedRoute = routeOptions?.[selectedRouteIndex];
    const isOperateFree = Number(selectedRoute?.operateFree) === 1;
    useEffect(() => {
        let cancelled = false;
        queryRoutePreferences({ openCityId }).then((res: any) => {
            if (cancelled) return;
            const list = Array.isArray(res) ? res : (Array.isArray(res?.list) ? res.list : (Array.isArray(res?.data) ? res.data : []));
            const normalized = list.map((item: any) => {
                const label = item?.label || item?.name || item?.displayName || item?.preferenceName || item?.value;
                const value = item?.value ?? item?.code ?? item?.preferenceCode ?? label;
                const code = item?.code ?? item?.preferenceCode ?? item?.value ?? label;
                if (!label || value === undefined || value === null) return null;
                return { label: String(label), value: String(value), code: String(code) };
            }).filter(Boolean) as RoutePreferenceOption[];
            if (normalized.length > 0) {
                setPreferenceOptions(normalized);
            }
        }).catch(() => {});
        return () => { cancelled = true; };
    }, [openCityId]);
    // Sync preference label when route selection changes externally (e.g. clicking map or route card)
    useEffect(() => {
        if (routeOptions && routeOptions[selectedRouteIndex]) {
            const currentRoute = routeOptions[selectedRouteIndex];
            // Match label based on preference from API response
            let mappedLabel = '智能推荐';
            if (preferenceOptions.length > 0 && currentRoute.preference !== undefined && currentRoute.preference !== null) {
                const matchedOption = preferenceOptions.find(opt => String(opt.code) === String(currentRoute.preference));
                if (matchedOption) {
                    mappedLabel = matchedOption.label;
                } else if (currentRoute.routePlanName) {
                    // Fallback to routePlanName if preference matching fails
                    const name = currentRoute.routePlanName;
                    mappedLabel = name.includes('-') ? name.split('-')[1] : name;
                }
            } else if (currentRoute.routePlanName) {
                // Fallback to routePlanName if preference matching fails
                const name = currentRoute.routePlanName;
                mappedLabel = name.includes('-') ? name.split('-')[1] : name;
            }
            setPreference(prev => {
                if (prev.label !== mappedLabel) {
                    const newCode = currentRoute.preference !== undefined && currentRoute.preference !== null ? String(currentRoute.preference) : mappedLabel;
                    return {
                        label: mappedLabel,
                        value: newCode,
                        code: newCode
                    };
                }
                return prev;
            });
        }
    }, [selectedRouteIndex, routeOptions, preferenceOptions]);
    useEffect(() => {
        if (!isRouteSelectExpanded && boxHeight !== null && minHeight.current > 0) {
@@ -154,6 +213,41 @@
        }
        return `${safeMinutes}分钟`;
    }
    const handleSelectPreference = async (item: RoutePreferenceOption) => {
        setPreference(item);
        if (routeOptions && routeOptions.length > 0 && handleSelectRoute) {
            const targetIndex = routeOptions.findIndex(route => {
                // Exact match by preference code
                if (route.preference !== undefined && route.preference !== null && String(route.preference) === String(item.code)) {
                    return true;
                }
                // Fallback match by name
                if (route.routePlanName) {
                    const name = route.routePlanName;
                    const mappedLabel = name.includes('-') ? name.split('-')[1] : name;
                    if (mappedLabel === item.label) {
                        return true;
                    }
                }
                return false;
            });
            if (targetIndex !== -1) {
                handleSelectRoute(targetIndex);
            }
        }
        try {
            await saveRoutePreference({
                code: item.code
            });
        } catch (error) {
            // keep local selection state to avoid interrupting the popup interaction
        }
    }
    return (
        <View className="release-route-container">
@@ -260,12 +354,16 @@
                </View>
                <View className="confirm-btn-box">
                    <View className="money-box">
                        <View className="route-content-top-money" onClick={() => toPriceDescription()} >
                            <Image className="tip-icon" src={tipDefaultIcon} />
                            预估
                            <Text className="money-num">{fareEstimate.finalFareStr || '-'}</Text>
                            元
                        </View>
                        {isOperateFree ? (
                            <View className="route-operate-free">运营免费</View>
                        ) : (
                            <View className="route-content-top-money" onClick={() => toPriceDescription()} >
                                <Image className="tip-icon" src={tipDefaultIcon} />
                                预估
                                <Text className="money-num">{fareEstimate.finalFareStr || '-'}</Text>
                                元
                            </View>
                        )}
                        <View className="route-content-bottom-right">
                            {
                                fareEstimate.discountAmount > 0 &&
@@ -288,7 +386,7 @@
                value={preference.value}
                openCityId={openCityId}
                onClose={() => setShowPreferencePopup(false)}
                onSelect={(item) => setPreference(item)}
                onSelect={handleSelectPreference}
            />
        </View>
    )
src/robotaxi/pages/begin-route/components/route-preference-popup/index.tsx
@@ -9,6 +9,7 @@
export type RoutePreferenceOption = {
  label: string;
  value: string;
  code: string;
};
type Props = {
@@ -20,9 +21,9 @@
};
const DEFAULT_OPTIONS: RoutePreferenceOption[] = [
  { label: '智能推荐', value: '智能推荐' },
  { label: '时间优先', value: '时间优先' },
  { label: '低价优先', value: '低价优先' }
  { label: '智能推荐', value: '智能推荐', code: '智能推荐' },
  { label: '时间优先', value: '时间优先', code: '时间优先' },
  { label: '低价优先', value: '低价优先', code: '低价优先' }
];
const normalizeOptions = (res: any): RoutePreferenceOption[] => {
@@ -41,12 +42,14 @@
  const normalized = list.map((item: any) => {
    const label = item?.label || item?.name || item?.displayName || item?.preferenceName || item?.value;
    const value = item?.value ?? item?.code ?? item?.preferenceCode ?? label;
    const code = item?.code ?? item?.preferenceCode ?? item?.value ?? label;
    if (!label || value === undefined || value === null) {
      return null;
    }
    return {
      label: String(label),
      value: String(value)
      value: String(value),
      code: String(code)
    };
  }).filter(Boolean) as RoutePreferenceOption[];
src/robotaxi/pages/begin-route/hooks/use-order-actions.ts
@@ -15,6 +15,10 @@
  startSite: any;
  /** 费用信息 */
  fareEstimate: any;
  /** 路线备选项 */
  routeOptions?: any[];
  /** 选中的路线索引 */
  selectedRouteIndex?: number;
  /** 路线错误标记 */
  routeAndFareError: boolean;
  /** 下单提交中 */
@@ -79,6 +83,15 @@
      xpElectronicFenceAreaId: s?.electronicAreaId || deps.endSite?.electronicAreaId || '',
      estimatedTime
    };
    // Add selectedRouteId if available
    if (deps.routeOptions && typeof deps.selectedRouteIndex === 'number') {
      const selectedRoute = deps.routeOptions[deps.selectedRouteIndex];
      if (selectedRoute?.route?.routeID) {
        payload.selectedRouteId = selectedRoute.route.routeID;
      }
    }
    if (cachedCouponId) payload.userCouponId = cachedCouponId;
    const res = await saveOrder(payload);
    const status_code = res?.orderId ? 1 : 0;
src/robotaxi/pages/begin-route/hooks/use-route-manager.ts
@@ -217,7 +217,7 @@
        newEndLng = routeData.destination.longitude ?? newEndLng;
    }
    if (newStartLat && newStartLng && typeof deps.setStartSite === 'function') {
    if (Number.isFinite(newStartLat) && Number.isFinite(newStartLng) && typeof deps.setStartSite === 'function') {
        deps.setStartSite({
           ...deps.startSite,
           latitude: newStartLat,
@@ -226,7 +226,7 @@
        });
    }
    if (newEndLat && newEndLng && typeof deps.setEndSite === 'function') {
    if (Number.isFinite(newEndLat) && Number.isFinite(newEndLng) && typeof deps.setEndSite === 'function') {
        deps.setEndSite({
           ...deps.endSite,
           latitude: newEndLat,
@@ -269,11 +269,9 @@
    }
  };
  // 处理地图上的 polyline 点击事件
  const handlePolylineTap = (e: any) => {
    console.log('handlePolylineTap/////////////', e);
  const resolveRouteIndexByTap = (e: any) => {
    // 确保当前处于发单状态(有路线选项),并且有路线可供选择
    if (deps.tripStatusRef.current !== 1 || allRoutePoints.length <= 1) return;
    if (deps.tripStatusRef.current !== 1 || allRoutePoints.length <= 1) return -1;
    // 优先使用 polylineId;如果运行时未返回 id,则退化为用点击坐标匹配最近路线
    let targetIndex = -1;
@@ -294,7 +292,7 @@
    if (targetIndex === -1) {
      const tapLatitude = Number(e?.detail?.latitude ?? e?.latitude);
      const tapLongitude = Number(e?.detail?.longitude ?? e?.longitude);
      if (!Number.isFinite(tapLatitude) || !Number.isFinite(tapLongitude)) return;
      if (!Number.isFinite(tapLatitude) || !Number.isFinite(tapLongitude)) return -1;
      let nearestDistance = Infinity;
      allRoutePoints.forEach((routeLine, index) => {
@@ -314,9 +312,23 @@
        });
      });
      if (nearestDistance > 80) return;
      if (nearestDistance > 120) return -1;
    }
    return targetIndex;
  };
  // 处理地图上的 polyline 点击事件
  const handlePolylineTap = (e: any) => {
    const targetIndex = resolveRouteIndexByTap(e);
    if (targetIndex >= 0 && targetIndex < allRoutePoints.length) {
      handleSelectRoute(targetIndex);
    }
  };
  // 某些端上浅色路线不会触发 polyline tap,退化为地图点击后按最近路线匹配
  const handleMapTap = (e: any) => {
    const targetIndex = resolveRouteIndexByTap(e);
    if (targetIndex >= 0 && targetIndex < allRoutePoints.length) {
      handleSelectRoute(targetIndex);
    }
@@ -549,6 +561,7 @@
            points: reducePoints(points, deps.isAndroid ? 120 : 200),
            color: '#C2CAF1',
            width: 10,
            clickable: true,
            dottedLine: false,
            arrowLine: true,
          });
@@ -562,6 +575,7 @@
          points: displayRoutePoints, // 选中的路线使用已经降采样处理过的点
          color: '#7B91FF',
          width: 10,
          clickable: true,
          dottedLine: false,
          arrowLine: true,
        });
@@ -573,6 +587,7 @@
        points: displayRoutePoints,
        color: '#7B91FF',
        width: 10,
        clickable: true,
        dottedLine: false,
        arrowLine: true,
      });
@@ -621,6 +636,7 @@
    selectedRouteIndex,
    handleSelectRoute,
    handlePolylineTap,
    handleMapTap,
    fareEstimate,
    setFareEstimate,
    routeAndFareError,
src/robotaxi/pages/begin-route/hooks/use-view-delegates.tsx
@@ -102,6 +102,9 @@
export default function useViewDelegates(deps: Deps) {
  /** 时长文案 */
  const durationDisplay = formatDurationDisplay(deps.routeDuration);
  const routeSummaryText = deps.routeDistance && deps.routeDuration !== null
    ? `${durationDisplay.value}${durationDisplay.unit} ${deps.routeDistance.value}${deps.routeDistance.unit === 'm' ? '米' : '公里'}`
    : '';
  /**
   * 渲染等待态气泡。
@@ -123,27 +126,40 @@
   */
  const renderDefaultCallout = (item: any, calloutKey: string) => (
    <CoverView slot='callout' marker-id={item.id} key={calloutKey} className='custom-callout'>
      {(item.name !== '车辆位置' && !(item.id === 2 && [7].includes(deps.tripStatus))) && (
        <CoverView className={`custom-callout-content ${deps.isAndroid && 'txt-center '}`} style={{ zIndex: 1 }}>
          <CoverView style={{ lineHeight: '22px', display: 'flex', alignItems: 'center' }}>{item.name}</CoverView>
          {deps.isAndroid && <CoverView style={{ width: '2px' }}></CoverView>}
          {deps.tripStatus == 1 && <CoverImage className='custom-callout-icon' src={deps.customCalloutIconSrc} />}
        </CoverView>
      )}
      {(item.name === '车辆位置' && [4, 6].includes(deps.tripStatus) && !deps.isAndroid) && (
        <CoverView className='custom-callout-content' style={{ padding: '6px 10px', minWidth: '40px', justifyContent: 'center', zIndex: 2 }}>
          <CoverView className='car-time'>
            <CoverView className='car-time-num'>{deps.routeDistance?.value ?? 0}</CoverView>
            <CoverView>{deps.routeDistance?.unit === 'm' ? '米' : '公里'}</CoverView>
            <CoverView style={{ marginLeft: '2.5px' }} className='car-time-num'>{durationDisplay.value}</CoverView>
            <CoverView>{durationDisplay.unit}</CoverView>
      {item.isRouteSummaryBubble ? (
        routeSummaryText ? (
          <CoverView className='route-summary-callout'>
            <CoverView className='route-summary-callout-bubble'>
              {routeSummaryText}
            </CoverView>
            <CoverView className='route-summary-callout-arrow' />
          </CoverView>
        </CoverView>
      )}
      {(item.id === 2 && [7].includes(deps.tripStatus) && !deps.isAndroid && deps.mapScale >= 20) && (
        <CoverView className='custom-callout-content'>
          已到达
        </CoverView>
        ) : null
      ) : (
        <>
          {(item.name !== '车辆位置' && !(item.id === 2 && [7].includes(deps.tripStatus))) && (
            <CoverView className={`custom-callout-content ${deps.isAndroid && 'txt-center '}`} style={{ zIndex: 1 }}>
              <CoverView style={{ lineHeight: '22px', display: 'flex', alignItems: 'center' }}>{item.name}</CoverView>
              {deps.isAndroid && <CoverView style={{ width: '2px' }}></CoverView>}
              {deps.tripStatus == 1 && <CoverImage className='custom-callout-icon' src={deps.customCalloutIconSrc} />}
            </CoverView>
          )}
          {(item.name === '车辆位置' && [4, 6].includes(deps.tripStatus) && !deps.isAndroid) && (
            <CoverView className='custom-callout-content' style={{ padding: '6px 10px', minWidth: '40px', justifyContent: 'center', zIndex: 2 }}>
              <CoverView className='car-time'>
                <CoverView className='car-time-num'>{deps.routeDistance?.value ?? 0}</CoverView>
                <CoverView>{deps.routeDistance?.unit === 'm' ? '米' : '公里'}</CoverView>
                <CoverView style={{ marginLeft: '2.5px' }} className='car-time-num'>{durationDisplay.value}</CoverView>
                <CoverView>{durationDisplay.unit}</CoverView>
              </CoverView>
            </CoverView>
          )}
          {(item.id === 2 && [7].includes(deps.tripStatus) && !deps.isAndroid && deps.mapScale >= 20) && (
            <CoverView className='custom-callout-content'>
              已到达
            </CoverView>
          )}
        </>
      )}
    </CoverView>
  );
@@ -153,6 +169,7 @@
   */
  const renderMarkerCallout = (item: any, index: number) => {
    const calloutKey = `callout-${item.id}-${item.name || ''}`;
    if (item.isRouteSummaryBubble) return renderDefaultCallout(item, calloutKey);
    const isWaiting = [2, 3].includes(deps.tripStatus) && index === 0;
    if (isWaiting) return renderWaitingCallout(item, calloutKey);
    if (item.name === '车辆位置' && deps.isAndroid && [4, 6].includes(deps.tripStatus)) return null;
src/robotaxi/pages/begin-route/index.less
@@ -120,6 +120,41 @@
    padding: 8px 20px;
}
.route-summary-callout {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-bottom: 12rpx;
}
.route-summary-callout-bubble {
    position: relative;
    z-index: 2;
    white-space: nowrap;
    border-radius: 10rpx;
    background: rgba(0, 0, 0, 0.6);
    font-size: 20rpx;
    font-weight: 500;
    color: #FFFFFF;
    line-height: 28rpx;
    padding: 10rpx 12rpx 9rpx 14rpx;
}
.route-summary-callout-arrow {
    position: absolute;
    left: 50%;
    bottom: 2rpx;
    width: 0;
    height: 0;
    margin-left: -8rpx;
    background: transparent;
    border-style: solid;
    border-width: 10rpx 8rpx 0 8rpx;
    border-color: rgba(0, 0, 0, 0.6) transparent transparent transparent;
    z-index: 1;
}
.txt-center {
    text-align: center;
}
src/robotaxi/pages/begin-route/index.tsx
@@ -41,6 +41,8 @@
import walkIcon from '../../../robotaxi/assets/walk-icon.png'
import { _ROBOTAXI_WS_HOST } from '../../../constants/api';
const ROUTE_SUMMARY_MARKER_ID = 999001;
export default function BeginRoute() {
  const WAITING_TIMER_START_KEY = 'waitingTimerStartAt'; // 等待计时开始时间
  const WAITING_TIMER_ELAPSED_KEY = 'waitingTimerElapsed'; // 等待计时已过秒数
@@ -206,6 +208,7 @@
    selectedRouteIndex,
    handleSelectRoute,
    handlePolylineTap,
    handleMapTap,
    fareEstimate,
    routeAndFareError,
    routeDistance,
@@ -225,6 +228,31 @@
    requestOrderRoute: routeRequestOrderRoute,
    updateWalkingRouteForStart: routeUpdateWalkingRouteForStart
  } = routeState; // 路线状态解构
  const routeSummaryMarker = useMemo(() => {
    if (tripStatus !== 1 || !routeDistance || routeDuration === null || !Array.isArray(routePoints) || routePoints.length === 0) {
      return null;
    }
    const midpoint = routePoints[Math.max(0, Math.floor(routePoints.length / 2))];
    if (!midpoint?.latitude || !midpoint?.longitude) {
      return null;
    }
    return {
      id: ROUTE_SUMMARY_MARKER_ID,
      latitude: midpoint.latitude,
      longitude: midpoint.longitude,
      iconPath: 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car.png',
      width: 1,
      height: 1,
      alpha: 0,
      zIndex: 3,
      isRouteSummaryBubble: true,
      customCallout: { anchorY: 0, anchorX: 0, display: 'ALWAYS' }
    };
  }, [tripStatus, routeDistance, routeDuration, routePoints]);
  const markersWithRouteSummary = useMemo(() => {
    if (!routeSummaryMarker) return markers;
    return [...markers, routeSummaryMarker];
  }, [markers, routeSummaryMarker]);
  const viewportState = useMapViewport({
    tripStatus,
    statusRule,
@@ -394,6 +422,8 @@
    endSite,
    startSite,
    fareEstimate,
    routeOptions,
    selectedRouteIndex,
    routeAndFareError,
    callSubmitting,
    cancelType,
@@ -468,7 +498,7 @@
    isAndroid,
    tripStatus,
    mapScale,
    markers,
    markers: markersWithRouteSummary,
    isRouteSelectExpanded,
    onToggleRouteSelect: setIsRouteSelectExpanded,
    shouldShowWaitingRadar,
@@ -508,7 +538,8 @@
    trunkStatus,
    routeOptions,
    selectedRouteIndex,
    handleSelectRoute
    handleSelectRoute,
    handleMapTap
  }); // 视图渲染委托
  const mapLongitude = longitude ?? 116.397128;
  const mapLatitude = latitude ?? 39.916527;
@@ -532,12 +563,13 @@
      mapLongitude={mapLongitude}
      mapLatitude={mapLatitude}
      mapScale={mapScale}
      markers={markers}
      markers={markersWithRouteSummary}
      polyline={polyline}
      showLocation={!!longitude && showLocationFlag}
      handleCalloutTap={handleCalloutTap}
      handleRegionChange={handleRegionChange}
      onPolylineTap={handlePolylineTap}
      onMapTap={handleMapTap}
      renderMapOverlays={renderMapOverlays}
      toBack={toBack}
      backIcon={backIcon}