速度过滤优化

This commit is contained in:
2026-07-17 09:39:27 +08:00
parent 496fc3c913
commit 7eab8c9317
4 changed files with 2 additions and 542 deletions
-228
View File
@@ -1,228 +0,0 @@
import React, { useEffect, useRef } from 'react';
import "leaflet/dist/leaflet.css"
import { MapContainer, TileLayer, useMap as useLeafletMap } from "react-leaflet";
import L from "leaflet";
// 引入Leaflet图标资源
// @ts-ignore
import markerIcon2x from "leaflet/dist/images/marker-icon-2x.png";
// @ts-ignore
import markerIcon from "leaflet/dist/images/marker-icon.png";
// @ts-ignore
import markerShadow from "leaflet/dist/images/marker-shadow.png";
import enhance from "../src/core/enhance.tsx";
import { baseURL, G, host, lightenColor } from "../src/Global.js";
import { Aircraft, Aircraft_Track_Point } from "../src/Map/Aircraft.tsx"
import axios from "axios";
import { Aircraft_Info_Show } from "../src/Map/Aircraft_Info_Show.tsx";
import { Data_Source_Config } from "../src/Data_Source/Data_Source_Config.tsx";
import { Data_Source_Show } from "../src/Data_Source/Data_Source_Show.tsx";
import { app } from "../src/App.tsx";
import { Data_Source } from "../src/Data_Source/Data_Source.tsx";
// npm install leaflet react-leaflet@4.x
// 修复Leaflet图标路径(改用import方式,适配React模块解析)
delete (L.Icon.Default.prototype as any)._getIconUrl;
L.Icon.Default.mergeOptions({
iconRetinaUrl: markerIcon2x,
iconUrl: markerIcon,
shadowUrl: markerShadow,
});
// 定义POS类
export class POS {
lat: number;
lon: number;
}
export class Leaflet_Map_Wrapper extends enhance.Base{
}
export class Leaflet_Map extends enhance.Base {
// @ts-ignore
map: L.Map = null;
data_source_show: Data_Source_Show = new Data_Source_Show();
aircraft_info_show: Aircraft_Info_Show = new Aircraft_Info_Show(this);
data_source_config: Data_Source_Config = null
private savedCenter: L.LatLng | null = null;
private savedZoom: number | null = null;
intervalId: number | null = null;
autoRefreshTimer = null; // 用于存储定时器ID
refreshInterval: number = 1; // 刷新间隔(秒)
mapRef: { current: L.Map | null } = { current: null };
INIT_EXTENT = L.latLngBounds(
[36.42, 119.98], // 西南角:
[38.40, 122.56] // 东北角:
);
on_mount: () => void = () => {
// 从ref获取地图实例
this.map = this.mapRef.current;
if (this.savedCenter && this.savedZoom && this.map) {
this.map.setView(this.savedCenter, this.savedZoom);
}
if (this.data_source_config) {
let ds_list = this.data_source_config.list.list;
ds_list.forEach((ds: Data_Source) => {
if (!ds.enable) return;
for (const [key, aircraft] of ds.aircraftMap) {
aircraft.on_mount();
}
ds.base_station.on_mount();
ds.refresh()
});
}
// 自动刷新定时器
this.autoRefreshTimer = setInterval(() => {
if (this.data_source_config) {
let ds_list = this.data_source_config.list.list;
ds_list.forEach((ds: Data_Source) => {
if (!ds.enable) return;
ds.refresh()
});
}
}, this.refreshInterval * 1000);
this.flush();
}
on_un_mount: () => void = () => {
if (this.map) {
this.savedCenter = this.map.getCenter();
this.savedZoom = this.map.getZoom();
}
// 清除图层(保留TileLayer,只清理业务图层)
if (this.map) {
this.map.eachLayer((layer) => {
// 跳过TileLayer,只移除自定义图层(飞机、轨迹等)
if (!(layer instanceof L.TileLayer)) {
this.map!.removeLayer(layer);
}
});
}
// 清除定时器
if (this.autoRefreshTimer) {
clearInterval(this.autoRefreshTimer);
this.autoRefreshTimer = null;
}
this.map = null;
this.mapRef.current = null;
}
list(): Data_Source[] {
if (!this.data_source_config) return []
return this.data_source_config.list.list
}
get_aircraft(data_source_key: string, icao: string): Aircraft {
let d = app.get_Data_Source(data_source_key)
return d.get_aircraft(icao)
}
// 封装Map组件,用于获取react-leaflet的地图实例
MapContent = () => {
const map = useLeafletMap();
useEffect(() => {
this.mapRef.current = map;
map.fitBounds(this.INIT_EXTENT, {
padding: [50, 50], // 可选:添加内边距,避免内容贴边
maxZoom: 10 // 可选:限制适配后的最大缩放级别
});
// 可选:监听范围变化,实时获取当前extent
// map.on('moveend zoomend', () => {
// const currentExtent = map.getBounds(); // 获取当前范围
// console.log("当前地图范围:", {
// southwest: currentExtent.getSouthWest(), // 西南角
// northeast: currentExtent.getNorthEast() // 东北角
// });
// });
// 组件挂载时执行原有on_mount逻辑
this.on_mount();
// 组件卸载时执行原有on_un_mount逻辑
return () => this.on_un_mount();
}, []);
return null;
};
render(props: any) {
// 地图基础配置
const MAP_CENTER = L.latLng(34.3227, 118.5525);
const ZOOM_RANGE = { minZoom: 1, maxZoom: 9 };
return (
<MapContainer
id="map"
center={MAP_CENTER}
minZoom={ZOOM_RANGE.minZoom}
maxZoom={ZOOM_RANGE.maxZoom}
style={{ width: '100%', height: '100%', zIndex: 1 }}
zoomControl={false}
attributionControl={false}
doubleClickZoom={false}
>
<TileLayer
url={`http://${host}/tiles/{z}/{x}/{y}.png`}
/>
<this.aircraft_info_show.x></this.aircraft_info_show.x>
<this.data_source_show.x></this.data_source_show.x>
<this.MapContent />
</MapContainer>
);
}
aircraft_click(that: Aircraft) {
this.aircraft_info_show.active_aircraft = that;
let data_source = this.data_source_config.map(that.data_source.key)
if (data_source.active_aircraft != that) {
if (data_source.active_aircraft) {
data_source.active_aircraft.hide_path();
}
data_source.active_aircraft = that;
data_source.active_aircraft.show_path();
}
let a = this.aircraft_info_show;
if (a.drawer.have_open === false) {
a.drawer.toggleOpen()
}
if (a.selected_key === a.DETAILED_INFORMATION) {
axios.post(`${baseURL}/get_aircraft_detail_info`, {
data_source_key: that.data_source.key,
icao: that.icao,
}).then(res => {
a.detailed_information = G.transformToTreeData(res.data);
a.flush();
})
}
if (a.selected_key === a.BASE_INFORMATION) {
axios.post(`${baseURL}/get_aircraft_base_info`, {
data_source_key: that.data_source.key,
icao: that.icao,
}).then(res => {
a.base_information = G.transformToTreeData(res.data);
a.flush();
})
}
}
timer: any;
mlat_source: Data_Source = new Data_Source();
mlat: Map<string, Aircraft> = new Map();
constructor() {
super();
this.mlat_source.key = "mlat_source";
}
}
-313
View File
@@ -1,313 +0,0 @@
import "leaflet/dist/leaflet.css"
import L from 'leaflet';
import gcoord from "gcoord"
import React, {useEffect, useState} from 'react';
import enhance from "../src/core/enhance.tsx";
import {baseURL, G, host, lightenColor} from "../src/Global.js";
import {Aircraft, Aircraft_Track_Point} from "../src/Map/Aircraft.tsx"
import {Button, Drawer, Switch} from "antd";
// https://ant.design/components/tree-cn
import {Menu, type MenuProps, Tree} from 'antd';
import type {TreeDataNode, TreeProps} from 'antd';
// @ts-ignore
import {ReloadOutlined, SearchOutlined, SettingOutlined} from "@ant-design/icons";
import axios from "axios";
import {Aircraft_Info_Show} from "../src/Map/Aircraft_Info_Show.tsx";
import {Data_Source_Config} from "../src/Data_Source/Data_Source_Config.tsx";
import {Data_Source_Show} from "../src/Data_Source/Data_Source_Show.tsx";
import {app} from "../src/App.tsx";
//import {Base_Station} from "./Base_Station.tsx";
import {Data_Source} from "../src/Data_Source/Data_Source.tsx";
export class POS {
lat: number;
lon: number;
}
export class Leaflet_Map extends enhance.Base {
// @ts-ignore
map: L.Map = null;
data_source_show: Data_Source_Show = new Data_Source_Show();
// @ts-ignore
aircraft_info_show: Aircraft_Info_Show = new Aircraft_Info_Show(this);
data_source_config: Data_Source_Config = null
private savedCenter: L.LatLng | null = null;
private savedZoom: number | null = null;
intervalId: number | null = null;
autoRefreshTimer = null; // 用于存储定时器ID
refreshInterval : number = 1; // 用于存储定时器ID
on_mount: () => void = () => {
console.log("地图加载");
this.map = this.load_map();
this.map.whenReady(() => {
});
if (this.savedCenter && this.savedZoom) {
this.map.setView(this.savedCenter, this.savedZoom);
}
if (this.data_source_config) {
let ds_list = this.data_source_config.list.list;
ds_list.forEach((ds: Data_Source) => {
if (!ds.enable) return; // ✅ 跳过当前项
for (const [key, aircraft] of ds.aircraftMap) {
aircraft.on_mount();
}
ds.base_station.on_mount();
ds.refresh()
});
}
this.autoRefreshTimer = setInterval(() => {
if (this.data_source_config){
let ds_list = this.data_source_config.list.list;
ds_list.forEach((ds: Data_Source) => {
if (!ds.enable) return; // ✅ 跳过当前项
ds.refresh()
});
}
}, this.refreshInterval * 1000); // 以秒为单位
this.flush();
}
on_un_mount: () => void = () => {
console.log("地图卸载");
if (this.map) {
this.savedCenter = this.map.getCenter();
this.savedZoom = this.map.getZoom();
}
let map = this.map;
map.eachLayer(function(layer) {
map.removeLayer(layer);
});
if (this.autoRefreshTimer) {
clearInterval(this.autoRefreshTimer); // 清除定时器
this.autoRefreshTimer = null;
}
this.map = null
}
list(): Data_Source[] {
if (!this.data_source_config) return []
return this.data_source_config.list.list
}
get_aircraft(data_source_key: string, icao: string): Aircraft {
let d = app.get_Data_Source(data_source_key)
return d.get_aircraft(icao)
}
style = {}
render(props: any) {
return (
<div style={{
width: '100%',
height: '100%',
}}>
<this.aircraft_info_show.x></this.aircraft_info_show.x>
<this.data_source_show.x></this.data_source_show.x>
<div id="map" style={{
width: '100%',
height: '100%',
zIndex: 1,
}}/>
</div>
);
}
aircraft_click(that: Aircraft) {
this.aircraft_info_show.active_aircraft = that;
let data_source = this.data_source_config.map(that.data_source.key)
if (data_source.active_aircraft != that) {
if (data_source.active_aircraft) {
data_source.active_aircraft.hide_path();
}
data_source.active_aircraft = that;
data_source.active_aircraft.show_path();
}
let a = this.aircraft_info_show;
if(a.drawer.have_open === false){
a.drawer.toggleOpen()
}
if (a.selected_key === a.DETAILED_INFORMATION) {
axios.post(`${baseURL}/get_aircraft_detail_info`, {
data_source_key: that.data_source.key,
icao: that.icao,
}).then(res => {
a.detailed_information = G.transformToTreeData(res.data);
a.flush();
})
}
if (a.selected_key === a.BASE_INFORMATION) {
axios.post(`${baseURL}/get_aircraft_base_info`, {
data_source_key: that.data_source.key,
icao: that.icao,
}).then(res => {
a.base_information = G.transformToTreeData(res.data);
a.flush();
})
}
}
timer
mlat_source: Data_Source = new Data_Source();
mlat: Map<string, Aircraft> = new Map();
constructor() {
super();
this.mlat_source.key = "mlat_source";
// this.timer = setInterval(() => {
// this.mlat_source.aircraft_show = true;
// axios.post(`${baseURL}/get_mlat_list`, {})
// .then(res => {
//
// //console.log(res.data);
// res.data.forEach(item => {
// //console.log(item);
// let mlat_air = this.mlat.get(item.icao);
// if (!mlat_air) {
// mlat_air = new Aircraft(item.icao, this.mlat_source)
// mlat_air.mlat_show = true;
// this.mlat.set(item.icao, mlat_air);
// //mlat_air.track_path.addTo(this.map);
// }
//
// mlat_air.add_malt_data(item);
//
// });
// })
// .catch(err => {
// console.error("请求出错:", err);
// });
// }, 1000);
}
load_map = () => {
const TILE_SERVER = `http://${host}`;
const ZOOM_RANGE = {minZoom: 3, maxZoom: 15};
const MAP_CENTER: L.LatLng = new L.LatLng(34.3227, 118.5525);
const MAP_ZOOM = 3;
L.Icon.Default.imagePath = `http://${host}/images/`;
let BaiduMercator = L.Util.extend({},
L.Projection.Mercator,
{
// 百度椭球赤道半径 a=6378206,相当于在 WGS84 椭球赤道半径上加了 69 米
R: 6378206,
// 百度椭球极半径 b=6356584.314245179,相当于在 WGS84 椭球极半径上减了 168 米
R_MINOR: 6356584.314245179,
// 数据覆盖范围在经度[-180°,180°],纬度 [-85.051129°, 85.051129°] 之间
bounds: new L.Bounds([-20037725.11268234, -19994619.55417086], [20037725.11268234, 19994619.55417086])
}
);
let Baidu = L.Util.extend({}, L.CRS.Earth, { // 定义百度坐标参考系统 (CRS)
code: 'EPSG:Baidu',
projection: BaiduMercator,
transformation: new L.Transformation(1, 0.5, -1, 0.5),
scale: function (zoom: any) {
return 1 / Math.pow(2, (18 - zoom))
},
zoom: function (scale: any) {
return 18 - Math.log(1 / scale) / Math.LN2
},
})
let BaiDuTileLayer = L.TileLayer.extend({
initialize: function (param: any, options: any) {
var templateUrl = TILE_SERVER + "/tiles/{z}/{x}/{y}.png";
console.log(`templateUrl ${templateUrl}`)
options = L.extend({
getUrlArgs: (o: any) => {
return {x: o.x, y: (-1 - o.y), z: o.z}
},
p: param,
minZoom: ZOOM_RANGE.minZoom,
maxZoom: ZOOM_RANGE.maxZoom,
minNativeZoom: 3,
maxNativeZoom: 12
}, options)
// @ts-ignore
L.TileLayer.prototype.initialize.call(this, templateUrl, options)
},
getTileUrl: function (coords: any) {
if (this.options.getUrlArgs) {
return L.Util.template(this._url, L.extend({
s: this._getSubdomain(coords),
r: L.Browser.retina ? '@2x' : ''
},
this.options.getUrlArgs(coords), this.options))
} else {
return L.TileLayer.prototype.getTileUrl.call(this, coords)
}
},
_setZoomTransform: function (level: any, center: any, zoom: any) { // 设置缩放变换,使用 gcoord 库进行坐标纠偏
// @ts-ignore
var _center = L.latLng(gcoord.transform([center.lng, center.lat], gcoord.WGS84, gcoord.BD09).reverse()) // 采用 gcoord 库进行纠偏
// @ts-ignore
L.TileLayer.prototype._setZoomTransform.call(this, level, _center, zoom)
},
_getTiledPixelBounds: function (center: any) { // 获取瓦片的像素边界,使用 gcoord 库进行坐标纠偏
// @ts-ignore
var _center = L.latLng(gcoord.transform([center.lng, center.lat], gcoord.WGS84, gcoord.BD09).reverse()) // 采用 gcoord 库进行纠偏
// @ts-ignore
return L.TileLayer.prototype._getTiledPixelBounds.call(this, _center)
}
})
// @ts-ignore
let img_Layer = new BaiDuTileLayer("img", {
minZoom: ZOOM_RANGE.minZoom,
maxZoom: ZOOM_RANGE.maxZoom,
coordType: 'bd09'
});
// 创建一个地图实例,并指定了容器 ID (#map)、中心点坐标、初始缩放级别等参数。
let ret = new L.Map("map", {
crs: Baidu,
center: MAP_CENTER,
zoom: MAP_ZOOM,
zoomControl: false,
attributionControl: false,
doubleClickZoom: false
})
ret.addLayer(img_Layer);
return ret;
};
}
+1
View File
@@ -34,6 +34,7 @@ export class Data_Source extends enhance.Base {
alt: number = 0;
update_form_gps: boolean = false;
aircraft_pixel_size: number = 20;
use_system_time: boolean = false;
constructor() {
super();
+1 -1
View File
@@ -42,7 +42,7 @@ export default defineConfig({
}
},
build: {
outDir: 'D:\\ae\\proj\\projects\\ECAP_Server\\webapp\\wwwroot'
outDir: 'wwwroot'
}
})