83.在 Vue3 中使用 OpenLayers 利用 TLE 计算并显示单个卫星的轨迹

1. 前言

在可视化开发中,卫星轨迹的实时计算与展示是一个比较有趣的应用场景。TLE(Two-Line Element Set)是一种用于描述卫星轨道参数的格式,我们可以通过 satellite.js 解析 TLE 数据,并计算卫星在任意时间点的位置。

本文介绍如何在 Vue3 中使用 OpenLayers,结合 satellite.js 解析 TLE 数据,实现卫星轨迹的动态计算和可视化展示。


2. 项目技术栈

在本示例中,我们使用以下技术:

  • Vue3 + Composition API —— 现代化 Vue 组件开发方式
  • OpenLayers —— 强大的地图渲染库
  • satellite.js —— 计算卫星轨迹的 JS 库
  • dayjs —— 处理日期和时间

3. 安装依赖

在 Vue3 项目中,我们需要安装 OpenLayerssatellite.js 这两个核心库:

npm install ol satellite.js dayjs

4. 代码实现

4.1 组件结构

我们使用 Vue3 的 Composition API,并封装一个 Map 组件,实现以下功能:

  • 使用 OpenLayers 创建地图并加载 OSM 底图;
  • 解析 TLE 计算卫星的位置;
  • 计算并绘制卫星的轨迹;
  • 实时更新卫星位置。

完整代码如下:

