openlayers上跟据经纬度画出轨迹


1.需求 展示经纬度位置的轨迹,

2.点击展示具体信息

3.每个线段上加上流向线

先说下箭头,箭头样式比较难调

默认图片的箭头是6点钟方向

javascript 复制代码
     // 为线段添加箭头,放在线段中点
      let lastSegmentAngle = 0; // 存储最后一个线段的角度
      if (coordinates.length > 1) {
        for (let i = 1; i < coordinates.length; i++) {
          // 计算线段中点
          const midX = (coordinates[i-1][0] + coordinates[i][0]) / 2;
          const midY = (coordinates[i-1][1] + coordinates[i][1]) / 2;
          
          // 计算当前线段的方向角度(动态方向)
          const dx = coordinates[i][0] - coordinates[i-1][0];
          const dy = coordinates[i][1] - coordinates[i-1][1];
          let segmentAngle = Math.atan2(dy, dx);
          
          // 存储最后一个线段的角度
          if (i === coordinates.length - 1) {
            lastSegmentAngle = segmentAngle;
          }
          
          // 调整旋转角度,确保箭头指向线段的正确方向
          segmentAngle += Math.PI / 2;
          
          // 创建箭头要素
          const arrowFeature = new Feature({
            geometry: new Point([midX, midY])
          });
          // 创建箭头样式 - 使用jiantou图片作为箭头
          const arrowStyle = new Style({
            image: new Icon({
              src: this.jiantou, // 使用jiantou图片
              scale: 0.05, // 调整图片大小
              rotation: - segmentAngle, // 根据线段方向旋转图片
              anchor: [0.5, 0.5] // 设置锚点为图片中心
            })
          });
javascript 复制代码
<script>
import { getShipTrajectory } from "@/api/ship";
import "ol/ol.css";
import { Map, View } from "ol";
import TileLayer from "ol/layer/Tile";
import VectorLayer from "ol/layer/Vector";
import XYZ from "ol/source/XYZ";
import Overlay from "ol/Overlay";
import { Style, Icon, Stroke, Fill, Circle, Text, RegularShape } from "ol/style";
import { Draw, Modify } from "ol/interaction.js";
import { Cluster, Vector as VectorSource } from "ol/source";
import { Feature } from "ol";
import { Point, LineString } from "ol/geom";
import { drawStyleFunction, modifyStyle } from "./draw.js";
import startImg from "@/assets/img/start_point.png";
import jiantou from "@/assets/img/jiantou.png";
import chuanImg from "@/assets/img/chuan.png";
import ship_start from "@/assets/img/ship_start.png";
import ship_end from "@/assets/img/ship_end.png";
import marker_action from "@/assets/img/marker_action.png";
import marker_point from "@/assets/img/marker_point.png";
import { offset } from "ol/sphere.js";

// 线性插值函数,计算两点之间的中间点
function interpolatePoint(start, end, t) {
  return [
    start[0] + (end[0] - start[0]) * t,
    start[1] + (end[1] - start[1]) * t,
  ];
}
let tk = "b9031f80391e6b65bd1dd80dcde1b097";
export default {
  props: {
    zoomNum: {
      type: Number,
      default: 9,
    },
    pointList: {
      type: Array,
      default: () => [],
    },
    timeArr: {
      type: Array,
      default: () => [],
    },
    region: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      activeType: 1,
      map: null,
      selectValue: "",
      // region: "",
      jiantou: jiantou, // 添加jiantou图片
      chuanImg: chuanImg, // 添加chuanImg图片
      ship_start: ship_start, // 添加ship_start图片
      ship_end: ship_end, // 添加ship_end图片
      guiji: [
        {
          ti: "2026-03-10 10:58:53",
          lo: "121.787665",
          la: "31.359718",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-16 08:03:00",
          lo: "121.795298",
          la: "31.30542",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-16 08:27:03",
          lo: "121.728603",
          la: "31.290915",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-16 10:44:47",
          lo: "121.930703",
          la: "31.115172",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-16 10:48:58",
          lo: "121.939618",
          la: "31.110445",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-16 12:16:34",
          lo: "122.187375",
          la: "31.023797",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-16 12:35:51",
          lo: "122.249098",
          la: "31.00373",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-16 13:48:44",
          lo: "122.312147",
          la: "31.007642",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-16 15:27:57",
          lo: "122.496935",
          la: "30.910865",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-16 16:29:58",
          lo: "122.679985",
          la: "30.881056",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-16 19:57:04",
          lo: "122.816666",
          la: "30.703333",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-17 06:03:03",
          lo: "122.96833",
          la: "30.743334",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-17 08:45:35",
          lo: "123.219692",
          la: "30.678365",
          starttime: "-",
          stoptime: "-",
        },
        {
          ti: "2026-03-17 09:02:20",
          lo: "122.74989166666667",
          la: "30.8293",
          starttime: "2026-03-17 09:46:51",
          stoptime: "2026-03-16 17:49:53",
        },
        {
          ti: "2026-03-17 10:53:41",
          lo: "123.394357",
          la: "30.61296",
          starttime: "-",
          stoptime: "-",
        },
      ],
      guijis:[
                {
                    "accumulatetime": "-",
                    "co": "111.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "111.0",
                    "isstoppoint": "0",
                    "la": "30.540001",
                    "lo": "123.589996",
                    "m": "412371225",
                    "msgid": "27",
                    "n": "ZHONGYUKE211",
                    "sp": "10.0",
                    "src": "171",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-17 12:48:03",
                    "timestamp": 1773722883000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "169.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "0.0",
                    "isstoppoint": "0",
                    "la": "30.295139",
                    "lo": "123.986557",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "9.8",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-17 16:55:54",
                    "timestamp": 1773737754000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "174.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "0.0",
                    "isstoppoint": "0",
                    "la": "30.154907",
                    "lo": "123.98571",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "8.8",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-17 17:51:00",
                    "timestamp": 1773741060000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "174.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "174.0",
                    "isstoppoint": "0",
                    "la": "30.028334",
                    "lo": "123.995003",
                    "m": "412371225",
                    "msgid": "27",
                    "n": "ZHONGYUKE211",
                    "sp": "8.0",
                    "src": "171",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-17 18:42:08",
                    "timestamp": 1773744128000,
                    "z": "0"
                },
                {
                    "accumulatetime": "0h39m",
                    "co": "-",
                    "dis": "297.7304961346104",
                    "displayzoom": "10",
                    "frmt": "0",
                    "hdg": "-",
                    "isstoppoint": "1",
                    "la": "30.003334045410156",
                    "lo": "123.99666595458984",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "position": "POINT(123.99666595458984 30.003334045410156)",
                    "sp": "2",
                    "src": "1",
                    "starttime": "2026-03-17 19:36:21",
                    "stoptime": "2026-03-17 18:57:03",
                    "ti": "2026-03-17 18:57:03",
                    "timestamp": 1773745023000,
                    "z": "-"
                },
                {
                    "accumulatetime": "1h28m",
                    "co": "-",
                    "dis": "297.7304961346104",
                    "displayzoom": "10",
                    "frmt": "0",
                    "hdg": "-",
                    "isstoppoint": "1",
                    "la": "29.69333267211914",
                    "lo": "123.97833251953125",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "position": "POINT(123.97833251953125 29.69333267211914)",
                    "sp": "2",
                    "src": "1",
                    "starttime": "2026-03-17 23:22:49",
                    "stoptime": "2026-03-17 23:09:09",
                    "ti": "2026-03-17 23:09:09",
                    "timestamp": 1773760149000,
                    "z": "-"
                },
                {
                    "accumulatetime": "-",
                    "co": "183.9",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "199.0",
                    "isstoppoint": "0",
                    "la": "29.715962",
                    "lo": "123.983057",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "4.9",
                    "src": "90117",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-17 23:21:16",
                    "timestamp": 1773760876000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "186.6",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "194.0",
                    "isstoppoint": "0",
                    "la": "29.714528",
                    "lo": "123.982768",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "5.6",
                    "src": "90117",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-17 23:22:17",
                    "timestamp": 1773760937000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "181.1",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "189.0",
                    "isstoppoint": "0",
                    "la": "29.6842",
                    "lo": "123.979847",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "6.1",
                    "src": "90117",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-17 23:40:47",
                    "timestamp": 1773762047000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "175.9",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "187.0",
                    "isstoppoint": "0",
                    "la": "29.66159",
                    "lo": "123.979693",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "6.3",
                    "src": "90117",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-17 23:53:31",
                    "timestamp": 1773762811000,
                    "z": "0"
                },
                {
                    "accumulatetime": "3h9m",
                    "co": "-",
                    "dis": "297.7304961346104",
                    "displayzoom": "10",
                    "frmt": "0",
                    "hdg": "-",
                    "isstoppoint": "1",
                    "la": "29.619809999999998",
                    "lo": "123.98842666666665",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "position": "POINT(123.98842666666665 29.619809999999998)",
                    "sp": "2",
                    "src": "1",
                    "starttime": "2026-03-18 03:32:02",
                    "stoptime": "2026-03-18 01:18:06",
                    "ti": "2026-03-18 01:18:06",
                    "timestamp": 1773767886000,
                    "z": "-"
                },
                {
                    "accumulatetime": "-",
                    "co": "94.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "94.0",
                    "isstoppoint": "0",
                    "la": "29.606667",
                    "lo": "123.989998",
                    "m": "412371225",
                    "msgid": "27",
                    "n": "ZHONGYUKE211",
                    "sp": "1.0",
                    "src": "171",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 02:06:05",
                    "timestamp": 1773770765000,
                    "z": "0"
                },
                {
                    "accumulatetime": "2h45m",
                    "co": "-",
                    "dis": "297.7304961346104",
                    "displayzoom": "10",
                    "frmt": "0",
                    "hdg": "-",
                    "isstoppoint": "1",
                    "la": "29.623332977294922",
                    "lo": "123.96499633789062",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "position": "POINT(123.96499633789062 29.623332977294922)",
                    "sp": "2",
                    "src": "1",
                    "starttime": "2026-03-18 07:22:08",
                    "stoptime": "2026-03-18 04:57:03",
                    "ti": "2026-03-18 04:57:03",
                    "timestamp": 1773781023000,
                    "z": "-"
                },
                {
                    "accumulatetime": "0h49m",
                    "co": "-",
                    "dis": "297.7304961346104",
                    "displayzoom": "10",
                    "frmt": "0",
                    "hdg": "-",
                    "isstoppoint": "1",
                    "la": "30.087786666666666",
                    "lo": "123.74503",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "position": "POINT(123.74503 30.087786666666666)",
                    "sp": "2",
                    "src": "1",
                    "starttime": "2026-03-18 11:52:30",
                    "stoptime": "2026-03-18 11:42:14",
                    "ti": "2026-03-18 11:42:14",
                    "timestamp": 1773805334000,
                    "z": "-"
                },
                {
                    "accumulatetime": "-",
                    "co": "298.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "298.0",
                    "isstoppoint": "0",
                    "la": "30.096666",
                    "lo": "123.739998",
                    "m": "412371225",
                    "msgid": "27",
                    "n": "ZHONGYUKE211",
                    "sp": "7.0",
                    "src": "171",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 12:00:04",
                    "timestamp": 1773806404000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "352.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "357.0",
                    "isstoppoint": "0",
                    "la": "29.852364",
                    "lo": "123.507957",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "3.6",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 16:43:22",
                    "timestamp": 1773823402000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "347.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "2.0",
                    "isstoppoint": "0",
                    "la": "29.857027",
                    "lo": "123.506737",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "6.6",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 16:48:32",
                    "timestamp": 1773823712000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "252.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "5.0",
                    "isstoppoint": "0",
                    "la": "29.857313",
                    "lo": "123.500519",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "0.5",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 17:03:56",
                    "timestamp": 1773824636000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "309.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "331.0",
                    "isstoppoint": "0",
                    "la": "29.85928",
                    "lo": "123.497543",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "5.2",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 17:08:00",
                    "timestamp": 1773824880000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "179.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "28.0",
                    "isstoppoint": "0",
                    "la": "29.862926",
                    "lo": "123.492775",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "1.1",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 17:13:17",
                    "timestamp": 1773825197000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "226.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "89.0",
                    "isstoppoint": "0",
                    "la": "29.847246",
                    "lo": "123.484337",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "1.3",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 17:46:44",
                    "timestamp": 1773827204000,
                    "z": "0"
                },
                {
                    "accumulatetime": "0h48m",
                    "co": "-",
                    "dis": "297.7304961346104",
                    "displayzoom": "10",
                    "frmt": "0",
                    "hdg": "-",
                    "isstoppoint": "1",
                    "la": "29.861066666666666",
                    "lo": "123.49172166666666",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "position": "POINT(123.49172166666666 29.861066666666666)",
                    "sp": "2",
                    "src": "1",
                    "starttime": "2026-03-18 18:05:46",
                    "stoptime": "2026-03-18 17:52:49",
                    "ti": "2026-03-18 17:52:49",
                    "timestamp": 1773827569000,
                    "z": "-"
                },
                {
                    "accumulatetime": "-",
                    "co": "322.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "342.0",
                    "isstoppoint": "0",
                    "la": "29.854013",
                    "lo": "123.468918",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "3.6",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 18:14:08",
                    "timestamp": 1773828848000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "328.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "338.0",
                    "isstoppoint": "0",
                    "la": "29.865534",
                    "lo": "123.458397",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "5.5",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 18:25:27",
                    "timestamp": 1773829527000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "309.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "336.0",
                    "isstoppoint": "0",
                    "la": "29.876894",
                    "lo": "123.446907",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "2.7",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 18:36:56",
                    "timestamp": 1773830216000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "325.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "336.0",
                    "isstoppoint": "0",
                    "la": "29.889561",
                    "lo": "123.433464",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "4.7",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 18:51:37",
                    "timestamp": 1773831097000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "313.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "337.0",
                    "isstoppoint": "0",
                    "la": "29.910669",
                    "lo": "123.414543",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "2.7",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 19:11:28",
                    "timestamp": 1773832288000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "318.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "336.0",
                    "isstoppoint": "0",
                    "la": "29.916401",
                    "lo": "123.408829",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "5.0",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 19:18:40",
                    "timestamp": 1773832720000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "319.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "339.0",
                    "isstoppoint": "0",
                    "la": "29.930286",
                    "lo": "123.396523",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "3.2",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 19:33:17",
                    "timestamp": 1773833597000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "297.7",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "296.0",
                    "isstoppoint": "0",
                    "la": "29.949522",
                    "lo": "123.369597",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "5.0",
                    "src": "90289",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 19:58:23",
                    "timestamp": 1773835103000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "304.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "311.0",
                    "isstoppoint": "0",
                    "la": "29.954422",
                    "lo": "123.360033",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "6.4",
                    "src": "90289",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 20:03:30",
                    "timestamp": 1773835410000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "296.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "302.0",
                    "isstoppoint": "0",
                    "la": "29.964911",
                    "lo": "123.341469",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "5.7",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 20:15:02",
                    "timestamp": 1773836102000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "310.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "316.0",
                    "isstoppoint": "0",
                    "la": "29.97802",
                    "lo": "123.320602",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "6.0",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 20:28:27",
                    "timestamp": 1773836907000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "257.6",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "253.0",
                    "isstoppoint": "0",
                    "la": "29.98097",
                    "lo": "123.305702",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "8.5",
                    "src": "90289",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 20:36:46",
                    "timestamp": 1773837406000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "286.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "276.0",
                    "isstoppoint": "0",
                    "la": "29.982441",
                    "lo": "123.259491",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "8.7",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 20:54:25",
                    "timestamp": 1773838465000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "25.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "272.0",
                    "isstoppoint": "0",
                    "la": "29.987907",
                    "lo": "123.237518",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "0.0",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 21:16:24",
                    "timestamp": 1773839784000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "199.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "282.0",
                    "isstoppoint": "0",
                    "la": "29.993174",
                    "lo": "123.233376",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "0.8",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-18 22:10:05",
                    "timestamp": 1773843005000,
                    "z": "0"
                },
                {
                    "accumulatetime": "5h20m",
                    "co": "-",
                    "dis": "297.7304961346104",
                    "displayzoom": "10",
                    "frmt": "0",
                    "hdg": "-",
                    "isstoppoint": "1",
                    "la": "29.98707389831543",
                    "lo": "123.23887634277344",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "position": "POINT(123.23887634277344 29.98707389831543)",
                    "sp": "2",
                    "src": "1",
                    "starttime": "2026-03-19 02:24:49",
                    "stoptime": "2026-03-18 22:57:05",
                    "ti": "2026-03-18 22:57:05",
                    "timestamp": 1773845825000,
                    "z": "-"
                },
                {
                    "accumulatetime": "-",
                    "co": "91.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "260.0",
                    "isstoppoint": "0",
                    "la": "29.992147",
                    "lo": "123.237679",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "0.5",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 00:28:29",
                    "timestamp": 1773851309000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "96.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "271.0",
                    "isstoppoint": "0",
                    "la": "29.969641",
                    "lo": "123.246933",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "0.5",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 01:51:28",
                    "timestamp": 1773856288000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "159.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "271.0",
                    "isstoppoint": "0",
                    "la": "29.962959",
                    "lo": "123.248802",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "1.3",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 02:09:18",
                    "timestamp": 1773857358000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "188.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "267.0",
                    "isstoppoint": "0",
                    "la": "29.948713",
                    "lo": "123.250603",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "3.0",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 02:43:21",
                    "timestamp": 1773859401000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "160.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "268.0",
                    "isstoppoint": "0",
                    "la": "29.945333",
                    "lo": "123.251106",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "2.4",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 02:50:39",
                    "timestamp": 1773859839000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "169.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "267.0",
                    "isstoppoint": "0",
                    "la": "29.943939",
                    "lo": "123.251244",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "0.7",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 02:53:39",
                    "timestamp": 1773860019000,
                    "z": "0"
                },
                {
                    "accumulatetime": "0h36m",
                    "co": "-",
                    "dis": "297.7304961346104",
                    "displayzoom": "10",
                    "frmt": "0",
                    "hdg": "-",
                    "isstoppoint": "1",
                    "la": "29.954545974731445",
                    "lo": "123.2501220703125",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "position": "POINT(123.2501220703125 29.954545974731445)",
                    "sp": "2",
                    "src": "1",
                    "starttime": "2026-03-19 03:06:09",
                    "stoptime": "2026-03-19 02:53:39",
                    "ti": "2026-03-19 02:53:39",
                    "timestamp": 1773860019000,
                    "z": "-"
                },
                {
                    "accumulatetime": "-",
                    "co": "348.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "357.0",
                    "isstoppoint": "0",
                    "la": "29.942226",
                    "lo": "123.25071",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "1.3",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 03:00:46",
                    "timestamp": 1773860446000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "340.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "344.0",
                    "isstoppoint": "0",
                    "la": "29.947002",
                    "lo": "123.248878",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "4.5",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 03:06:00",
                    "timestamp": 1773860760000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "342.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "344.0",
                    "isstoppoint": "0",
                    "la": "29.972246",
                    "lo": "123.23819",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "2.7",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 03:30:52",
                    "timestamp": 1773862252000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "344.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "350.0",
                    "isstoppoint": "0",
                    "la": "29.992386",
                    "lo": "123.229744",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "4.4",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 03:50:26",
                    "timestamp": 1773863426000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "357.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "0.0",
                    "isstoppoint": "0",
                    "la": "30.002773",
                    "lo": "123.228012",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "3.0",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 04:00:53",
                    "timestamp": 1773864053000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "203.6",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "280.0",
                    "isstoppoint": "0",
                    "la": "29.981847",
                    "lo": "123.225123",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "0.9",
                    "src": "50133",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 04:42:44",
                    "timestamp": 1773866564000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "195.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "264.0",
                    "isstoppoint": "0",
                    "la": "29.97823",
                    "lo": "123.224304",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "2.9",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 04:48:55",
                    "timestamp": 1773866935000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "186.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "266.0",
                    "isstoppoint": "0",
                    "la": "29.972954",
                    "lo": "123.222694",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "2.3",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 04:58:13",
                    "timestamp": 1773867493000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "201.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "263.0",
                    "isstoppoint": "0",
                    "la": "29.97127",
                    "lo": "123.222374",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "1.9",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 05:01:13",
                    "timestamp": 1773867673000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "341.9",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "1.0",
                    "isstoppoint": "0",
                    "la": "29.959708",
                    "lo": "123.2175",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "2.7",
                    "src": "50133",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 05:25:14",
                    "timestamp": 1773869114000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "359.8",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "7.0",
                    "isstoppoint": "0",
                    "la": "29.963093",
                    "lo": "123.216823",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "4.3",
                    "src": "50133",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 05:28:23",
                    "timestamp": 1773869303000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "14.9",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "10.0",
                    "isstoppoint": "0",
                    "la": "29.97606",
                    "lo": "123.21807",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "2.8",
                    "src": "50133",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 05:39:42",
                    "timestamp": 1773869982000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "10.5",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "17.0",
                    "isstoppoint": "0",
                    "la": "29.991087",
                    "lo": "123.222262",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "2.4",
                    "src": "50133",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 05:55:06",
                    "timestamp": 1773870906000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "10.9",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "19.0",
                    "isstoppoint": "0",
                    "la": "29.99525",
                    "lo": "123.223472",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "4.7",
                    "src": "50133",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 05:59:14",
                    "timestamp": 1773871154000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "13.5",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "19.0",
                    "isstoppoint": "0",
                    "la": "30.00399",
                    "lo": "123.225988",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "2.9",
                    "src": "50133",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 06:07:27",
                    "timestamp": 1773871647000,
                    "z": "0"
                },
                {
                    "accumulatetime": "1h5m",
                    "co": "-",
                    "dis": "297.7304961346104",
                    "displayzoom": "10",
                    "frmt": "0",
                    "hdg": "-",
                    "isstoppoint": "1",
                    "la": "30.00890350341797",
                    "lo": "123.22752380371094",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "position": "POINT(123.22752380371094 30.00890350341797)",
                    "sp": "2",
                    "src": "1",
                    "starttime": "2026-03-19 07:19:54",
                    "stoptime": "2026-03-19 06:14:41",
                    "ti": "2026-03-19 06:14:41",
                    "timestamp": 1773872081000,
                    "z": "-"
                },
                {
                    "accumulatetime": "-",
                    "co": "207.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "92.0",
                    "isstoppoint": "0",
                    "la": "30.006002",
                    "lo": "123.225708",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "2.0",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 06:21:54",
                    "timestamp": 1773872514000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "239.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "83.0",
                    "isstoppoint": "0",
                    "la": "30.004417",
                    "lo": "123.22493",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "0.8",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 06:25:58",
                    "timestamp": 1773872758000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "191.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "100.0",
                    "isstoppoint": "0",
                    "la": "30.00161",
                    "lo": "123.223175",
                    "m": "412371225",
                    "msgid": "3",
                    "n": "ZHONGYUKE211",
                    "sp": "2.6",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 06:33:18",
                    "timestamp": 1773873198000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "231.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "103.0",
                    "isstoppoint": "0",
                    "la": "29.994894",
                    "lo": "123.217293",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "1.4",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 06:53:54",
                    "timestamp": 1773874434000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "247.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "287.0",
                    "isstoppoint": "0",
                    "la": "29.988047",
                    "lo": "123.209427",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "2.1",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 07:19:54",
                    "timestamp": 1773875994000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "173.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "163.0",
                    "isstoppoint": "0",
                    "la": "29.98538",
                    "lo": "123.208076",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "6.8",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 07:26:14",
                    "timestamp": 1773876374000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "171.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "163.0",
                    "isstoppoint": "0",
                    "la": "29.967674",
                    "lo": "123.21209",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "8.9",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 07:33:33",
                    "timestamp": 1773876813000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "176.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "165.0",
                    "isstoppoint": "0",
                    "la": "29.942801",
                    "lo": "123.218536",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "8.7",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 07:43:53",
                    "timestamp": 1773877433000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "179.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "179.0",
                    "isstoppoint": "0",
                    "la": "29.875",
                    "lo": "123.230003",
                    "m": "412371225",
                    "msgid": "27",
                    "n": "ZHONGYUKE211",
                    "sp": "8.0",
                    "src": "171",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 08:12:11",
                    "timestamp": 1773879131000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "168.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "163.0",
                    "isstoppoint": "0",
                    "la": "29.831274",
                    "lo": "123.242119",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "8.8",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 08:31:13",
                    "timestamp": 1773880273000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "171.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "166.0",
                    "isstoppoint": "0",
                    "la": "29.823746",
                    "lo": "123.243202",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "8.9",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 08:34:13",
                    "timestamp": 1773880453000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "183.5",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "175.0",
                    "isstoppoint": "0",
                    "la": "29.781602",
                    "lo": "123.246013",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "8.5",
                    "src": "50023",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 08:50:53",
                    "timestamp": 1773881453000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "169.4",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "159.0",
                    "isstoppoint": "0",
                    "la": "29.73874",
                    "lo": "123.247777",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "8.0",
                    "src": "50214",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 09:08:33",
                    "timestamp": 1773882513000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "175.6",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "87.0",
                    "isstoppoint": "0",
                    "la": "29.737605",
                    "lo": "123.247282",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "1.2",
                    "src": "50214",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 09:29:33",
                    "timestamp": 1773883773000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "195.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "195.0",
                    "isstoppoint": "0",
                    "la": "29.711967",
                    "lo": "123.243851",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "9.3",
                    "src": "1221",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 09:55:54",
                    "timestamp": 1773885354000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "179.7",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "180.0",
                    "isstoppoint": "0",
                    "la": "29.666322",
                    "lo": "123.244383",
                    "m": "412371225",
                    "msgid": "1",
                    "n": "ZHONGYUKE211",
                    "sp": "8.5",
                    "src": "50214",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 10:14:33",
                    "timestamp": 1773886473000,
                    "z": "0"
                },
                {
                    "accumulatetime": "-",
                    "co": "172.0",
                    "dis": "297.7304961346104",
                    "displayzoom": "12",
                    "frmt": "0",
                    "hdg": "172.0",
                    "isstoppoint": "0",
                    "la": "29.52",
                    "lo": "123.25",
                    "m": "412371225",
                    "msgid": "27",
                    "n": "ZHONGYUKE211",
                    "sp": "7.0",
                    "src": "171",
                    "starttime": "-",
                    "stoptime": "-",
                    "ti": "2026-03-19 11:18:08",
                    "timestamp": 1773890288000,
                    "z": "0"
                }
            ],
      source: new VectorSource(),
      pointSource: new VectorSource(), // 用于船舶动画
      pathSource: new VectorSource(), // 用于路径线条
      markerSource: new VectorSource(), // 用于点位标记
      drawnPoints: [], // 已走过的点位记录
      pointLayer: null,
      pathLayer: null, // 路径图层
      markerLayer: null, // 点位标记图层
      startImg: startImg,
      chuanImg: chuanImg,
      marker_point: marker_point,
      marker_action: marker_action,
      ship_end: ship_end,
      ship_start: ship_start,
      modify: null,
      pointLists: [],
      tk: "b9031f80391e6b65bd1dd80dcde1b097",
      mapType: 1,
      mapBaseUrl3:
        "http://t0.tianditu.gov.cn/cva_w/wmts?tk=" +
        tk +
        "&service=wmts&request=GetTile&version=1.0.0&layer=cva&style=default&format=tiles&tileMatrixSet=w&tileMatrix={z}&tileRow={y}&tileCol={x}",
      mapBaseUrl1:
        "http://t0.tianditu.gov.cn/vec_w/wmts?tk=" +
        tk +
        "&service=wmts&request=GetTile&version=1.0.0&layer=vec&style=default&format=tiles&tileMatrixSet=w&tileMatrix={z}&tileRow={y}&tileCol={x}",
      // mapBaseUrl2: "https://m12.shipxy.com/tile.c?l=Na&m=o&x={x}&y={y}&z={z}",
      // mapBaseUrl1: "https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
      // 动画相关变量
      animationFrameId: null,
      currentPointIndex: 0,
      animationProgress: 0,
      animationSpeed: 0.05,
      boatFeature: null,
      animationCompleted: false,
      showCard: false,
      showCardItem: false, // 最近一次捕捞日志
      cardData: [
        { label: "时间", value: "围网" },
        { label: "船名", value: "船名" },
        { label: "MMSI", value: `412371225` },
        { label: "船首向", value: "191°" },
        { label: "航迹向", value: `188°` },
        { label: "速度", value: `6.1节` },
        { label: "吃水", value: `3.5米` },
        { label: "纬度", value: `35°32'25"N` },
        { label: "京都", value: `121°12'13"E` },
      ],
      clusterSource: null, // 聚合数据源
      clusterLayer: null, // 聚合图层
      activeMarker: null, // 当前激活的点位
    };
  },
  watch: {
    region: {
      handler(val) {
        if (val) {
          console.log("this.region", val);
          this.getShipLine(val);
        }
      },
      deep: true,
    },
  },
  mounted() {
    if (this.$refs.mapContainer) {
   

      this.initMap();
        
      // this.initBoatAnimation();
    }
  },
  beforeDestroy() {
    // 清理动画
    if (this.animationFrameId) {
      cancelAnimationFrame(this.animationFrameId);
    }
  },
  methods: {
    getShipLine(c) {
      this.pointLists = [];
      getShipTrajectory(c).then((res) => {
        if (res.code == 200) {
          if (!res.data.length) {
            this.$toast.success("暂无数据");
          }
          console.log("this.timeArr", this.timeArr);
          const pointList = [];
          const dateToMilliseconds = (dateString) => {
            // 处理不同格式的日期字符串
            if (!dateString) return null;
            // 如果已经是数字类型,直接返回
            if (typeof dateString === "number") {
              return dateString;
            }
            // 如果是10位数字字符串,可能是秒级时间戳
            if (
              typeof dateString === "string" &&
              /^[0-9]{10}$/.test(dateString)
            ) {
              return parseInt(dateString) * 1000;
            }
            // 处理日期字符串,替换短横线为斜杠以兼容Safari
            if (typeof dateString === "string") {
              dateString = dateString.replace(/-/gm, "/");
            }
            return new Date(dateString).getTime() / 1000;
          };
          res.data?.map((item) => {
            if (
              this.timeArr.length > 0 &&
              item.utc >= dateToMilliseconds(this.timeArr[0]) &&
              item.utc <= dateToMilliseconds(this.timeArr[1])
            ) {
              console.log("item.utc", item);
              pointList.push([Number(item.lng), Number(item.lat)]);
            } else {
              pointList.push([Number(item.lng), Number(item.lat)]);
            }
          });
          console.log("pointList", pointList);
          setTimeout(() => {
            this.map.getView().animate({
              center: pointList[0],
              zoom: 10,
              duration: 1000,
            });
          }, 200);
          this.pointLists = pointList;
          this.initBoatAnimation();
        }
      });
    },
    thinPoints(points, zoomNum) {
      if (!points || points.length === 0) return [];

      // 根据缩放级别确定抽稀程度
      let interval = 1;
      if (zoomNum < 8) {
        interval = 10;
      } else if (zoomNum < 10) {
        interval = 5;
      } else if (zoomNum < 12) {
        interval = 3;
      } else if (zoomNum < 18) {
        interval = 2;
      } else {
        interval = 1; // 显示所有点
      }

      return points.filter((point, index) => index % interval === 0);
    },
    updateMarkersByZoom() {
      // 清除现有标记
      this.markerSource.clear();

      // 获取当前缩放级别下的稀疏点
      const thinnedPoints = this.thinPoints(this.pointLists, this.zoomNum);

      // 添加稀疏点到图层
      thinnedPoints.forEach((point) => {
        const markerFeature = new Feature({
          geometry: new Point(point),
        });
        this.markerSource.addFeature(markerFeature);
      });
    },
    changeType(type) {
      this.activeType = type;
    },
    // 初始化地图
    initMap() {
      let TK = "f9a96471e3962600b9e0f579e29e62d1";
      // 创建瓦片图层
      this.tdtLayer1 = new TileLayer({
        source: new XYZ({
          url: this.mapBaseUrl1, //  + this.tk,
        }),
      });
      // 标记图层
      // this.tdtLayer2 = new TileLayer({
      //   source: new XYZ({
      //     // url: this.mapBaseUrl2,
      //     // url: `https://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TK}`,
      //     // url: "http://t0.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=f9a96471e3962600b9e0f579e29e62d1" ,
      //     // url: "http://t0.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=" + this.tk,
      //   }),
      // });
      // 标注图层
      this.tdtLayer3 = new TileLayer({
        source: new XYZ({
          url: this.mapBaseUrl3,
        }),
      });

      // 路径图层(在底图之上,船舶之下)
      this.pathLayer = new VectorLayer({
        source: this.pathSource,
        style: new Style({
          stroke: new Stroke({
            color: "rgb(234, 215, 176)",
            width: 3,
            lineDash: [5, 5],
          }),
        }),
        zIndex: 50,
      });

      // 点位标记图层
      this.markerLayer = new VectorLayer({
        source: this.markerSource,
        style: new Style({
          image: new Icon({
            src: this.marker_point,
            scale: 0.6,
            anchor: [0.5, 0.5],
          }),
        }),
        zIndex: 70,
      });
      this.startEndLayer = new VectorLayer({
        source: new VectorSource(),
        zIndex: 80, // 确保在聚合图层之上
      });
      // 船舶动画图层(最上层)
      this.pointLayer = new VectorLayer({
        source: this.pointSource,
        style: new Style({
          image: new Icon({
            src: this.chuanImg,
            scale: 0.8,
            anchor: [0.5, 0.5],
          }),
        }),
        zIndex: 100,
      });

      // 创建 OpenLayers 地图对象
      this.map = new Map({
        target: this.$refs.mapContainer,
        layers: [
          this.tdtLayer1,
          // this.tdtLayer2,
          this.tdtLayer3,
          this.pathLayer,
          this.markerLayer, // 使用聚合图层
          this.startEndLayer,
          this.pointLayer,
        ],
        view: new View({
          projection: "EPSG:4326",
          center: [122.480077, 36.915106],
          zoom: this.zoomNum,
          minZoom: 2,
          maxZoom: 18,
        }),
      });

      // 地图点击事件
      this.map.on("click", (e) => {
        this.showCard = false;
        this.showCardItem = false;
        console.log('地图点击事件触发');
        
        // 获取点击位置的所有要素
        const features = [];
        this.map.forEachFeatureAtPixel(e.pixel, (feature, layer) => {
          features.push({ feature, layer });
        });
        
        console.log('点击到的所有要素:', features);
        
        // 遍历所有要素,找到markerLayer的要素
        for (const { feature, layer } of features) {
          console.log('处理要素:', feature);
          console.log('要素所属图层:', layer);
          
          // 检查是否是markerLayer的要素
          if (layer === this.markerLayer) {
            console.log('找到markerLayer的要素');
            const clickedCoord = feature.values_.geometry.getCoordinates();
            console.log('点击的坐标:', clickedCoord);
            
            // 从originalData中查找对应的点位数据
            if (this.originalData) {
              console.log('originalData存在,长度:', this.originalData.length);
              const clickedData = this.originalData.find(item => {
                const itemCoord = [Number(item.lo), Number(item.la)];
                return Math.abs(itemCoord[0] - clickedCoord[0]) < 0.00001 && Math.abs(itemCoord[1] - clickedCoord[1]) < 0.00001;
              });
              this.cardData =[]
              if (clickedData) {
                console.log('点击的点位各项数据:', clickedData);
                this.cardData = [
                  { label: "时间", value: clickedData.ti||'-' },
                  { label: "船名", value: clickedData.n||'-' },
                  { label: "MMSI", value: clickedData.m||'-' },
                  { label: "船首向", value: clickedData.hdg +'°'  },
                  { label: "航迹向", value: clickedData.co +'°' },    
                  // { label: "船首向", value: isNaN(Number(clickedData.hdg))?Math.round(Number(clickedData.hdg)) +'°':'-'  },
                  // { label: "航迹向", value: isNaN(Number(clickedData.co))?Math.round(Number(clickedData.co)) +'°':'-' },    
                  { label: "速度", value: clickedData.sp?Number(clickedData.sp)+'节':'-' },
                  { label: "吃水", value:  3.5+'米' },
                  { label: "纬度", value: clickedData.la?(clickedData.la+'N'):'-' },
                  { label: "经度", value: clickedData.lo?(clickedData.lo+'E'):'-' },
                ];
                console.log(this.cardData,'this.cardDatathis.cardData');
      //            cardData: [
      //   { label: "时间", value: "围网" },
      //   { label: "船名", value: "船名" },
      //   { label: "MMSI", value: `412371225` },
      //   { label: "船首向", value: "191°" },
      //   { label: "航迹向", value: `188°` },
      //   { label: "速度", value: `6.1节` },
      //   { label: "吃水", value: `3.5米` },
      //   { label: "纬度", value: `35°32'25"N` },
      //   { label: "京都", value: `121°12'13"E` },
      // ],

              } else {
                console.log('没有找到对应的点位数据');
              }
            } else {
              console.log('originalData不存在');
            }
            
            this.addMarkerAction(feature.values_.geometry.getCoordinates());
            const pixel = e.pixel;
            const mapContainer = this.$refs.mapContainer;
            const containerRect = mapContainer.getBoundingClientRect();
            const containerWidth = containerRect.width;
            const containerHeight = containerRect.height;

            const xRatio = pixel[0] / containerWidth;
            const yRatio = pixel[1] / containerHeight;

            const horizontalPos = xRatio < 0.5 ? "left" : "right";
            const verticalPos = yRatio < 0.5 ? "top" : "bottom";

            // 找到点击的索引
            const clickedIndex = this.originalData.findIndex(item => {
              const itemCoord = [Number(item.lo), Number(item.la)];
              return Math.abs(itemCoord[0] - clickedCoord[0]) < 0.00001 && Math.abs(itemCoord[1] - clickedCoord[1]) < 0.00001;
            });
            
            if (clickedIndex === this.originalData.length - 1) {
              this.showCardItem = true;
            } else {
              this.showCard = true;
            }

            this.$nextTick(() => {
              const cardElement = document.querySelector(".card-box");
              const cardElementItem = document.querySelector(".card-box-item");
              if (cardElement) {
                cardElement.style.left = "";
                cardElement.style.right = "";
                cardElement.style.top = "";
                cardElement.style.bottom = "";

                // 计算卡片位置,确保在点击点附近
                let cardLeft, cardTop;
                
                // 右侧空间不足时显示在左侧
                if (pixel[0] > containerWidth - 200) {
                  cardLeft = pixel[0] - 210;
                } else {
                  cardLeft = pixel[0] + 10;
                }
                
                // 底部空间不足时显示在上方
                if (pixel[1] > containerHeight - 120) {
                  cardTop = pixel[1] - 160;
                } else {
                  cardTop = pixel[1] + 10;
                }
                
                // 确保卡片在容器内
                cardLeft = Math.max(10, Math.min(cardLeft, containerWidth - 210));
                cardTop = Math.max(10, Math.min(cardTop, containerHeight - 160));

                cardElement.style.left = `${cardLeft}px`;
                cardElement.style.top = `${cardTop}px`;

                cardElement.style.position = "absolute";
                cardElement.style.zIndex = "200";
              }
              if (cardElementItem) {
                cardElementItem.style.left = "";
                cardElementItem.style.right = "";
                cardElementItem.style.top = "";
                cardElementItem.style.bottom = "";

                // 计算卡片位置,确保在点击点附近
                let cardLeft, cardTop;
                
                // 右侧空间不足时显示在左侧
                if (pixel[0] > containerWidth - 160) {
                  cardLeft = pixel[0] - 170;
                } else {
                  cardLeft = pixel[0] + 10;
                }
                
                // 底部空间不足时显示在上方
                if (pixel[1] > containerHeight - 100) {
                  cardTop = pixel[1] - 110;
                } else {
                  cardTop = pixel[1] + 10;
                }
                
                // 确保卡片在容器内
                cardLeft = Math.max(10, Math.min(cardLeft, containerWidth - 170));
                cardTop = Math.max(10, Math.min(cardTop, containerHeight - 110));

                cardElementItem.style.left = `${cardLeft}px`;
                cardElementItem.style.top = `${cardTop}px`;

                cardElementItem.style.position = "absolute";
                cardElementItem.style.zIndex = "200";
              }
            });
            break; // 找到markerLayer的要素后跳出循环
          }
        }
      });
      this.map.on("movestart", () => {
        this.showCard = false;
        this.showCardItem = false;
        console.log(this.map.getView().getZoom());
         this.updateClusterDisplay();
      });

      // 地图缩放事件,用于动态调整聚合
      this.moveendHandler = () => {
        console.log('moveend event triggered, zoom:', this.map.getView().getZoom());
        if (this.originalData) {
          console.log('1updating cluster display...');
         
        }
      };
      this.map.on('moveend', this.moveendHandler);

      this.modify = new Modify({ source: this.source, style: modifyStyle });
      // 隐藏缩放按钮
      document.getElementsByClassName("ol-zoom")[0].style.display = "none";
      this.getShipLineS(this.guijis);
    },
    getShipLineS(a){
      if (!a || !Array.isArray(a) || a.length === 0) {
        return;
      }
      // 保存原始数据
      this.originalData = a;
      const coordinates = a.map(item => [Number(item.lo), Number(item.la)]);
      
      if (coordinates.length < 2) {
        return;
      }
      

      if (coordinates.length > 0) {
        // 暂时移除 moveend 事件监听,避免动画过程中触发刷新
        this.map.un('moveend', this.moveendHandler);
        this.map.getView().animate({
          center: coordinates[coordinates.length - 1], // 使用最后一个点作为地图中心
          zoom: 8, // 调整缩放级别为9
          duration: 1,
        });
        // 添加上船的动画效果
        
        
        this.initShipAnimation(coordinates);
        
        // 动画初始化后重新更新标记点显示
        setTimeout(() => {
          this.updateClusterDisplay();
        }, 100);
      }
    },
    
    // 初始化船舶动画
    initShipAnimation(coordinates) {
      // 清除已有船舶要素
      // this.pathSource.clear();
      // 绘制轨迹线(方向线/流向线)
      const lineFeature = new Feature({
        geometry: new LineString(coordinates)
      });

      lineFeature.setStyle(new Style({
        stroke: new Stroke({
          color: 'rgb(234, 215, 176)',
          width: 3
        })
      }));

      this.pathSource.addFeature(lineFeature);
      
      // 为线段添加箭头,放在线段中点
      let lastSegmentAngle = 0; // 存储最后一个线段的角度
      if (coordinates.length > 1) {
        for (let i = 1; i < coordinates.length; i++) {
          // 计算线段中点
          const midX = (coordinates[i-1][0] + coordinates[i][0]) / 2;
          const midY = (coordinates[i-1][1] + coordinates[i][1]) / 2;
          
          // 计算当前线段的方向角度(动态方向)
          const dx = coordinates[i][0] - coordinates[i-1][0];
          const dy = coordinates[i][1] - coordinates[i-1][1];
          let segmentAngle = Math.atan2(dy, dx);
          
          // 存储最后一个线段的角度
          if (i === coordinates.length - 1) {
            lastSegmentAngle = segmentAngle;
          }
          
          // 调整旋转角度,确保箭头指向线段的正确方向
          segmentAngle += Math.PI / 2;
          
          // 创建箭头要素
          const arrowFeature = new Feature({
            geometry: new Point([midX, midY])
          });
          
          // 创建箭头样式 - 使用jiantou图片作为箭头
          const arrowStyle = new Style({
            image: new Icon({
              src: this.jiantou, // 使用jiantou图片
              scale: 0.05, // 调整图片大小
              rotation: - segmentAngle, // 根据线段方向旋转图片
              anchor: [0.5, 0.5] // 设置锚点为图片中心
            })
          });
          
          arrowFeature.setStyle(arrowStyle);
          this.pathSource.addFeature(arrowFeature);
        }
      }
      
      // 创建船舶要素
      this.shipFeature = new Feature({
        geometry: new Point(coordinates[0])
      });
      
      // 设置船舶样式
      this.shipFeature.setStyle(new Style({
        image: new Icon({
          src: this.chuanImg,
          scale: 0.8,
          anchor: [0.5, 0.5]
        })
      }));
      
      this.pathSource.addFeature(this.shipFeature);
      
      // 开始船舶动画
      this.startShipAnimation(coordinates);
    },
    
    // 开始船舶动画
    startShipAnimation(coordinates) {
      let currentIndex = 0;
      let progress = 0;
      const duration = 5000; // 动画总时长
      const startTime = Date.now();
      
      const animate = () => {
        const elapsed = Date.now() - startTime;
        progress = Math.min(elapsed / duration, 1);
        
        // 计算当前位置
        const totalPoints = coordinates.length;
        const targetIndex = Math.min(Math.floor(progress * totalPoints), totalPoints - 1);
        const t = (progress * totalPoints) % 1;
        
        if (targetIndex < totalPoints - 1) {
          const currentPoint = coordinates[targetIndex];
          const nextPoint = coordinates[targetIndex + 1];
          
          // 线性插值计算当前位置
          const currentPosition = [
            currentPoint[0] + (nextPoint[0] - currentPoint[0]) * t,
            currentPoint[1] + (nextPoint[1] - currentPoint[1]) * t
          ];
          
          // 更新船舶位置
          this.shipFeature.getGeometry().setCoordinates(currentPosition);
          
          // 计算并更新船舶方向
          const dx = nextPoint[0] - currentPoint[0];
          const dy = nextPoint[1] - currentPoint[1];
          let angle = Math.atan2(dy, dx);
          angle += Math.PI / 2;
          
          this.shipFeature.setStyle(new Style({
            image: new Icon({
              src: this.chuanImg,
              scale: 0.8,
              rotation: -angle,
              anchor: [0.5, 0.5]
            })
          }));
        } else if (targetIndex === totalPoints - 1) {
          // 到达终点
          this.shipFeature.getGeometry().setCoordinates(coordinates[totalPoints - 1]);
        }
        
        if (progress < 1) {
          requestAnimationFrame(animate);
        }
      };
      
      animate();
    },

    // 根据缩放级别更新聚合显示
    updateClusterDisplay() {
      if (!this.originalData) {
        return;
      }
      this.pathSource.clear();
      this.markerSource.clear();
      const coordinates = this.originalData.map(item => [Number(item.lo), Number(item.la)]);
      // 绘制轨迹线(方向线/流向线)
      const lineFeature = new Feature({
        geometry: new LineString(coordinates)
      });

      lineFeature.setStyle(new Style({
        stroke: new Stroke({
          color: 'rgb(234, 215, 176)',
          width: 3
          // 移除虚线,使用实线作为方向线
        })
      }));

      this.pathSource.addFeature(lineFeature);

      // 为线段添加箭头,放在线段中点
      let lastSegmentAngle = 0; // 存储最后一个线段的角度
      if (coordinates.length > 1) {
        for (let i = 1; i < coordinates.length; i++) {
          // 计算线段中点
          const midX = (coordinates[i-1][0] + coordinates[i][0]) / 2;
          const midY = (coordinates[i-1][1] + coordinates[i][1]) / 2;
          
          // 计算当前线段的方向角度(动态方向)
          const dx = coordinates[i][0] - coordinates[i-1][0];
          const dy = coordinates[i][1] - coordinates[i-1][1];
          let segmentAngle = Math.atan2(dy, dx);
          
          // 存储最后一个线段的角度
          if (i === coordinates.length - 1) {
            lastSegmentAngle = segmentAngle;
          }
          
          // 调整旋转角度,确保箭头指向线段的正确方向
          // 由于箭头图片默认方向的影响,需要根据实际情况调整角度
          // 这里直接使用计算出的角度,不做额外调整,让箭头图片自然指向线段方向
          segmentAngle += Math.PI / 2; // 注释掉之前的调整
          
          
          // 创建箭头要素
          const arrowFeature = new Feature({
            geometry: new Point([midX, midY])
          });
          
          // 创建箭头样式 - 使用jiantou图片作为箭头
          const arrowStyle = new Style({
            image: new Icon({
              src: this.jiantou, // 使用jiantou图片
              scale: 0.05, // 调整图片大小
              rotation: - segmentAngle, // 根据线段方向旋转图片
              anchor: [0.5, 0.5] // 设置锚点为图片中心
            })
          });
          
          arrowFeature.setStyle(arrowStyle);
          this.pathSource.addFeature(arrowFeature);
        }
      }

      const zoom = this.map.getView().getZoom();
       console.log('zoom----------------',zoom,);
      // if (zoom >= 9) {
      //   // 放大到9级以上,显示所有点的时间
      //   this.originalData.forEach((item, index) => {
      //     const coord = [Number(item.lo), Number(item.la)];
          
      //     const markerFeature = new Feature({
      //       geometry: new Point(coord),
      //       data: item
      //     });

      //     const styles = [];

      //     if (index === 0) {
      //       styles.push(new Style({
      //         image: new Icon({
      //           src: this.ship_start,
      //           scale: 0.5,
      //           anchor: [0.5, 0.5]
      //         })
      //       }));
      //     } else if (index === this.originalData.length - 1) {
      //       // 计算最后一个线段的角度并调整船舶图片方向
      //       let shipAngle = lastSegmentAngle;
      //       shipAngle += Math.PI / 2; // 与箭头图片使用相同的调整
            
      //       styles.push(new Style({
      //         image: new Icon({
      //           src: this.chuanImg,
      //           scale: 0.8, // 固定缩放比例
      //           rotation: - shipAngle, // 船的照片方向与最后一个线段的箭头方向一致
      //           anchor: [0.5, 0.5],
      //           // 确保船舶图片在缩放时保持固定大小
      //           // size: [50, 50] // 设置固定大小
      //         })
      //       }));
      //     } else {
      //       styles.push(new Style({
      //         image: new Circle({
      //           radius: 5,
      //           fill: new Fill({ color: 'rgb(234, 215, 176)' }),
      //           stroke: new Stroke({ color: '#fff', width: 2 })
      //         })
      //       }));
      //     }

      //     // 显示每个点的时间
      //     styles.push(new Style({
      //       text: new Text({
      //         text: item.ti,
      //         font: '10px Arial',
      //         fill: new Fill({ color: '#333' }),
      //         stroke: new Stroke({ color: '#fff', width: 2 }),
      //         offsetX: 0,
      //         offsetY: -15,
      //         placement: 'point',
      //         backgroundFill: new Fill({ color: '#fff' }),
      //         backgroundStroke: new Stroke({ color: '#ccc', width: 1 }),
      //         padding: [2, 4, 2, 4]
      //       })
      //     }));

      //     // 始终显示停靠时间
      //     if (item.starttime && item.stoptime && item.starttime !== '-' && item.stoptime !== '-') {
      //       const startTime = new Date(item.starttime);
      //       const stopTime = new Date(item.stoptime);
      //       const duration = Math.abs(stopTime - startTime) / (1000 * 60);
      //       const hours = Math.floor(duration / 60);
      //       const minutes = Math.floor(duration % 60);
      //       const stopDuration = `停靠:${hours}h${minutes}m`;

      //       styles.push(new Style({
      //         text: new Text({
      //           text: stopDuration,
      //           font: '10px Arial',
      //           fill: new Fill({ color: '#fff' }),
      //           offsetX: 0,
      //           offsetY: 15,
      //           placement: 'point',
      //           backgroundFill: new Fill({ color: '#00f' }),
      //           backgroundStroke: new Stroke({ color: '#ccc', width: 1 }),
      //           padding: [2, 4, 2, 4]
      //         })
      //       }));
      //     }

      //     markerFeature.setStyle(styles);
      //     this.markerSource.addFeature(markerFeature);
      //   });
      // } else {
        // 缩放级别较低(zoom ≤ 9),每隔3个点显示一个时间
        this.originalData.forEach((item, index) => {
          const coord = [Number(item.lo), Number(item.la)];
          
          const markerFeature = new Feature({
            geometry: new Point(coord),
            data: item
          });

          const styles = [];

          if (index === 0) {
            styles.push(new Style({
              image: new Icon({
                src: this.ship_start,
                scale: 0.5,
                anchor: [0.5, 0.5]
              })
            }));
          } else if (index === this.originalData.length - 1) {
            // 计算最后一个线段的角度并调整船舶图片方向
            let shipAngle = lastSegmentAngle;
            shipAngle += Math.PI / 2; // 与箭头图片使用相同的调整
            
            styles.push(new Style({
              image: new Icon({
                src: this.chuanImg,
                scale: 1, // 固定缩放比例
                rotation: - shipAngle, // 船的照片方向与最后一个线段的箭头方向一致
                anchor: [0.5, 0.5],
                // 确保船舶图片在缩放时保持固定大小
                // size: [50, 50] // 设置固定大小
              })
            }));
          } else {
            styles.push(new Style({
              image: new Circle({
                radius: 5,
                fill: new Fill({ color: 'rgb(234, 215, 176)' }),
                stroke: new Stroke({ color: '#fff', width: 2 })
              })
            }));
          }

          // 每隔3个点显示时间
          if (index === 0 || index === this.originalData.length - 1 || index % 6 === 0) {
            styles.push(new Style({
              text: new Text({
                text: item.ti,
                font: '10px Arial',
                fill: new Fill({ color: '#333' }),
                stroke: new Stroke({ color: '#fff', width: 2 }),
                offsetX: 0,
                offsetY: -15,
                placement: 'point',
                backgroundFill: new Fill({ color: '#fff' }),
                backgroundStroke: new Stroke({ color: '#ccc', width: 1 }),
                padding: [2, 4, 2, 4]
              })
            }));
          }

          // 始终显示停靠时间
          if (item.starttime && item.stoptime && item.starttime !== '-' && item.stoptime !== '-') {
            const startTime = new Date(item.starttime);
            const stopTime = new Date(item.stoptime);
            const duration = Math.abs(stopTime - startTime) / (1000 * 60);
            const hours = Math.floor(duration / 60);
            const minutes = Math.floor(duration % 60);
            const stopDuration = `停:${hours}h${minutes}m`;

            styles.push(new Style({
              text: new Text({
                text: stopDuration,
                font: '10px Arial',
                fill: new Fill({ color: '#fff' }),
                offsetX: 0,
                offsetY: 15,
                placement: 'point',
                backgroundFill: new Fill({ color: '#00f' }),
                backgroundStroke: new Stroke({ color: '#ccc', width: 1 }),
                padding: [2, 4, 2, 4]
              })
            }));
          }

          markerFeature.setStyle(styles);
          this.markerSource.addFeature(markerFeature);
        });
      // }
    },

    // 初始化船舶动画
    // 修改initBoatAnimation方法,在动画开始时添加标记点抽稀逻辑
    initBoatAnimation() {
      // 清除已有要素(增强清理逻辑)
      this.pointSource.clear();
      // 不要清除markerSource,因为标记点的显示由updateClusterDisplay方法负责
      // this.markerSource.clear();
      this.pathSource.clear();
      this.startEndLayer.getSource().clear(); // 清空起点终点图层
      this.drawnPoints = [];
      this.animationFrameId = null; // 确保动画帧ID被重置

      // 创建船舶要素并明确设置样式
      this.boatFeature = new Feature({
        geometry: new Point(this.pointLists[0]),
      });
      // 明确设置船舶图标样式
      this.boatFeature.setStyle(
        new Style({
          image: new Icon({
            src: this.chuanImg,
            scale: 0.8,
            anchor: [0.5, 0.5],
          }),
        })
      );
      this.pointSource.addFeature(this.boatFeature);

      // 添加起点和终点标记(保持不变)
      const startMarker = new Feature({
        geometry: new Point(this.pointLists[0]),
      });
      startMarker.setStyle(
        new Style({
          image: new Icon({
            src: this.ship_start,
            scale: 0.5,
            anchor: [0.5, 0.5],
          }),
        })
      );
      this.startEndLayer.getSource().addFeature(startMarker);

      this.drawnPoints.push(this.pointLists[0]);

      // 重置动画状态
      this.animationCompleted = false;
      this.currentPointIndex = 0;
      this.animationProgress = 0;

      // 开始动画
      this.startAnimation();
    },

    //开始动画
    startAnimation() {
      if (this.animationCompleted || this.animationFrameId) {
        return;
      }

      const animate = () => {
        const currentPoint = this.pointLists[this.currentPointIndex];
        const isLastPoint =
          this.currentPointIndex === this.pointLists.length - 1;
        const nextPointIndex = isLastPoint
          ? this.currentPointIndex
          : this.currentPointIndex + 1;
        const nextPoint = this.pointLists[nextPointIndex];

        this.animationProgress += this.animationSpeed;

        if (this.animationProgress > 1) {
          this.animationProgress = 1;
        }

        const currentPosition = interpolatePoint(
          currentPoint,
          nextPoint,
          this.animationProgress
        );

        this.boatFeature.getGeometry().setCoordinates(currentPosition);
        this.updatePath(currentPosition);

        if (this.animationProgress >= 1) {
          if (isLastPoint) {
            // 动画完成处理
            this.boatFeature.setStyle(null);
            this.pointSource.removeFeature(this.boatFeature);
            setTimeout(() => {
              this.animationCompleted = true;
              this.animationFrameId = null;
              const endMarker = new Feature({
                geometry: new Point(
                  this.pointLists[this.pointLists.length - 1]
                ),
              });
              endMarker.setStyle(
                new Style({
                  image: new Icon({
                    src: this.ship_end,
                    scale: 0.5,
                    anchor: [0.5, 0.5],
                  }),
                })
              );
              this.startEndLayer.getSource().addFeature(endMarker);

              // 动画完成后更新标记点并添加缩放监听器
              this.zoomNum = this.map.getView().getZoom();
              this.updateMarkersByZoom();

              this.map.getView().on("change:resolution", () => {
                this.zoomNum = this.map.getView().getZoom();
                this.updateMarkersByZoom();
              });
            }, 100);
            return;
          } else {
            // 只有当船舶到达下一个点时才更新标记点(使用固定zoom=8抽稀)
            this.animationProgress = 0;
            this.currentPointIndex = nextPointIndex;
            this.drawnPoints.push(nextPoint);

            // 更新标记点(使用固定zoom=8抽稀)
            this.markerSource.clear();
            const thinnedPoints = this.thinPoints(
              this.pointLists.slice(0, nextPointIndex + 1),
              8
            );
            thinnedPoints.forEach((point) => {
              const markerFeature = new Feature({
                geometry: new Point(point),
              });
              this.markerSource.addFeature(markerFeature);
            });
          }
        }

        this.animationFrameId = requestAnimationFrame(animate);
      };

      if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId);
      }
      this.animationFrameId = requestAnimationFrame(animate);
    },

    // 添加点位标记
    addMarker(coord) {
      const markerFeature = new Feature({
        geometry: new Point(coord),
      });
      markerFeature.setStyle(
        new Style({
          image: new Icon({
            src: this.marker_point,
            scale: 0.7,
            anchor: [0.5, 0.5],
          }),
        })
      );
      this.markerSource.addFeature(markerFeature);
    },
    addMarkerAction(coord) {
      if (this.activeMarker) {
        this.startEndLayer.getSource().removeFeature(this.activeMarker);
      }
      const markerFeature = new Feature({
        geometry: new Point(coord),
      });
      markerFeature.setStyle(
        new Style({
          image: new Icon({
            src: this.marker_action,
            scale: 0.6,
            anchor: [0.5, 0.5],
          }),
        })
      );
      this.startEndLayer.getSource().addFeature(markerFeature);
      this.activeMarker = markerFeature;
    },

    // 更新路径线条 - 只显示已走过的路径
    updatePath(currentPosition) {
      // 复制已走过的点并添加当前位置
      const pathPoints = [...this.drawnPoints, currentPosition];

      // 清除现有路径并添加新路径
      this.pathSource.clear();
      const pathFeature = new Feature({
        geometry: new LineString(pathPoints),
      });
      this.pathSource.addFeature(pathFeature);
    },

    // 时间选择框改变事件
    selectChange() {},
    // 设置自定义打点要素
    setMarkers(point) {
      const markerDom = document.createElement("img");
      markerDom.src = this.startImg;
      markerDom.style.width = "30px";
      markerDom.style.height = "30px";
      markerDom.setAttribute("class", "location-active");
      const marker = new Overlay({
        element: markerDom,
        position: point,
        offset: [-30, -30],
        autoPan: false,
      });
      this.map.addOverlay(marker);
      setTimeout(() => {
        this.map.getView().animate({
          center: point,
          zoom: 10,
          duration: 1000,
        });
      }, 200);
    },
    isFirstPoint(coordinates) {
      if (!this.pointLists || this.pointLists.length === 0) return false;
      const firstPoint = this.pointLists[0];
      return (
        coordinates[0] === firstPoint[0] && coordinates[1] === firstPoint[1]
      );
    },

    isLastPoint(coordinates) {
      if (!this.pointLists || this.pointLists.length === 0) return false;
      const lastPoint = this.pointLists[this.pointLists.length - 1];
      return coordinates[0] === lastPoint[0] && coordinates[1] === lastPoint[1];
    },
    // 改变瓦片图层
    changeBaseMap(type) {
      if (this.map) {
        this.mapType = type;
        if (this.mapType == 1) {
          // 海图
          this.mapBaseUrl =
            "https://m12.shipxy.com/tile.c?l=Na&m=o&x={x}&y={y}&z={z}"; //  + this.tk;
          //   "http://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=" + this.tk;
        } else {
          this.mapBaseUrl =
            "http://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=" +
            this.tk;
          //  "https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}";
        }
        // 重新加载图层
        this.tdtLayer1.setSource(
          new XYZ({
            url: this.mapBaseUrl,
          })
        );
      }
    },
  },
};
</script>

