'增加卫星星座选择'

This commit is contained in:
jiangteng 2023-02-03 17:16:20 +08:00
parent ed84dc1f95
commit 2d7b7d3cae
6 changed files with 452 additions and 126 deletions

View File

@ -1,9 +1,30 @@
# satellite-track # satellite-track
satellite-track使用TLE数据追踪卫星使用cesium、vue、satelliteJS开发。 **README.en.md**
## [预览](https://jiangteng2019.github.io/satellite-track/) ### satellite-track uses TLE data to track satellites and is developed using cesium, vue and satelliteJS.
###说明 ### [preview](https://jiangteng2019.github.io/satellite-track/)
1、为了节约性能卫星轨道数据选择显示而不全量显示
2、数据来源于celestrak
1. In order to save performance, the satellite orbit data is displayed by clicking.
1. Data from celestrak.
1. The access speed of github pages is slow, and the TLE data and cesium data are large. Please wait patiently for the resources to load.
-------------------------------------------
**README.md**
### satellite-track使用TLE数据追踪卫星使用cesium、vue、satelliteJS开发。
### [预览](https://jiangteng2019.github.io/satellite-track/)
1. 为了节约性能,卫星轨道数据点击显示,而非全量显示;
1. 数据来源于celestrak;
1. github pages 访问速度慢TLE数据与cesium数据较大请耐心等待资源加载;
[![satellite-track](https://images.cnblogs.com/cnblogs_com/engeng/2270012/o_230203011203_1.jpg "satellite-track")](https://images.cnblogs.com/cnblogs_com/engeng/2270012/o_230203011203_1.jpg "satellite-track")
[![satellite-track](https://images.cnblogs.com/cnblogs_com/engeng/2270012/o_230203011139_2.jpg "satellite-track")](https://images.cnblogs.com/cnblogs_com/engeng/2270012/o_230203011139_2.jpg "satellite-track")

View File

@ -1,21 +1,21 @@
import axios from "axios"; import axios from "axios";
const BASE_URL = "https://celestrak.org" const BASE_URL = "https://celestrak.org";
function getTleData(path = "") { function getTleDataFromExternal(path = "") {
let uri = BASE_URL + path; let uri = `${BASE_URL}/NORAD/elements/gp.php?GROUP=${path}&FORMAT=tle`;
return axios.get(uri).then(res => { return axios.get(uri).then(res => {
res.status === 200 ? ElMessage.success('获取TLE成功') : ElMessage.error('获取TLE失败'); if (res.status === 200) {
return res.status === 200 ? Promise.resolve(res.data) : Promise.reject(res.statusText); ElMessage.success('获取TLE成功');
localStorage.setItem(path, res.data); // 缓存TLE数据减轻数据服务压力
return Promise.resolve(res.data);
} else {
ElMessage.error('获取TLE失败');
return Promise.reject(res.statusText);
}
}); });
} }
/**
* @description 获取最近30天的发射卫星的TLE数据
* @returns Promise
*/
function getTleWithLastThirtyDays(path = "/NORAD/elements/gp.php?GROUP=last-30-days&FORMAT=tle") {
return getTleData(path);
}
export { getTleWithLastThirtyDays };
export { getTleDataFromExternal };

View File

@ -12,7 +12,7 @@ class SatelliteEntity {
this.tleLine2 = tleLine2.trim(); this.tleLine2 = tleLine2.trim();
this.satrec = twoline2satrec(this.tleLine1, this.tleLine2); this.satrec = twoline2satrec(this.tleLine1, this.tleLine2);
this.totalSeconds = 864000;// 864000 this.totalSeconds = 86400;// 24小时
this.stepSeconds = 100; this.stepSeconds = 100;
this.leadTime = parseInt(24 * 3600 / circle); this.leadTime = parseInt(24 * 3600 / circle);
this.trailTime = 0; this.trailTime = 0;
@ -56,7 +56,7 @@ class SatelliteEntity {
description: this.name, description: this.name,
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({ start: start, stop: stop })]), availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({ start: start, stop: stop })]),
position: this._getPositionProperty(), position: this._getPositionProperty(),
point: { pixelSize: 10, color: Cesium.Color.fromRandom({ alpha: 1.0 }) }, point: { pixelSize: 8, color: Cesium.Color.fromRandom({ alpha: 1.0 }) },
path: new Cesium.PathGraphics({ path: new Cesium.PathGraphics({
width: 1, width: 1,
show: false, show: false,
@ -67,7 +67,6 @@ class SatelliteEntity {
label: { label: {
text: this.name, text: this.name,
font: '12px sans-serif', font: '12px sans-serif',
scale: 0.8,
showBackground: true, showBackground: true,
backgroundColor: new Cesium.Color(0.165, 0.165, 0.165, 0.5), backgroundColor: new Cesium.Color(0.165, 0.165, 0.165, 0.5),
backgroundPadding: new Cesium.Cartesian2(4, 4), backgroundPadding: new Cesium.Cartesian2(4, 4),

View File

@ -28,6 +28,7 @@
fill: #edffff; fill: #edffff;
cursor: pointer; cursor: pointer;
} }
.menu_button:hover { .menu_button:hover {
color: #fff; color: #fff;
fill: #fff; fill: #fff;
@ -40,11 +41,37 @@
.el-drawer { .el-drawer {
background-color: rgba($color: #303336, $alpha: 0.9); background-color: rgba($color: #303336, $alpha: 0.9);
color: #fff; color: #fff;
.satellite_type {
color: #95D475;
font-weight: bold;
font-size: 14px;
padding: 10px;
padding-left: 0;
}
.el-drawer__header { .el-drawer__header {
background-color: #303336; background-color: #303336;
color: inherit; color: inherit;
margin: 0
} }
.el-checkbox { .el-checkbox {
color: inherit; color: inherit;
} }
} }
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
border-radius: 10px;
}
::-webkit-scrollbar-thumb {
background-color: #ccc;
border-radius: 10px;
transition: all .2s ease-in-out;
}

View File

@ -7,18 +7,11 @@
</div> </div>
<!-- 抽屉 --> <!-- 抽屉 -->
<el-drawer v-model="drawer" title="卫星选择" direction="ltr"> <el-drawer v-model="drawer" title="卫星选择" direction="ltr">
<el-row> <el-checkbox-group v-model="checked" @change="handleSatelliteChange" :max=5>
卫星 <template v-for="(item, index) in allSatellite" :key="index">
</el-row> <el-row v-if="item.type === 'title'" class="satellite_type">{{ item.label }}</el-row>
<el-checkbox-group v-model="checked" @change="handleSpacialInterestChange"> <el-checkbox v-if="!item.type" :label="item.value">{{ item.label }}</el-checkbox>
<el-checkbox v-for="(item, index) in options" :label="item.value">{{ item.label }}</el-checkbox> </template>
</el-checkbox-group>
<el-row>
气象和地球资源卫星
</el-row>
<el-checkbox-group v-model="checked" @change="handleWeatherSatelliteChange">
<el-checkbox v-for="(item, index) in weatherSatellite" :label="item.value">{{ item.label }}</el-checkbox>
</el-checkbox-group> </el-checkbox-group>
</el-drawer> </el-drawer>
</template> </template>
@ -29,97 +22,33 @@
import * as Cesium from 'cesium'; import * as Cesium from 'cesium';
import "cesium/Build/Cesium/Widgets/widgets.css"; import "cesium/Build/Cesium/Widgets/widgets.css";
import { onMounted, onBeforeMount, ref } from 'vue'; import { onMounted, ref, watch } from 'vue';
import "./SatelliteTrack.scss" import "./SatelliteTrack.scss"
import { getTleWithLastThirtyDays } from '@/http/index' import { getTleDataFromExternal } from '@/http/index'
import SatelliteEntity from '@/js/SatelliteEntity'; import SatelliteEntity from '@/js/SatelliteEntity';
import { specialSatellite, weatherSatellite, communicationSatellite, navigationSatellite, scientificSatellite, miscellaneousSatellite } from "./satelliteType"
import { add } from 'lodash';
let allSatellite = [...specialSatellite, ...weatherSatellite, ...communicationSatellite, ...navigationSatellite, ...scientificSatellite, ...miscellaneousSatellite];
window.CESIUM_BASE_URL = import.meta.env.MODE === 'development' ? '/cesium' : '/satellite-track/cesium'; window.CESIUM_BASE_URL = import.meta.env.MODE === 'development' ? '/cesium' : '/satellite-track/cesium';
let viewer; let viewer;
const totalSeconds = 864000; const totalSeconds = 86400;
//
const satelliteMap = new Map(); const satelliteMap = new Map();
// //
const drawer = ref(false); const drawer = ref(false);
const checked = ref([]);
const options = ref([
{
label: "Last 30 Days' Launches",
value: 1
},
{
label: 'Space Stations',
value: 2
},
{
label: '100 (or so) Brightest',
value: 3
},
{
label: 'Active Satellites',
value: 4
},
{
label: 'Analyst Satellites ',
value: 5
},
{
label: 'IRIDIUM 33 Debris',
value: 6
},
{
label: 'COSMOS 2251 Debris',
value: 7
}
])
const weatherSatellite = ref([ const checked = ref([]);
{
label: 'Weather', const clickedSatelliteArray = [];
value: 1
},
{
label: 'NOAA',
value: 2
},
{
label: 'GOES',
value: 3
},
{
label: 'Earth Resources',
value: 4
},
{
label: 'Search & Rescue (SARSAT) ',
value: 5
},
{
label: 'Disaster Monitoring',
value: 6
},
{
label: 'TDRSS',
value: 7
},
{
label: 'ARGOS Data Collection System',
value: 8
},
{
label: 'Planet',
value: 9
},
{
label: 'Spire',
value: 10
}
])
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiYjZmMWM4Ny01YzQ4LTQ3MzUtYTI5Mi1hNTgyNjdhMmFiMmMiLCJpZCI6NjIwMjgsImlhdCI6MTYyNjY3MTMxNX0.5SelYUyzXWRoMyjjFvmFIAoPtWlJPQMjsVl2e_jQe-c'; Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiYjZmMWM4Ny01YzQ4LTQ3MzUtYTI5Mi1hNTgyNjdhMmFiMmMiLCJpZCI6NjIwMjgsImlhdCI6MTYyNjY3MTMxNX0.5SelYUyzXWRoMyjjFvmFIAoPtWlJPQMjsVl2e_jQe-c';
@ -194,48 +123,92 @@ function parseTle(data = "") {
} }
function addCesiumEventListener() { function addCesiumEventListener() {
let callback = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);// let callback = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) { viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
callback(movement); callback(movement);
const pickedFeature = viewer.scene.pick(movement.position); const pickedFeature = viewer.scene.pick(movement.position);
console.log(pickedFeature); console.log(pickedFeature);
if (!Cesium.defined(pickedFeature)) { if (!Cesium.defined(pickedFeature)) {
satelliteMap.forEach(item => { clickedSatelliteArray.forEach(item => {
item.path.show = false; item.id.path.show = false;
}) })
return; return;
} }
if (pickedFeature) { if (pickedFeature) {
pickedFeature.id.path.show = new Cesium.ConstantProperty(true); pickedFeature.id.path.show = new Cesium.ConstantProperty(true);
pickedFeature.id.label.distanceDisplayCondition = undefined; pickedFeature.id.label.distanceDisplayCondition = undefined;
clickedSatelliteArray.push(pickedFeature);
} }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK); }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
} }
// //
function handleSpacialInterestChange(e) { function handleSatelliteChange(e) {
console.log(e);
} }
function handleWeatherSatelliteChange(e) {
console.log(e); // tle
async function getTleData(path) {
let data = localStorage.getItem(path);
if (data) {
console.log(`%c 命中缓存,key值为${path}`, 'color:#0f0;');
return data;
} else {
console.warn("未命中缓存开始下载TLE数据");
return await getTleDataFromExternal(path);
}
} }
onMounted(async () => { // satellite entity
initCesium(); async function addSatellite(path) {
initTimeLine(); // map
addCesiumEventListener(); if (satelliteMap.has(path)) {
let satelliteList = satelliteMap.get(path);
let result = await getTleWithLastThirtyDays(); satelliteList.forEach(item => viewer.entities.add(item));
} else {
let result = await getTleData(path);
let parsedResult = parseTle(result); let parsedResult = parseTle(result);
let satelliteSet = new Set();
parsedResult.forEach(tle => { parsedResult.forEach(tle => {
let satellite = new SatelliteEntity(tle); let satellite = new SatelliteEntity(tle);
let cesiumSateEntity = satellite.createSatelliteEntity(); let cesiumSateEntity = satellite.createSatelliteEntity();
let result = viewer.entities.add(cesiumSateEntity); let result = viewer.entities.add(cesiumSateEntity);
satelliteMap.set(satellite.name, result); satelliteSet.add(result);
}); });
satelliteMap.set(path, satelliteSet);
}
}
function removeSatellite(path) {
if (satelliteMap.has(path)) {
let satelliteList = satelliteMap.get(path);
satelliteList.forEach(item => viewer.entities.remove(item));
}
}
//
watch(checked, (newValue, oldValue) => {
let filterValue = newValue.concat(oldValue).filter((item, index, arr) => arr.indexOf(item) === arr.lastIndexOf(item));
let satelliteClassify = allSatellite.find(item => item.value === filterValue[0]);
//
if (newValue.length > oldValue.length) {
addSatellite(satelliteClassify.group);
} else {
//
removeSatellite(satelliteClassify.group);
}
})
//
onMounted(async () => {
initCesium();
initTimeLine();
addCesiumEventListener();
}) })

View File

@ -0,0 +1,306 @@
let specialSatellite = [
{
label: "特殊卫星",
value: null,
group: null,
type: "title"
},
{
label: "Last 30 Days' Launches",
value: 1,
group: 'last-30-days'
},
{
label: 'Space Stations',
value: 2,
group: 'stations'
},
{
label: '100 (or so) Brightest',
value: 3,
group: 'visual'
},
{
label: 'Active Satellites',
value: 4,
group: 'active'
},
{
label: 'Analyst Satellites ',
value: 5,
group: 'analyst'
}
];
let weatherSatellite = [
{
label: "气象和地球资源卫星",
value: null,
group: null,
type: "title"
},
{
label: 'Weather',
value: 6,
group: 'weather'
},
{
label: 'NOAA',
value: 7,
group: 'noaa'
},
{
label: 'GOES',
value: 8,
group: 'goes'
},
{
label: 'Earth Resources',
value: 9,
group: 'resource'
},
{
label: 'Search & Rescue (SARSAT) ',
value: 10,
group: 'sarsat'
},
{
label: 'Disaster Monitoring',
value: 11,
group: 'dmc'
},
{
label: 'TDRSS',
value: 12,
group: 'tdrss'
},
{
label: 'ARGOS Data Collection System',
value: 13,
group: 'argos'
},
{
label: 'Planet',
value: 14,
group: 'planet'
},
{
label: 'Spire',
value: 15,
group: 'spire'
}
];
let communicationSatellite = [
{
label: "通讯卫星",
value: null,
group: null,
type: "title"
},
{
label: 'Active Geosynchronous',
value: 16,
group: 'geo'
},
{
label: 'GEO Protected Zone',
value: 17,
group: 'gpz'
},
{
label: 'GEO Protected Zone Plus',
value: 18,
group: 'gpz-plus'
},
{
label: 'Intelsat',
value: 19,
group: 'intelsat'
},
{
label: 'SES',
value: 20,
group: 'ses'
},
{
label: 'Iridium',
value: 21,
group: 'iridium'
},
{
label: 'Iridium NEXT',
value: 22,
group: 'iridium-NEXT'
},
{
label: 'Starlink',
value: 23,
group: 'starlink'
},
{
label: 'OneWeb',
value: 24,
group: 'oneweb'
},
{
label: 'Orbcomm',
value: 25,
group: 'orbcomm'
},
{
label: 'Globalstar',
value: 26,
group: 'globalstar'
},
{
label: 'Swarm',
value: 27,
group: 'swarm'
},
{
label: 'Amateur Radio',
value: 28,
group: 'amateur'
},
{
label: 'Experimental Comm',
value: 29,
group: 'x-comm'
},
{
label: 'Other Comm',
value: 30,
group: 'other-comm'
},
{
label: 'SatNOGS',
value: 31,
group: 'satnogs'
},
{
label: 'Gorizont',
value: 32,
group: 'gorizont'
},
{
label: 'Raduga',
value: 33,
group: 'raduga'
},
{
label: 'Molniya',
value: 34,
group: 'molniya'
},
];
let navigationSatellite = [
{
label: "导航卫星",
value: null,
group: null,
type: "title"
},
{
label: 'GNSS',
value: 35,
group: 'gnss'
},
{
label: 'GPS Operational',
value: 36,
group: 'gps-ops'
},
{
label: 'GLONASS Operational',
value: 37,
group: 'glo-ops'
},
{
label: 'Galileo',
value: 38,
group: 'galileo'
},
{
label: 'Beidou',
value: 39,
group: 'beidou'
},
{
label: 'Satellite-Based Augmentation System',
value: 40,
group: 'sbas'
},
{
label: 'Navy Navigation Satellite System (NNSS)',
value: 41,
group: 'nnss'
},
{
label: 'Russian LEO Navigation',
value: 42,
group: 'musson'
},
];
let scientificSatellite = [
{
label: "科学卫星",
value: null,
group: null,
type: "title"
},
{
label: 'Space & Earth Science',
value: 43,
group: 'science'
},
{
label: 'Geodetic',
value: 44,
group: 'geodetic'
},
{
label: 'Engineering',
value: 45,
group: 'engineering'
},
{
label: 'Education',
value: 46,
group: 'education'
}
];
let miscellaneousSatellite = [
{
label: "其他卫星",
value: null,
group: null,
type: "title"
},
{
label: 'Miscellaneous Military',
value: 47,
group: 'military'
},
{
label: 'Radar Calibration',
value: 48,
group: 'radar'
},
{
label: 'CubeSats',
value: 49,
group: 'cubesat'
},
{
label: 'Other Satellites',
value: 50,
group: 'other'
}
]
export { specialSatellite, weatherSatellite, communicationSatellite, navigationSatellite, scientificSatellite, miscellaneousSatellite };