前言
在许多卫星应用场景中,我们需要 基于 TLE(Two-Line Element Set, 两行根数)计算卫星轨迹,并在地图上进行可视化。本文将使用 Vue 3 + OpenLayers + satellite.js,实现 实时计算卫星轨迹,并在地图上动态更新卫星位置,最终效果如下:
📌 功能概览:
- 解析 TLE 数据,计算卫星位置和轨迹。
- 使用 OpenLayers 渲染地图,并展示卫星运动轨迹。
- 每秒动态更新卫星位置,显示卫星的实时飞行状态。
1. 依赖安装
首先,我们需要安装以下依赖:
- OpenLayers:用于地图渲染和矢量图层管理。
- satellite.js:用于解析 TLE 并计算卫星轨迹。
- dayjs:用于处理时间。
在 Vue 3 项目中运行以下命令:
npm install ol satellite.js dayjs
2. 代码实现
<!--
* @Author: 彭麒
* @Date: 2025/3/7
* @Email: 1062470959@qq.com
* @Description: 此源码版权归吉檀迦俐所有,可供学习和借鉴或商用。
-->
<template>
<div class="container">
<div class="w-full flex justify-center flex-wrap">
<div class="font-bold text-[24px]">在Vue3中使用OpenLayers根据两行根数计算并显示卫星轨迹(EPSG:3857)</div>
</div>
<div id="vue-openlayers"></div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import OSM from "ol/source/OSM";
import TileLayer from "ol/layer/Tile";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import { Point, LineString } from "ol/geom";
import Feature from "ol/Feature";
import Style from "ol/style/Style";
import Stroke from "ol/style/Stroke";
import Icon from "ol/style/Icon";
import { fromLonLat } from "ol/proj";
import * as satellite from 'satellite.js'; // 引入 satellite.js 库
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import satimg from '@/assets/OpenLayers/satellite.png'; // 引入卫星图标
dayjs.extend(utc);
const map = ref(null);
// const satimg = new URL("../assets/img/satellite.svg", import.meta.url).href;
const tleLine1 =
"1 25544U 98067A 19156.50900463 .00003075 00000-0 59442-4 0 9992";
const tleLine2 =
"2 25544 51.6433 59.2583 0008217 16.4489 347.6017 15.51174618173442";
const satelliteSource = new VectorSource({ wrapX: true });
const satelliteTrackSource = new VectorSource({ wrapX: true });
let timerId = null;
// 计算卫星轨迹
const getSatTrack = () => {
let curTime = new Date();
let lineData = [];
for (let i = 0; i < 50; i++) {
let newTimePoint = dayjs(curTime).add(i, "minute").toDate();
lineData.push(onePoint(newTimePoint));
}
showTrack(lineData);
};
// 根据时间获取卫星的坐标点
const onePoint = (timePoint) => {
let satrec = satellite.twoline2satrec(tleLine1, tleLine2);
let positionAndVelocity = satellite.propagate(satrec, timePoint);
let positionEci = positionAndVelocity.position;
let gmst = satellite.gstime(timePoint);
let positionGd = satellite.eciToGeodetic(positionEci, gmst);
let lon = satellite.degreesLong(positionGd.longitude);
let lat = satellite.degreesLat(positionGd.latitude);
return fromLonLat([lon, lat]);
};
// 获取卫星信息
const getSatInfo = () => {
let curPoint = onePoint(new Date());
let futurePoint = onePoint(dayjs(new Date()).add(5, "minute").toDate());
let dx = futurePoint[0] - curPoint[0];
let dy = futurePoint[1] - curPoint[1];
let rotation = Math.atan2(dy, dx) + 0.887;
showPoint(curPoint, -rotation);
};
// 显示卫星
const showPoint = (coords, rotation) => {
satelliteSource.clear();
let pointFeature = new Feature({
geometry: new Point(coords),
});
pointFeature.setStyle(satStyle(rotation));
satelliteSource.addFeature(pointFeature);
};
// 显示卫星轨迹
const showTrack = (coords) => {
satelliteTrackSource.clear();
let lineFeature = new Feature({
geometry: new LineString(coords),
});
lineFeature.setStyle(trackStyle());
satelliteTrackSource.addFeature(lineFeature);
};
// 轨迹样式
const trackStyle = () =>
new Style({
stroke: new Stroke({
width: 2,
color: "orange",
}),
});
// 卫星样式
const satStyle = (rotation) =>
new Style({
image: new Icon({
src: satimg,
anchor: [0.5, 0.5],
color: "#f00",
scale: 0.1,
rotation: rotation,
}),
});
const initMap = () => {
map.value = new Map({
target: "vue-openlayers",
layers: [
new TileLayer({ source: new OSM() }),
new VectorLayer({ source: satelliteTrackSource }),
new VectorLayer({ source: satelliteSource }),
],
view: new View({
center: fromLonLat([116, 39]),
projection: "EPSG:3857",
zoom: 2,
}),
});
getSatTrack();
timerId = setInterval(getSatInfo, 1000);
};
onMounted(initMap);
onBeforeUnmount(() => {
clearInterval(timerId);
});
</script>
<style scoped>
.container {
width: 840px;
height: 520px;
margin: 50px auto;
border: 1px solid #42b983;
}
#vue-openlayers {
width: 800px;
height: 400px;
margin: 0 auto;
border: 1px solid #42b983;
position: relative;
}
</style>
3. 运行效果
🌍 实现功能:
- 地图加载后,自动计算卫星轨迹。
- 每秒更新卫星位置,展示实时飞行状态。
- 卫星图标旋转,与飞行方向一致。
📌 优化方向:
- 支持更多 TLE 数据,让用户输入不同的卫星信息。
- 交互优化,点击卫星查看详细参数。
- 动态轨迹,持续绘制最新轨迹点,而不是每次清空重绘。
4. 结语
本文介绍了如何使用 Vue 3 + OpenLayers + satellite.js 计算并展示 卫星轨迹,希望对你有所帮助!🚀 如果觉得有用,欢迎点赞、收藏! 🎉