You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中使用pigeon-maps实现船舶航线动画的问题求助

解决pigeon-maps中船舶航线动画的三个问题

问题1:动画执行速度极快后消失

原因:requestAnimationFrame默认每秒执行约60次,500步的话几秒就跑完了,且没有保留最终线路。解决方法是给每帧动画加固定延迟,同时减少总步数控制时长。

问题2:线路仅呈南北直线,无法连接起点终点

原因:代码里坐标拼接错误,lineCoordinates.push([start[0] + i, start[0] + j]);第二个参数误用了start[0],应该是start[1] + j,导致Y轴坐标始终为X起点值,形成直线。

问题3:移至state后仅地图缩放时触发动画

原因:直接修改geojson对象不会触发React重渲染,必须通过setState更新状态;且初始动画需要在组件挂载后主动触发,而非依赖地图缩放事件。


修正后的完整代码

import { useState, useEffect } from 'react';
import { Map, GeoJSON } from 'pigeon-maps';

export default function ShipRouteMap() {
  // 用state管理GeoJSON数据,确保更新时触发重渲染
  const [routeGeoJSON, setRouteGeoJSON] = useState({
    type: "FeatureCollection",
    features: [
      {
        type: "Feature",
        properties: {},
        geometry: {
          type: "LineString",
          coordinates: [] // 初始空线路
        }
      }
    ]
  });

  useEffect(() => {
    const start = [0.108266, 52.202758];
    const end = [0.11556, 52.201733];
    const totalSteps = 100; // 减少步数控制动画时长
    const stepDelay = 30; // 每步延迟30ms,总时长约3秒

    // 计算每步的坐标增量
    const diffX = end[0] - start[0];
    const diffY = end[1] - start[1];
    const stepX = diffX / totalSteps;
    const stepY = diffY / totalSteps;

    let currentStep = 0;
    let currentCoordinates = [start]; // 初始包含起点

    const animateStep = () => {
      if (currentStep < totalSteps) {
        const nextX = start[0] + stepX * (currentStep + 1);
        const nextY = start[1] + stepY * (currentStep + 1);
        currentCoordinates.push([nextX, nextY]);
        
        // 更新state触发地图重渲染
        setRouteGeoJSON(prev => ({
          ...prev,
          features: [
            {
              ...prev.features[0],
              geometry: {
                ...prev.features[0].geometry,
                coordinates: [...currentCoordinates]
              }
            }
          ]
        }));

        currentStep++;
        // 用setTimeout控制动画速度
        setTimeout(animateStep, stepDelay);
      }
    };

    // 启动动画
    animateStep();

    // 组件卸载时清理定时器,防止内存泄漏
    return () => clearTimeout(animateStep);
  }, []);

  return (
    <Map height={600} center={[52.2022, 0.1119]} zoom={14}>
      <GeoJSON
        data={routeGeoJSON}
        style={{ stroke: "#2196F3", strokeWidth: 3 }}
      />
    </Map>
  );
}

关键修改说明

  • 修复坐标错误:把start[0] + j改成start[1] + j,确保Y轴坐标正确计算。
  • 控制动画速度:用setTimeout替代纯requestAnimationFrame,通过stepDelay控制每步间隔,同时减少总步数让动画时长更合理。
  • 正确触发重渲染:通过setRouteGeoJSON更新state,每次动画步骤生成新的coordinates数组,确保React检测到变化并重新渲染GeoJSON图层。
  • 保留完整线路:动画结束后currentCoordinates包含完整的起点到终点坐标,线路不会消失。

内容的提问来源于stack exchange,提问作者jgabb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:17:45