314 lines
11 KiB
TypeScript
314 lines
11 KiB
TypeScript
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;
|
|
};
|
|
}
|
|
|