refactor(camera): 优化地图相机控制逻辑及移除调试组件引用
- 注释掉调试面板 DebugOrderSimulatorPanel 的导入与使用,防止线上干扰
- 新增 userLocation 支持,优先使用最新用户定位,降低定位误差
- 完善 map-camera 中的性能日志,增加关键流程的调用记录
- 调整车辆到达上车点意图逻辑,改为准确聚焦上车点并居中可视区域
- 移除不再使用的 userLocation 旧值及 fit(includePoints)方案,改用 focus 聚焦
- 细化相机位置计算时的回退策略与日志,提升调试效率与稳定性
| | |
| | | const isAuto = options?.isAuto ?? true; |
| | | const signature = options?.signature ?? ''; |
| | | const paddingInput = options?.padding; |
| | | // mapPerfLog('focus:request', { point, isAuto, signature }); |
| | | mapPerfLog('focus:request', { point, isAuto, signature }); |
| | | this.enqueue({ |
| | | kind: 'focus', |
| | | isAuto, |
| | |
| | | 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; |
| | | } |
| | | ); |
| | |
| | | private enqueue(cmd: InternalCommand): void { |
| | | // 避让窗口内忽略自动意图 |
| | | if (cmd.isAuto && this.isHolding()) { |
| | | // mapPerfLog('skip:hold', { kind: cmd.kind, signature: cmd.signature, points: cmd.points }); |
| | | mapPerfLog('skip:hold', { kind: cmd.kind, signature: cmd.signature, points: cmd.points }); |
| | | return; |
| | | } |
| | | // 自动意图去重(fit/focus):相同签名且已应用/在途/排队则跳过(用户显式意图不去重) |
| | |
| | | cmd.signature === this.lastAppliedSignature || |
| | | this.queue.some((q) => q.signature === cmd.signature); |
| | | if (duplicate) { |
| | | // mapPerfLog('skip:dedup', { signature: cmd.signature, points: cmd.points }); |
| | | mapPerfLog('skip:dedup', { signature: cmd.signature, points: cmd.points }); |
| | | return; |
| | | } |
| | | } |
| | |
| | | }; |
| | | |
| | | /** |
| | | * 车辆已到(VehicleArrivedPickup) 意图:focus 上车点(车已到,二者接近), |
| | | * centerInVisibleArea 居中到扣除底部卡片后的可视区域。 |
| | | * |
| | | * 不使用 fit(includePoints): |
| | | * 1. 不使用 userLocation——到达上车点时用户定位仍是页面进入时的旧值,会把视口撑歪 |
| | | * (与 arrivedDestinationPolicy 同理); |
| | | * 2. 车+用户+上车点三点极近时 includePoints 不理会不对称 padding,会把点放到 |
| | | * 整张地图几何中心(视觉上贴近底部卡片),与 callingPolicy 注释同理。 |
| | | * 改用 focus + centerInVisibleArea:与 callingPolicy 一致,精确居中到可视区域。 |
| | | * 车辆已到(VehicleArrivedPickup) 意图:focus 上车点,centerInVisibleArea 居中到 |
| | | * 扣除底部卡片后的可视区域。车已到上车点,二者接近,直接居中上车点即可。 |
| | | */ |
| | | const buildArrivedPickupIntent = (ctx: CameraContext, stable: boolean): CameraIntent => { |
| | | const vehicleRaw = siteToPoint(ctx.vehicleLocation); |
| | | const pickup = siteToPoint(ctx.startSite); |
| | | const car = vehicleRaw || pickup; // 车辆坐标校验,缺失用上车点兜底 |
| | | mapPerfLog('policy:arrived-pickup-points', { |
| | | stable, |
| | | car: { got: !!vehicleRaw, usedPickupFallback: !vehicleRaw && !!pickup, point: car }, |
| | | pickup: { got: !!pickup, point: pickup }, |
| | | }); |
| | | if (!car) { |
| | | if (!pickup) { |
| | | return NO_CAMERA_INTENT; |
| | | } |
| | | return { |
| | | type: 'focus', |
| | | point: car, |
| | | point: pickup, |
| | | centerInVisibleArea: true, |
| | | signature: stable ? 'arrived-pickup' : undefined, |
| | | }; |
| | |
| | | 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 PickupExceptionPopup from './components/pickup-exception-popup'; |
| | | import CreditPayPopup from './components/credit-pay-popup'; |
| | | // 调试面板:模拟完整行程流转(仅 dev 构建可见) |
| | | import DebugOrderSimulatorPanel from './components/debug-order-simulator-panel'; |
| | | // import DebugOrderSimulatorPanel from './components/debug-order-simulator-panel'; |
| | | // 转场动效调试面板:呼叫中→派单成功、送驾中→行程结束(仅 dev 构建可见) |
| | | // import DebugTransitionPanel from './components/debug-transition-panel'; |
| | | // 到达结束态全屏礼花动效 |
| | |
| | | routePoints, |
| | | walkingPoints, |
| | | vehicleLocation, |
| | | userLocation: currentUserLocation, |
| | | getPadding: cameraGetPadding, |
| | | getFocusPadding: cameraGetFocusPadding, |
| | | onLocated: () => setMapLoading(false), |
| | |
| | | bindSocketListeners={bindSocketListeners} |
| | | /> */} |
| | | {/* 模拟器入口已关闭,如需本地调试可取消下方注释 */} |
| | | <DebugOrderSimulatorPanel |
| | | {/* <DebugOrderSimulatorPanel |
| | | orderId={orderId} |
| | | setOrderId={setOrderId} |
| | | setTripStatus={setTripStatus} |
| | |
| | | setShowCancelPopup={setShowCancelPopup} |
| | | setShowModifyDestinationFailPopup={setShowModifyDestinationFailPopup} |
| | | setModifyDestinationFailMessage={setModifyDestinationFailMessage} |
| | | /> |
| | | /> */} |
| | | |
| | | </> |
| | | ) |