

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>