template

javascript 复制代码
<template>
  <div class="map_box">
    <div id="mapDiv" class="map" ref="mapContainer">
    <!-- 渔船选择框 -->
    <div v-if="showCard" class="card-box">
      <div v-for="(item, index) in cardData" :key="index" class="flex">
        <div class="data_label">{{ item.label }}</div>
        <div class="data_value">{{ item.value }}</div>
      </div>
    </div>
    <div v-if="showCardItem" class="card-box-item">
      <div class="item">作业时间</div>
      <div class="item">2025.10.08 13:30:25</div>
    </div>
    </div>
  </div>
</template>

css

javascript 复制代码
<style lang="scss">
.baseSelect.el-popper[x-placement^="bottom"] .popper__arrow {
  border-bottom-color: rgba(0, 42, 84, 0.6);
}

.baseSelect.el-popper[x-placement^="bottom"] .popper__arrow::after {
  border-bottom-color: rgba(0, 42, 84, 0.6);
}

.baseSelect {
  background-color: rgba(0, 42, 84, 0.6);
  border: 1px solid;
  color: #fff;
  border-image: linear-gradient(
      360deg,
      rgba(0, 206, 170, 0.19),
      rgba(0, 206, 170, 0)
    )
    1 1;
  border-radius: 0;

  .el-input__inner {
    background-color: rgba(0, 42, 84, 0.3);
    border: 1px solid transparent;
    color: #fff;
  }

  .el-input.is-disabled {
    .el-input__inner {
      background-color: rgba(0, 42, 84, 0.3);
      border: 1px solid transparent;
      color: #fff;
    }
  }

  .el-date-range-picker__header {
    .el-picker-panel__icon-btn {
      color: #fff;
    }
  }

  .el-date-table {
    tr {
      th {
        color: #fff;
      }
    }

    td.in-range {
      div {
        background-color: rgba(0, 42, 84, 0.3);
      }
    }
  }

  .el-select-dropdown__item {
    color: #ffffff;
    font-size: 1.33rem;
    border: none;
  }

  .el-select-dropdown__item.hover,
  .el-select-dropdown__item:hover {
    background-color: rgba(125, 240, 242, 0.08);
  }

  .el-select-dropdown__item.selected {
    background-color: rgba(0, 183, 255, 0.3);
    color: #53b2d9;
  }

  .el-picker-panel__footer {
    background-color: transparent;

    .el-button {
      background-color: rgba(0, 183, 255, 0.6);
      color: #fff;
      border-color: transparent;
    }

    .el-button--text {
      background-color: transparent;
      color: #fff;
    }

    .el-button.is-disabled.is-plain {
      color: #fff;
      background-color: rgba(0, 183, 255, 0.6);
      border-color: transparent;
    }
  }
}
</style>
<style lang="scss" scoped>
相关推荐
23.1 小时前
【Java】NIO零拷贝技术揭秘:CPU不参与的数据传输
java·开发语言·nio
宸津-代码粉碎机1 小时前
SpringBoot 任务执行链路追踪实战:TraceID 透传全解析,实现从调度到执行的全链路可观测
开发语言·人工智能·spring boot·后端·python
漫随流水2 小时前
HTML和CSS和JavaScript的区别
javascript·css·html
茉莉玫瑰花茶2 小时前
CMake 工程指南 - 工程场景(5)
开发语言·c++·cmake
小J听不清2 小时前
CSS 浮动(float)全解析:布局 / 文字环绕 / 清除浮动
前端·javascript·css·html·css3
wuhen_n2 小时前
生产环境极致优化:拆包、图片压缩、Gzip/Brotli 完全指南
前端·javascript·vue.js
想做后端的前端2 小时前
Lua的元表和元方法
开发语言·junit·lua
大尚来也2 小时前
Spring Boot 3 + Spring Cloud 2026 微服务实战:云原生、AI 融合与架构演进
开发语言
a1117762 小时前
Three.js 3D模型动画展示项目(开源)
开发语言·javascript·ecmascript