| | |
| | | } |
| | | }; |
| | | |
| | | // 兜底定时器,防止回调丢失导致动画队列卡死 |
| | | fallbackTimer = setTimeout(() => { |
| | | finishTranslate(); |
| | | }, TRANSLATE_DURATION_MS + 50); |
| | | // 兜底定时器,防止回调丢失导致动画队列卡死 |
| | | fallbackTimer = setTimeout(() => { |
| | | finishTranslate(); |
| | | }, task.duration + 50); |
| | | |
| | | Taro.nextTick(() => { |
| | | const mapCtx = Taro.createMapContext('map'); |
| | | mapCtx.translateMarker({ |
| | | markerId: task.markerId, |
| | | destination: { |
| | | latitude: task.latitude, |
| | | longitude: task.longitude, |
| | | }, |
| | | autoRotate: false, |
| | | moveWithRotate: true, |
| | | rotate: task.rotate, |
| | | duration: Math.max(task.duration, 100), |
| | | animationEnd: () => { |
| | | if (translateSessionId !== translateSessionIdRef.current) { |
| | | return; |
| | | } |
| | | lastAppliedTranslateTaskRef.current = { |
| | | latitude: task.latitude, |
| | | longitude: task.longitude, |
| | | rotate: task.rotate |
| | | }; |
| | | finishTranslate(); |
| | | }, |
| | | fail: () => { |
| | | if (translateSessionId !== translateSessionIdRef.current) { |
| | | return; |
| | | } |
| | | lastAppliedTranslateTaskRef.current = { |
| | | latitude: task.latitude, |
| | | longitude: task.longitude, |
| | | rotate: task.rotate |
| | | }; |
| | | finishTranslate(); |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | Taro.nextTick(() => { |
| | | const mapCtx = Taro.createMapContext("map"); |
| | | mapCtx.translateMarker({ |
| | | markerId: task.markerId, |
| | | destination: { |
| | | latitude: task.latitude, |
| | | longitude: task.longitude, |
| | | }, |
| | | autoRotate: false, |
| | | moveWithRotate: true, |
| | | rotate: task.rotate, |
| | | // duration 为 0 时,微信地图在 iOS 存在 Bug(回调永远不触发或引发死锁)。 |
| | | // 兜底为 1ms,既能实现视觉上的"瞬移"(解决重置旋转矩阵的需求),又能保证动画队列正常结束。 |
| | | duration: Math.max(task.duration, 1), |
| | | animationEnd: () => { |
| | | if (translateSessionId !== translateSessionIdRef.current) { |
| | | return; |
| | | } |
| | | lastAppliedTranslateTaskRef.current = { |
| | | latitude: task.latitude, |
| | | longitude: task.longitude, |
| | | rotate: task.rotate, |
| | | }; |
| | | finishTranslate(); |
| | | }, |
| | | fail: () => { |
| | | if (translateSessionId !== translateSessionIdRef.current) { |
| | | return; |
| | | } |
| | | lastAppliedTranslateTaskRef.current = { |
| | | latitude: task.latitude, |
| | | longitude: task.longitude, |
| | | rotate: task.rotate, |
| | | }; |
| | | finishTranslate(); |
| | | }, |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // 更新车辆位置并维护最近位置引用 |
| | | const updateVehicleLocationThrottled = ( |
| | |
| | | }, []); |
| | | |
| | | /** |
| | | * 暂停 translateMarker 并切换到新的 markerId。 |
| | | * 在 CarMarker 重建期间调用:原生层即将销毁旧 marker、用 newMarkerId 创建新 marker, |
| | | * 这里同步把 vehicleMarkerIdRef 切到新 id,pending 任务的 markerId 也一并更新, |
| | | * 确保 ready 恢复后 translateMarker 作用于新 marker。 |
| | | * |
| | | * 关键:保留 pendingTranslateRef.current(只改 markerId)。 |
| | | * - 若 suspend 前已有 pending(最近一次推送写入但尚未 flush),ready 恢复后会直接消费它。 |
| | | * - 若 suspend 后再有新推送,translateCar useEffect 会用最新值覆盖 pending(markerId 用 ref 取最新)。 |
| | | * 重置 translateMarker 并准备新状态。 |
| | | * 背景:为了解决旧版方案(修改 marker ID)导致的车标虚影问题,我们现已将 marker ID 固定。 |
| | | * 当需要强行纠正位置或清除原生层残留的旋转矩阵(rotate)时: |
| | | * 我们不再销毁/重建 marker,而是将 pending 动画的 duration 设为极小值(0,实际运行为 1ms), |
| | | * 让原生引擎立即"瞬移"到目标状态,从而强制覆盖掉内部的旧状态。 |
| | | */ |
| | | const suspendVehicleMarker = useCallback((newMarkerId: number) => { |
| | | const suspendVehicleMarker = useCallback((_newMarkerId: number) => { |
| | | isTranslatingRef.current = false; |
| | | // 清除上一次的记录,让下次 translate 时认为发生了位移和角度变化,必须派发指令 |
| | | lastAppliedTranslateTaskRef.current = null; |
| | | vehicleMarkerReadyRef.current = false; |
| | | clearVehicleMarkerReadyTimer(); |
| | | translateSessionIdRef.current += 1; |
| | | vehicleMarkerIdRef.current = newMarkerId; |
| | | |
| | | // 注意:不更新 vehicleMarkerIdRef.current,因为不再派生新 ID |
| | | |
| | | // 保留 pending,并将 duration 设为 0 以强制原生层立即归位(重置旋转矩阵和位置) |
| | | if (pendingTranslateRef.current) { |
| | | pendingTranslateRef.current = { |
| | | ...pendingTranslateRef.current, |
| | | markerId: newMarkerId |
| | | duration: ROTATE_ONLY_DURATION_MS |
| | | }; |
| | | } |
| | | }, []); |