Merge branch 'fix/liaof-0814-center' into 'feature_2.6.0'
fix(begin-route): 修复弹窗组件导致地图视口跳变问题
See merge request robotaxi1/xp-robotaxi-miniprogram!282
| | |
| | | points: [point], |
| | | // 执行时才解析 padding 并换算纵向偏移,保证用的是执行那一刻的卡片高度/缩放 |
| | | run: () => |
| | | this.resolveFocusCenter(point, paddingInput).then((center) => |
| | | this.runNative((done) => { |
| | | this.resolveFocusCenter(point, paddingInput).then((center) => { |
| | | // mapPerfLog('focus:exec', { point, center }); |
| | | return this.runNative((done) => { |
| | | this.getCtx().moveToLocation({ |
| | | latitude: center.latitude, |
| | | longitude: center.longitude, |
| | | complete: done, |
| | | } as any); |
| | | }) |
| | | ), |
| | | }); |
| | | }), |
| | | }); |
| | | } |
| | | |
| | |
| | | const [top, , bottom] = padding; |
| | | const offsetPx = (Number(bottom) - Number(top)) / 2; |
| | | if (!Number.isFinite(offsetPx) || offsetPx === 0) { |
| | | // mapPerfLog('focus:fallback', { reason: 'zero-offset', offsetPx, padding }); |
| | | return point; |
| | | } |
| | | return Promise.all([this.getRegionSafe(), this.getMapHeightPx()]).then( |
| | |
| | | const latSpan = |
| | | (region?.northeast?.latitude ?? NaN) - (region?.southwest?.latitude ?? NaN); |
| | | if (!Number.isFinite(latSpan) || latSpan <= 0 || !heightPx) { |
| | | // mapPerfLog('focus:fallback', { reason: 'region-or-height-invalid', latSpan, heightPx }); |
| | | return point; |
| | | } |
| | | const degPerPx = latSpan / heightPx; |
| | |
| | | latitude: point.latitude - offsetPx * degPerPx, |
| | | longitude: point.longitude, |
| | | }; |
| | | // mapPerfLog('focus:visible-center', { point, center, offsetPx }); |
| | | // mapPerfLog('focus:visible-center', { point, center, offsetPx, latSpan, heightPx, degPerPx }); |
| | | return center; |
| | | } |
| | | ); |
| | |
| | | import { CameraContext, CameraIntent, CameraPolicy, NO_CAMERA_INTENT } from '../camera-policy.types'; |
| | | import { LatLng, buildPointsSignature } from '../map-camera'; |
| | | import { buildPointsSignature } from '../map-camera'; |
| | | import { collectPickupViewportPoints, siteToPoint } from '../collect-viewport-points'; |
| | | import { mapPerfLog } from '../map-perf-log'; |
| | | |
| | |
| | | }; |
| | | |
| | | /** |
| | | * 车辆已到(VehicleArrivedPickup) 意图:fit 车 + 用户 + 上车点 (viewport:'car_user')。 |
| | | * 车辆位置缺失时用上车点兜底(车已到,二者接近);点不足 2 个则 focus 单点。 |
| | | * 车辆已到(VehicleArrivedPickup) 意图:focus 上车点,centerInVisibleArea 居中到 |
| | | * 扣除底部卡片后的可视区域。车已到上车点,二者接近,直接居中上车点即可。 |
| | | */ |
| | | const buildArrivedPickupIntent = (ctx: CameraContext, stable: boolean): CameraIntent => { |
| | | const vehicleRaw = siteToPoint(ctx.vehicleLocation); |
| | | const pickup = siteToPoint(ctx.startSite); |
| | | const car = vehicleRaw || pickup; // 车辆坐标校验,缺失用上车点兜底 |
| | | const points: LatLng[] = []; |
| | | if (car) points.push(car); |
| | | const user = siteToPoint(ctx.userLocation); |
| | | if (user) points.push(user); |
| | | // 上车点始终纳入 fit(三点:车 + 用户 + 上车点),避免车辆已偏离上车点位置时 |
| | | // 上车点被推出可视区域;car 用上车点兜底时该点会与 car 重合,includePoints 对 |
| | | // 重复点安全,不影响结果。 |
| | | if (pickup) points.push(pickup); |
| | | // 调试日志:车辆到达上车点时打印三点各自是否取到及坐标,便于排查视口未居中问题。 |
| | | // includePoints 实际使用的 padding 值由 MapCamera.fit 内的 'fit:exec' 日志打印 |
| | | // (signature 同为 'arrived-pickup',可按签名关联两条日志)。 |
| | | mapPerfLog('policy:arrived-pickup-points', { |
| | | stable, |
| | | car: { got: !!vehicleRaw, usedPickupFallback: !vehicleRaw && !!pickup, point: car }, |
| | | user: { got: !!user, point: user }, |
| | | pickup: { got: !!pickup, point: pickup }, |
| | | fitPointsCount: points.length, |
| | | }); |
| | | if (points.length >= MIN_FIT_POINTS) { |
| | | return { |
| | | type: 'fit', |
| | | points, |
| | | signature: stable ? 'arrived-pickup' : undefined, |
| | | }; |
| | | // mapPerfLog('policy:arrived-pickup-points', { |
| | | // stable, |
| | | // pickup: { got: !!pickup, point: pickup }, |
| | | // }); |
| | | if (!pickup) { |
| | | return NO_CAMERA_INTENT; |
| | | } |
| | | // 只有车(无用户定位、无上车点):居中到车 |
| | | return car ? { type: 'focus', point: car } : NO_CAMERA_INTENT; |
| | | return { |
| | | type: 'focus', |
| | | point: pickup, |
| | | centerInVisibleArea: true, |
| | | signature: stable ? 'arrived-pickup' : undefined, |
| | | }; |
| | | }; |
| | | |
| | | /** |
| | | * 车辆已到上车点相机策略:把车+用户+上车点三点居中一次;手势后空闲回中。 |
| | | * 车辆已到上车点相机策略:focus 上车点到可视区域中心;手势后空闲回中。 |
| | | */ |
| | | export const arrivedPickupPolicy: CameraPolicy = { |
| | | onInitial: (ctx) => buildArrivedPickupIntent(ctx, true), |
| | |
| | | walkingPoints: LatLng[]; |
| | | /** 车辆当前位置(接驾/行程态 fit 用)。 */ |
| | | vehicleLocation: LatLng | null; |
| | | /** 最新用户定位(接驾态 fit 用,由外部刷新传入;为空时回退首帧定位值)。 */ |
| | | userLocation?: LatLng | null; |
| | | /** includePoints 留白(按底部卡片/安全区算好;支持异步,即 fit 执行前即时测量)。 */ |
| | | getPadding?: () => CameraPadding | Promise<CameraPadding>; |
| | | /** |
| | |
| | | endSite: d.endSite, |
| | | routePoints: d.routePoints || [], |
| | | walkingPoints: d.walkingPoints || [], |
| | | userLocation: userLocationRef.current, |
| | | userLocation: d.userLocation ?? userLocationRef.current, |
| | | vehicleLocation: d.vehicleLocation ?? null, |
| | | }; |
| | | }, []); |
| | |
| | | params.routePoints, |
| | | params.walkingPoints, |
| | | params.vehicleLocation, |
| | | params.userLocation, |
| | | getPolicy, |
| | | executeIntent, |
| | | buildContext, |
| | |
| | | import Taro, { useDidShow, useShareAppMessage } from "@tarojs/taro" |
| | | import { View } from '@tarojs/components'; |
| | | import { useEffect, useState, useRef, useMemo,useCallback } from 'react'; |
| | | import './index.less'; |
| | | |
| | |
| | | routePoints, |
| | | walkingPoints, |
| | | vehicleLocation, |
| | | userLocation: currentUserLocation, |
| | | getPadding: cameraGetPadding, |
| | | getFocusPadding: cameraGetFocusPadding, |
| | | onLocated: () => setMapLoading(false), |
| | |
| | | <BeginRouteViewProvider value={beginRouteViewContextValue}> |
| | | <BeginRouteView /> |
| | | </BeginRouteViewProvider> |
| | | <ModifyDestinationFailPopup |
| | | show={showModifyDestinationFailPopup} |
| | | content={modifyDestinationFailMessage} |
| | | onConfirm={handleAcknowledgeModifyDestinationFail} |
| | | /> |
| | | <PickupExceptionPopup |
| | | show={showPickupExceptionPopup} |
| | | pickupExceptionInfo={pickupExceptionInfo} |
| | | onClose={handleClosePickupExceptionPopup} |
| | | onConfirm={handleConfirmPickupExceptionNavigation} |
| | | /> |
| | | <CreditPayPopup |
| | | show={showCreditPayPopup} |
| | | onClose={handleCloseCreditPayPopup} |
| | | onConfirm={handleConfirmCreditPayPopup} |
| | | /> |
| | | <TripFinishedFireworks tripStatus={tripStatus} /> |
| | | <View> |
| | | {/* 与 BeginRoutePopupArea 同理:以下弹窗组件隐藏时 return null,节点挂载/卸载 |
| | | 不再连坐 <BeginRouteView> 中的 <Map>,避免 map 全量重应用 lat/lng/scale |
| | | 导致视口跳变。所有弹窗均为 position:fixed,外层 View 不影响定位。 */} |
| | | <ModifyDestinationFailPopup |
| | | show={showModifyDestinationFailPopup} |
| | | content={modifyDestinationFailMessage} |
| | | onConfirm={handleAcknowledgeModifyDestinationFail} |
| | | /> |
| | | <PickupExceptionPopup |
| | | show={showPickupExceptionPopup} |
| | | pickupExceptionInfo={pickupExceptionInfo} |
| | | onClose={handleClosePickupExceptionPopup} |
| | | onConfirm={handleConfirmPickupExceptionNavigation} |
| | | /> |
| | | <CreditPayPopup |
| | | show={showCreditPayPopup} |
| | | onClose={handleCloseCreditPayPopup} |
| | | onConfirm={handleConfirmCreditPayPopup} |
| | | /> |
| | | <TripFinishedFireworks tripStatus={tripStatus} /> |
| | | </View> |
| | | {/* 转场动效调试面板 — 固定在地图上方,始终可见(临时开启,调试完成后请重新注释) */} |
| | | {/* <DebugTransitionPanel |
| | | orderId={orderId} |
| | |
| | | setTripStatus={setTripStatus} |
| | | bindSocketListeners={bindSocketListeners} |
| | | /> */} |
| | | {/* 模拟器入口已关闭,如需本地调试可取消下方注释 |
| | | <DebugOrderSimulatorPanel |
| | | {/* 模拟器入口已关闭,如需本地调试可取消下方注释 */} |
| | | {/* <DebugOrderSimulatorPanel |
| | | orderId={orderId} |
| | | setOrderId={setOrderId} |
| | | setTripStatus={setTripStatus} |
| | |
| | | setShowCancelPopup={setShowCancelPopup} |
| | | setShowModifyDestinationFailPopup={setShowModifyDestinationFailPopup} |
| | | setModifyDestinationFailMessage={setModifyDestinationFailMessage} |
| | | />*/} |
| | | /> */} |
| | | |
| | | </> |
| | | ) |