<template><div class="container"><div class="w-full flex justify-center flex-wrap"><div class="font-bold text-[24px]">在Vue3中使用OpenLayers利用TLE动态计算并显示单个卫星的位置及轨迹</div></div><div id="vue-openlayers"></div></div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue'; // 引入 Vue 的 ref, onMounted 和 onUnmounted 函数
import 'ol/ol.css'; // 引入 OpenLayers 的 CSS 样式
import Map from 'ol/Map'; // 引入 OpenLayers 的 Map 类
import View from 'ol/View'; // 引入 OpenLayers 的 View 类
import OSM from 'ol/source/OSM'; // 引入 OpenLayers 的 OSM 类
import TileLayer from 'ol/layer/Tile'; // 引入 OpenLayers 的 TileLayer 类
import VectorLayer from 'ol/layer/Vector'; // 引入 OpenLayers 的 VectorLayer 类
import VectorSource from 'ol/source/Vector'; // 引入 OpenLayers 的 VectorSource 类
import { Point, LineString } from 'ol/geom'; // 引入 OpenLayers 的 Point 和 LineString 类
import Feature from 'ol/Feature'; // 引入 OpenLayers 的 Feature 类
import Style from 'ol/style/Style'; // 引入 OpenLayers 的 Style 类
import Fill from 'ol/style/Fill'; // 引入 OpenLayers 的 Fill 类
import Stroke from 'ol/style/Stroke'; // 引入 OpenLayers 的 Stroke 类
import Icon from 'ol/style/Icon'; // 引入 OpenLayers 的 Icon 类
import * as satellite from 'satellite.js'; // 引入 satellite.js 库
import dayjs from 'dayjs'; // 引入 dayjs 库
import utc from 'dayjs/plugin/utc'; // 引入 dayjs 的 utc 插件
import satImg from '@/assets/OpenLayers/satellite.png'; // 引入卫星图标dayjs.extend(utc); // 使用 dayjs 的 utc 插件const map = ref(null); // 定义 map 变量并初始化为 null
const tleLine1 = '1 25544U 98067A   19156.50900463  .00003075  00000-0  59442-4 0  9992'; // 定义 TLE 数据的第一行
const tleLine2 = '2 25544  51.6433  59.2583 0008217  16.4489 347.6017 15.51174618173442'; // 定义 TLE 数据的第二行const satelliteSource = new VectorSource({ wrapX: true }); // 创建一个新的 VectorSource 用于卫星位置
const satelliteTrackSource = new VectorSource({ wrapX: true }); // 创建一个新的 VectorSource 用于卫星轨迹let timerId = null; // 定义定时器 IDconst getSatTrack = () => {let curTime = new Date(); // 获取当前时间let lineData = []; // 定义一个数组用于存储轨迹数据for (let i = 0; i < 50; i++) { // 循环 50 次let newTimePoint = dayjs(curTime).add(i, 'minute').toDate(); // 获取未来的时间点let one = onePoint(newTimePoint); // 计算该时间点的卫星位置lineData.push(one); // 将位置添加到轨迹数据中}showTrack(lineData); // 显示轨迹
};const onePoint = (timePoint) => {let satrec = satellite.twoline2satrec(tleLine1, tleLine2); // 使用 TLE 数据创建卫星记录let positionAndVelocity = satellite.propagate(satrec, timePoint); // 计算卫星在指定时间点的位置和速度let positionEci = positionAndVelocity.position; // 获取卫星的 ECI 坐标let gmst = satellite.gstime(timePoint); // 计算格林尼治平恒时let positionGd = satellite.eciToGeodetic(positionEci, gmst); // 将 ECI 坐标转换为地理坐标let lonlat = [satellite.degreesLong(positionGd.longitude), // 获取经度satellite.degreesLat(positionGd.latitude), // 获取纬度];return lonlat; // 返回经纬度
};const getSatInfo = () => {let aaa = onePoint(new Date()); // 获取当前时间的卫星位置let min5 = dayjs(new Date()).add(5, 'minute').toDate(); // 获取 5 分钟后的时间let bbb = onePoint(min5); // 获取 5 分钟后的卫星位置let dx = bbb[0] - aaa[0]; // 计算经度差let dy = bbb[1] - aaa[1]; // 计算纬度差let rotation = Math.atan2(dy, dx) + 0.887; // 计算卫星的旋转角度showPoint(aaa, -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 = () => {return new Style({fill: new Fill({ color: '#00f' }), // 设置填充颜色stroke: new Stroke({ width: 2, color: '#f00' }), // 设置描边颜色和宽度});
};const satStyle = (rotation) => {return new Style({image: new Icon({src: satImg, // 设置图标的源anchor: [0.5, 0.5], // 设置图标的锚点scale: 0.1, // 设置图标的缩放比例rotation: rotation, // 设置图标的旋转角度}),});
};const initMap = () => {let satelliteLayer = new VectorLayer({source: satelliteSource, // 创建一个新的矢量图层用于卫星位置});let satelliteTrackLayer = new VectorLayer({source: satelliteTrackSource, // 创建一个新的矢量图层用于卫星轨迹});map.value = new Map({layers: [new TileLayer({ source: new OSM() }), // 创建一个新的瓦片图层satelliteTrackLayer, // 添加卫星轨迹图层satelliteLayer, // 添加卫星位置图层],target: 'vue-openlayers', // 设置地图的目标元素view: new View({center: [116, 39], // 设置地图的中心点projection: 'EPSG:4326', // 设置地图的投影zoom: 2, // 设置地图的缩放级别}),});getSatTrack(); // 获取卫星轨迹
};onMounted(() => {initMap(); // 初始化地图timerId = setInterval(() => {getSatInfo(); // 获取卫星信息}, 1000); // 每秒获取一次
});onUnmounted(() => {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>

5. 运行效果

运行代码后,页面中会显示:

  • 一个 OSM 地图
  • 一颗实时移动的卫星
  • 卫星轨迹的连线
  • 卫星每秒刷新位置

6. 结语

通过 OpenLayers + satellite.js,我们成功在 Vue3 项目中实现了卫星轨迹的可视化,并且代码封装合理,方便扩展。
你可以进一步优化:

  • 增加多个卫星的轨迹
  • 结合 Cesium.js 进行 3D 轨迹可视化
  • 使用 WebSocket 获取实时卫星数据

如果你喜欢这篇文章,欢迎点赞、收藏、关注!🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/16592.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3(2)

一.Vue新特性 &#xff08;1&#xff09;defineOptions:主要是用来定义Options API的选项 背景说明&#xff1a;有< script setup >之前&#xff0c;如果定义props&#xff0c;emits可以轻而易举地添加一个与setup平级 的属性。但是用了< script setup >后&#…

π 的奥秘:如何用有理数逼近无理数?

本文将围绕有理数、无理数、连续统以及它们之间的深刻联系展开讨论&#xff0c;并结合具体的数学理论如康托尔区间套定理、戴德金分割、柯西施瓦茨不等式等&#xff0c;进行简要探讨 由于本文并未深入探讨&#xff0c;可能存在部分不严谨的地方&#xff0c;也欢迎各位进行纠正…

图书管理项目(spring boot + Vue)

想要该项目的话&#xff0c;就 jia 我&#xff0c;并在评论区给我说一下&#xff0c;只需要1元&#xff0c;我把整个项目发给你 jia微&#xff1a;18439421203&#xff08;名字叫&#xff1a;Bingo&#xff09; 运行图片&#xff1a;

131,【2】 攻防世界 catcat-new

进入靶场 &#x1f431; 点击图片时发现url处很可疑 想到文件读取 ../app.py # 导入 os 模块&#xff0c;用于与操作系统进行交互&#xff0c;例如文件操作、路径操作等 import os # 导入 uuid 模块&#xff0c;用于生成通用唯一识别码&#xff0c;常用于生成随机的密钥 imp…

NO.12十六届蓝桥杯备战|关系操作符|操作符连用|浮点数比较|练习2道(C++)

关系操作符 关系操作符介绍 ⽤于⽐较的表达式&#xff0c;称为“关系表达式”&#xff08;relational expression&#xff09;&#xff0c;⾥⾯使⽤的运算符就称为“关 系运算符”&#xff08;relational operator&#xff09;&#xff0c;主要有下⾯6个。 运算符描述>⼤…

.NET Web-静态文件访问目录浏览

一、Web根目录访问 创建wwwroot文件夹app.UseStaticFiles(); // 启⽤静态⽂件中间件url/路径 进行访问 二、Web根目录之外的文件 app.UseStaticFiles(new StaticFileOptions {FileProvider new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath,&qu…

【漏洞复现】Casbin get-users 账号密码泄漏漏洞

免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删除。…

PPDock:复旦大学团队研发的蛋白质-配体“盲对接“技术

PPDock: Pocket Prediction-Based Protein−Ligand Blind Docking 发表于Journal of Chemical Information and Modeling&#xff0c;第一作者为 Jie Du&#xff0c;通讯作者为 Manning Wang&#xff0c;研究团队来自复旦大学。该研究提出一种新的基于口袋预测的蛋白质 - 配体盲…

中间件-安装Minio-集成使用(ubantu-docker)

目录 1、安装docer 2、运行以下命令拉取MinIO的Docker镜像 3、检查当前所有Docker下载的镜像 4、创建目录 5、创建Minio容器并运行 6、SDK操作 FileUploader.java 1、安装docer 参考这篇&#xff1a;Linux安装Docker 2、运行以下命令拉取MinIO的Docker镜像 docker pull…

使用 Notepad++ 编辑显示 MarkDown

Notepad 是一款免费的开源文本编辑器&#xff0c;专为 Windows 用户设计。它是替代记事本&#xff08;Notepad&#xff09;的最佳选择之一&#xff0c;因为它功能强大且轻量级。Notepad 支持多种编程语言和文件格式&#xff0c;并可以通过插件扩展其功能。 Notepad 是一款功能…

Java 大视界 -- 区块链赋能 Java 大数据:数据可信与价值流转(84)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

【Android开发】Android Studio汉化

前言 该插件是官方支持插件&#xff0c;未对任何软件进行修改和破解 Android Studio 是基于 IntelliJ IDEA 社区版开发的集成开发环境&#xff08;IDE&#xff09;&#xff0c;专门用于Android应用程序的开发。以下是为什么 Android Studio 能使用 IntelliJ IDEA 插件的原因&am…

七、I2C通信读取LM75B温度

7.1 概述 I2C&#xff08;Inter-Integrated Circuit&#xff09;是一种同步、多主从、串行通信协议&#xff0c;由飞利浦公司开发&#xff0c;主要用于短距离通信&#xff0c;尤其在集成电路之间。 7.1.1 主要特点 两线制&#xff1a;仅需SDA&#xff08;数据线&#xff09;…

CSS 小技巧 —— CSS 实现 Tooltip 功能-鼠标 hover 之后出现弹层

CSS 小技巧 —— CSS 实现 Tooltip 功能-鼠标 hover 之后出现弹层 1. 两个元素实现 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>纯 CSS 实现 Tooltip 功能-鼠标 hover 之后出现弹层</titl…

微信小程序医院挂号系统

第3章 系统设计 3.1系统体系结构 系统的体系结构非常重要&#xff0c;往往决定了系统的质量和生命周期。针对不同的系统可以采用不同的系统体系结构。本系统为微信小程序医院挂号系统&#xff0c;属于开放式的平台&#xff0c;所以在管理端体系结构中采用B/s。B/s结构抛弃了固…

开源堡垒机 JumpServer 社区版实战教程:一步步构建企业安全运维环境

文章目录 开源堡垒机 JumpServer 社区版实战教程&#xff1a;一步步构建企业安全运维环境一、访问JumpServer1.1 登录1.2 功能模块1.3 系统设置1.3.1 基本设置1.3.2 邮件设置 二、用户管理2.1 场景2.2 创建用户2.3 用户登录密码重置 三、资产管理3.1 准备工作3.2 登录控制台3.3…

小红书八股面经一份(JAVA开发)

1. zmysql索引结构 mysql索引底层采用的是b树的结构&#xff0c;一开始mysql的索引采用的是b树的结构&#xff0c;当数据量达到一定程度的时候&#xff0c;b树存在深度过大的问题&#xff0c;那么磁盘io次数就会飞速上升&#xff0c;导致查询效率慢。b树就很好的解决了这个问题…

redis 缓存击穿问题与解决方案

前言1. 什么是缓存击穿?2. 如何解决缓存击穿?怎么做?方案1: 定时刷新方案2: 自动续期方案3: 定时续期 如何选? 前言 当我们使用redis做缓存的时候,查询流程一般是先查询redis,如果redis未命中,再查询MySQL,将MySQL查询的数据同步到redis(回源),最后返回数据 流程图 为什…

路由过滤方法与常用工具

引言 在前面我们已经学习了路由引入&#xff0c;接下来我们就更进一步来学习路由过滤 前一篇文章&#xff1a;重发布&#xff1a;路由引入&#xff08;点击即可&#xff09; 路由过滤 定义&#xff1a;路由器在发布或者接收消息时&#xff0c;可能需要对路由信息进行过滤。 作用…

网络分析工具—WireShark的安装及使用

Wireshark 是一个广泛使用的网络协议分析工具&#xff0c;常被网络管理员、开发人员和安全专家用来捕获和分析网络数据包。它支持多种网络协议&#xff0c;能够帮助用户深入理解网络流量、诊断网络问题以及进行安全分析。 Wireshark 的主要功能 数据包捕获与分析&#xff1a; …