显示效果全面优化
10
package.json
|
@ -9,16 +9,18 @@
|
|||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"electron:dev": "cross-env NODE_ENV=development electron index.js",
|
||||
"electron:build": "rimraf dist && vite build && tsc -p tsconfig.electron.json && electron-builder"
|
||||
"electron:build": "rimraf dist && vite build && tsc -p tsconfig.electron.json && electron-builder",
|
||||
"fix-memory-limit": "cross-env LIMIT=10000 increase-memory-limit"
|
||||
},
|
||||
"dependencies": {
|
||||
"echarts": "^5.2.2",
|
||||
"echarts": "^5.4.1",
|
||||
"echarts-gl": "^2.0.9",
|
||||
"echarts-liquidfill": "^3.1.0",
|
||||
"electron-store": "^8.0.1",
|
||||
"nmea": "http://git.hwasmart.com/bd_group/node-nmea.git",
|
||||
"serialport": "9.2.4",
|
||||
"serialport": "10.5.0",
|
||||
"vue": "^3.0.5",
|
||||
"vue-echarts": "^6.0.0"
|
||||
"vue-echarts": "^6.6.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^1.1.5",
|
||||
|
|
|
@ -116,11 +116,11 @@ async function launch() {
|
|||
createWindow('satellite-state-monitor-platform', displays[0])
|
||||
} else {
|
||||
createWindow('satellite-data-monitor-platform', displays[0])
|
||||
await sleep(100);
|
||||
createWindow('satellite-info-monitor-platform', displays[1])
|
||||
await sleep(200);
|
||||
createWindow('satellite-info-monitor-platform', displays[1])
|
||||
await sleep(400);
|
||||
createWindow('satellite-signal-monitor-platform', displays[2])
|
||||
await sleep(300);
|
||||
await sleep(600);
|
||||
createWindow('satellite-state-monitor-platform', displays[3])
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const { ipcMain } = require('electron')
|
||||
const SerialPort = require('serialport')
|
||||
const InterByteTimeout = require('@serialport/parser-inter-byte-timeout')
|
||||
const { SerialPort } = require("serialport")
|
||||
const { InterByteTimeoutParser } = require('@serialport/parser-inter-byte-timeout')
|
||||
const config = require('./config')
|
||||
|
||||
const NMEAHandler = require('./api/NMEAHandler')
|
||||
|
@ -52,9 +52,13 @@ SerialPort.list().then((ports, err) => {
|
|||
try {
|
||||
const { path, baudRate } = getSerialPortConstructorArguments(ports)
|
||||
console.log(path, baudRate, '=====================')
|
||||
const serialPort = new SerialPort(path, { baudRate })
|
||||
const serialPort = new SerialPort({ path, baudRate })
|
||||
|
||||
const parser = serialPort.pipe(new InterByteTimeout({interval: 30}))
|
||||
const parser = serialPort.pipe(new InterByteTimeoutParser({interval: 30}))
|
||||
|
||||
NMEAHandler.on('received' , (nmeaStr) => {
|
||||
sendMsg('NMEA_RECEIVED', nmeaStr)
|
||||
})
|
||||
|
||||
NMEAHandler.on('handled' , (nmeaObj) => {
|
||||
sendMsg('nmea', JSON.stringify(nmeaObj))
|
||||
|
|
|
@ -19,15 +19,15 @@ import { city as city_full } from "./city/citygeo_full"
|
|||
import { city as city_geo } from "./city/citygeo"
|
||||
|
||||
export function intersect(checkPoint, polygonPoints) {
|
||||
for (let j = 0; j < polygonPoints.features.length; j++) {
|
||||
for (let j = 0; j < polygonPoints.features.length-1; j++) {
|
||||
var counter = 0;
|
||||
var i;
|
||||
var xinters;
|
||||
var p1, p2;
|
||||
var pointCount = polygonPoints.features[j].geometry.coordinates[0][0].length;
|
||||
p1 = polygonPoints.features[j].geometry.coordinates[0][0][0];
|
||||
var pointCount = polygonPoints.features[j].properties.name == "内蒙古自治区" ? polygonPoints.features[j].geometry.coordinates[0].length : polygonPoints.features[j].geometry.coordinates[0][0].length;
|
||||
p1 = polygonPoints.features[j].properties.name == "内蒙古自治区" ? polygonPoints.features[j].geometry.coordinates[0][0] : polygonPoints.features[j].geometry.coordinates[0][0][0];
|
||||
for (i = 1; i <= pointCount; i++) {
|
||||
p2 = polygonPoints.features[j].geometry.coordinates[0][0][i % pointCount];
|
||||
p2 = polygonPoints.features[j].properties.name == "内蒙古自治区" ? polygonPoints.features[j].geometry.coordinates[0][i % pointCount] : polygonPoints.features[j].geometry.coordinates[0][0][i % pointCount];
|
||||
if (
|
||||
checkPoint[0] > Math.min(p1[0], p2[0]) &&
|
||||
checkPoint[0] <= Math.max(p1[0], p2[0])
|
||||
|
@ -48,7 +48,7 @@ export function intersect(checkPoint, polygonPoints) {
|
|||
p1 = p2;
|
||||
}
|
||||
if (counter % 2 == 0) {
|
||||
console.log(polygonPoints.features[j].properties.name)
|
||||
console.log(counter)
|
||||
} else {
|
||||
return polygonPoints.features[j].properties.name;
|
||||
}
|
||||
|
|
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
|
@ -18,23 +18,23 @@
|
|||
<div class="cc-main-container">
|
||||
<div class="ccmc-left">
|
||||
<div class="station-info">
|
||||
<span> 北 斗 {{ bd_satellite_count }}</span>
|
||||
<span id="fontBd" style="text-shadow:0 0 0.5em #ff3232;"> 北 斗 {{ bd_satellite_count }}</span>
|
||||
</div>
|
||||
<div class="station-info">
|
||||
<span>Galileo {{ ga_satellite_count }}</span>
|
||||
<span id="fontGl" style="text-shadow:0 0 0.5em #6600ff;">GLONASS {{ gl_satellite_count }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ccmc-middle">
|
||||
<Ring ref="ring"/>
|
||||
<Ring ref="ring" @changeColor="changeColor"/>
|
||||
</div>
|
||||
|
||||
<div class="ccmc-right">
|
||||
<div class="station-info">
|
||||
<span>{{ gp_satellite_count }} G P S</span>
|
||||
<span id="fontGp" style="text-shadow:0 0 0.5em #00ffff;">{{ gp_satellite_count }} G P S</span>
|
||||
</div>
|
||||
<div class="station-info">
|
||||
<span>{{ gl_satellite_count }} GLONASS</span>
|
||||
<span id="fontGa" style="text-shadow:0 0 0.5em #00ff66;">{{ ga_satellite_count }} Galileo</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -45,7 +45,7 @@
|
|||
import Ring from './Ring.vue'
|
||||
import Decoration1 from './Layout/Decoration1.vue'
|
||||
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
|
||||
const bd_satellite_count = ref(0)
|
||||
const gp_satellite_count = ref(0)
|
||||
|
@ -66,6 +66,28 @@ const update = (bd_satellite_length: number, gp_satellite_length: number, gl_sat
|
|||
ring.value.update(bd_satellite_length, gp_satellite_length, gl_satellite_length, ga_satellite_length)
|
||||
}
|
||||
|
||||
let bdText, glText, gpText, gaText;
|
||||
|
||||
onMounted(() => {
|
||||
bdText = document.getElementById("fontBd");
|
||||
gpText = document.getElementById("fontGp");
|
||||
glText = document.getElementById("fontGl");
|
||||
gaText = document.getElementById("fontGa");
|
||||
});
|
||||
|
||||
|
||||
const changeColor = (change, id) => {
|
||||
let idPie = [bdText, gpText, glText, gaText];
|
||||
let colorPie = ['#ff3232', '#00ffff', '#6600ff', '#00ff66'];
|
||||
if(change){
|
||||
idPie[id].style.color = colorPie[id];
|
||||
}else{
|
||||
idPie.forEach(element => {
|
||||
element.style.color = "#ffffff";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ update })
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<v-chart :option="option" />
|
||||
<v-chart id="myClock" :option="option" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -9,7 +9,7 @@ import { TitleComponent } from "echarts/components";
|
|||
import { GaugeChart } from "echarts/charts";
|
||||
|
||||
import VChart from "vue-echarts";
|
||||
import { reactive } from "vue";
|
||||
import { reactive, onMounted } from "vue";
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
|
@ -17,6 +17,11 @@ use([
|
|||
GaugeChart
|
||||
]);
|
||||
|
||||
onMounted(() => {
|
||||
var mychart = document.getElementById("myClock");
|
||||
mychart.firstChild.style.margin = "auto";
|
||||
});
|
||||
|
||||
// TODO: 修复指针转过一圈之后反向旋转的bug
|
||||
const option = reactive({
|
||||
title: {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<v-chart :option="option" />
|
||||
<v-chart id="myCompass" :option="option" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -9,7 +9,7 @@ import { TitleComponent } from "echarts/components";
|
|||
import { GaugeChart } from "echarts/charts";
|
||||
|
||||
import VChart from "vue-echarts";
|
||||
import { reactive } from "vue";
|
||||
import { reactive, onMounted } from "vue";
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
|
@ -17,6 +17,11 @@ use([
|
|||
GaugeChart
|
||||
]);
|
||||
|
||||
onMounted(() => {
|
||||
var mychart = document.getElementById("myCompass");
|
||||
mychart.firstChild.style.margin = "auto";
|
||||
});
|
||||
|
||||
const option = reactive({
|
||||
title: {
|
||||
text: '航向',
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<v-chart class="chart w-h-full" :option="option" />
|
||||
<v-chart id="myMap" class="chart w-h-full" :option="option" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue'
|
||||
import { reactive, onMounted } from 'vue'
|
||||
import { use, registerMap } from "echarts/core";
|
||||
import { CanvasRenderer } from 'echarts/renderers'
|
||||
import { MapChart, ScatterChart } from 'echarts/charts';
|
||||
|
@ -14,6 +14,11 @@ import { intersect, findMap } from "../assets/geojson/geo.js";
|
|||
|
||||
use([ CanvasRenderer, MapChart, ScatterChart ]);
|
||||
|
||||
onMounted(() => {
|
||||
var mychart = document.getElementById("myMap");
|
||||
mychart.firstChild.style.margin = "auto";
|
||||
});
|
||||
|
||||
registerMap('nowin', fullMap);
|
||||
|
||||
const option = reactive({
|
||||
|
@ -98,13 +103,13 @@ const option = reactive({
|
|||
});
|
||||
|
||||
const update = (longitude: number, latitude: number, deepset:Array<string|boolean>) => {
|
||||
option.series[0].data[0] = [longitude, latitude]
|
||||
let nowpoint = [longitude, latitude]
|
||||
let nowMap = intersect(nowpoint,fullMap)
|
||||
let findit = findMap(nowpoint,nowMap,deepset)
|
||||
registerMap('nowMap', findit)
|
||||
option.geo[0].map = 'nowMap'
|
||||
option.geo[1].map = 'nowMap'
|
||||
option.series[0].data[0] = [longitude, latitude];
|
||||
let nowpoint = [longitude, latitude];
|
||||
let nowMap = intersect(nowpoint,fullMap);
|
||||
let findit = findMap(nowpoint,nowMap,deepset);
|
||||
registerMap('nowMap', findit);
|
||||
option.geo[0].map = 'nowMap';
|
||||
option.geo[1].map = 'nowMap';
|
||||
}
|
||||
|
||||
defineExpose({ update })
|
||||
|
|
|
@ -7,60 +7,77 @@ import { reactive } from "vue";
|
|||
import { use } from "echarts/core";
|
||||
import { CanvasRenderer } from "echarts/renderers";
|
||||
import { ScatterChart } from "echarts/charts";
|
||||
import {
|
||||
TitleComponent,
|
||||
PolarComponent
|
||||
} from "echarts/components";
|
||||
import { TitleComponent, PolarComponent } from "echarts/components";
|
||||
import VChart from "vue-echarts";
|
||||
import { get_in_positioning_id } from '../api/util'
|
||||
import { get_in_positioning_id } from "../api/util";
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
ScatterChart,
|
||||
TitleComponent,
|
||||
PolarComponent
|
||||
]);
|
||||
import beidouImg from "../assets/img/beidou.png";
|
||||
import gpsImg from "../assets/img/gps.png";
|
||||
import glonassImg from "../assets/img/glonass.png";
|
||||
import galileoImg from "../assets/img/galileo.png";
|
||||
import unbeidouImg from "../assets/img/unbeidou.png";
|
||||
import ungpsImg from "../assets/img/ungps.png";
|
||||
import unglonassImg from "../assets/img/unglonass.png";
|
||||
import ungalileoImg from "../assets/img/ungalileo.png";
|
||||
|
||||
var baseImg = {
|
||||
beidou: beidouImg,
|
||||
gps: gpsImg,
|
||||
glonass: glonassImg,
|
||||
galileo: galileoImg,
|
||||
unbeidou: unbeidouImg,
|
||||
ungps: ungpsImg,
|
||||
unglonass: unglonassImg,
|
||||
ungalileo: ungalileoImg,
|
||||
};
|
||||
|
||||
use([CanvasRenderer, ScatterChart, TitleComponent, PolarComponent]);
|
||||
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
color: String
|
||||
})
|
||||
color: String,
|
||||
baseUrl: String,
|
||||
});
|
||||
|
||||
const option = reactive({
|
||||
title: {
|
||||
text: props.title,
|
||||
left: 'center',
|
||||
left: "center",
|
||||
textStyle: {
|
||||
color: 'white',
|
||||
fontSize:28,
|
||||
color: "white",
|
||||
fontSize: 28,
|
||||
textBorderColor: props.color,
|
||||
textBorderWidth: 2,
|
||||
textShadowColor: props.color,
|
||||
textShadowBlur: 12,
|
||||
}
|
||||
},
|
||||
},
|
||||
animation: false,
|
||||
polar: {
|
||||
radius: '72%'
|
||||
radius: "72%",
|
||||
},
|
||||
angleAxis: {
|
||||
min: 0,
|
||||
max: 360,
|
||||
interval: 45,
|
||||
axisTick: {
|
||||
show: false
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
fontSize: 24,
|
||||
formatter: function (value: number) {
|
||||
switch (value)
|
||||
{
|
||||
case 0 : return '北';
|
||||
case 90 : return '东';
|
||||
case 180 : return '南';
|
||||
case 270 : return '西';
|
||||
switch (value) {
|
||||
case 0:
|
||||
return "北";
|
||||
case 90:
|
||||
return "东";
|
||||
case 180:
|
||||
return "南";
|
||||
case 270:
|
||||
return "西";
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
radiusAxis: {
|
||||
min: -90,
|
||||
|
@ -70,83 +87,174 @@ const option = reactive({
|
|||
rotate: -25,
|
||||
showMinLabel: false,
|
||||
showMaxLabel: false,
|
||||
verticalAlign: 'bottom',
|
||||
formatter: function(value: number){
|
||||
return Math.abs(value)
|
||||
verticalAlign: "bottom",
|
||||
formatter: function (value: number) {
|
||||
return Math.abs(value);
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
series: [{
|
||||
nmea: 'un-positioning',
|
||||
coordinateSystem: 'polar',
|
||||
type: 'scatter',
|
||||
symbolSize: 32,
|
||||
label: {
|
||||
show: true,
|
||||
color: 'white',
|
||||
fontSize: 14,
|
||||
textBorderColor: ({ data } : any) => data[3] > 0 ? props.color : '#ccc',
|
||||
textBorderWidth: 2,
|
||||
formatter: '{@[2]}'
|
||||
series: [
|
||||
{
|
||||
nmea: "un-positioning",
|
||||
coordinateSystem: "polar",
|
||||
type: "scatter",
|
||||
symbolSize: 32,
|
||||
symbol: "image://" + baseImg[props.baseUrl],
|
||||
label: {
|
||||
show: true,
|
||||
color: "white",
|
||||
fontSize: 14,
|
||||
offset: [0,30],
|
||||
textBorderColor: props.color,
|
||||
textBorderWidth: 2,
|
||||
formatter: "{@[2]}",
|
||||
},
|
||||
itemStyle: {
|
||||
color: props.color,
|
||||
borderColor: props.color,
|
||||
borderWidth: 2,
|
||||
shadowColor: props.color,
|
||||
shadowBlur: 6,
|
||||
},
|
||||
},
|
||||
itemStyle: {
|
||||
color: ({ data } : any) => data[3] > 0 ? props.color : '#ccc',
|
||||
borderColor: ({ data } : any) => data[3] > 0 ? 'red' : '#ccc',
|
||||
borderWidth: ({ data } : any) => data[3] > 0 ? 2 : 0,
|
||||
shadowColor: ({ data } : any) => data[3] > 0 ? 'red' : '#ccc',
|
||||
shadowBlur: ({ data } : any) => data[3] > 0 ? 6 : 0,
|
||||
{
|
||||
nmea: "un-positioning-un",
|
||||
coordinateSystem: "polar",
|
||||
type: "scatter",
|
||||
symbolSize: 32,
|
||||
symbol: "image://" + baseImg["un" + props.baseUrl],
|
||||
label: {
|
||||
show: true,
|
||||
color: "white",
|
||||
fontSize: 14,
|
||||
offset: [0,30],
|
||||
textBorderColor: "#ccc",
|
||||
textBorderWidth: 2,
|
||||
formatter: "{@[2]}",
|
||||
},
|
||||
itemStyle: {
|
||||
color: "#ccc",
|
||||
borderColor: "#ccc",
|
||||
borderWidth: 0,
|
||||
shadowColor: "#ccc",
|
||||
shadowBlur: 0,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
nmea: 'in-positioning',
|
||||
coordinateSystem: 'polar',
|
||||
type: 'scatter',
|
||||
symbolSize: 32,
|
||||
label: {
|
||||
show: true,
|
||||
color: 'white',
|
||||
formatter: '{@[2]}'
|
||||
{
|
||||
nmea: "in-positioning",
|
||||
coordinateSystem: "polar",
|
||||
type: "scatter",
|
||||
symbolSize: 32,
|
||||
symbol: "image://" + baseImg[props.baseUrl],
|
||||
label: {
|
||||
show: true,
|
||||
color: "white",
|
||||
fontSize: 14,
|
||||
offset: [0,30],
|
||||
textBorderColor: props.color,
|
||||
textBorderWidth: 2,
|
||||
formatter: "{@[2]}",
|
||||
},
|
||||
itemStyle: {
|
||||
color: props.color,
|
||||
borderColor: props.color,
|
||||
borderWidth: 2,
|
||||
shadowColor: props.color,
|
||||
shadowBlur: 6,
|
||||
},
|
||||
},
|
||||
itemStyle: {
|
||||
color: ({ data } : any) => data[3] > 0 ? props.color : '#ccc'
|
||||
{
|
||||
nmea: "in-positioning-un",
|
||||
coordinateSystem: "polar",
|
||||
type: "scatter",
|
||||
symbolSize: 32,
|
||||
symbol: "image://" + baseImg["un" + props.baseUrl],
|
||||
label: {
|
||||
show: true,
|
||||
color: "white",
|
||||
fontSize: 14,
|
||||
offset: [0,30],
|
||||
textBorderColor: "#ccc",
|
||||
textBorderWidth: 2,
|
||||
formatter: "{@[2]}",
|
||||
},
|
||||
itemStyle: {
|
||||
color: "#ccc",
|
||||
borderColor: "#ccc",
|
||||
borderWidth: 0,
|
||||
shadowColor: "#ccc",
|
||||
shadowBlur: 0,
|
||||
},
|
||||
},
|
||||
}]
|
||||
})
|
||||
],
|
||||
});
|
||||
|
||||
const update = (GSVArr: Array<any>, GSAArr: Array<any>) => {
|
||||
const planisphereOption: any = getPlanisphereOption(GSVArr, GSAArr)
|
||||
if (!planisphereOption) return
|
||||
const planisphereOption: any = getPlanisphereOption(GSVArr, GSAArr);
|
||||
if (!planisphereOption) return;
|
||||
|
||||
Object.assign(option, planisphereOption)
|
||||
}
|
||||
const getPlanisphereOption = (GSVArr: Array<any>, GSAArr: Array<any>) => {
|
||||
Object.assign(option, planisphereOption);
|
||||
};
|
||||
const getPlanisphereOption = (GSVArr: Array<any>, GSAArr: Array<any>) => {
|
||||
try {
|
||||
let in_positioning_data: Array<any> = [],
|
||||
un_positioning_data: Array<any> = []
|
||||
const in_positioning_id = get_in_positioning_id(GSAArr)
|
||||
in_positioning_undata: Array<any> = [],
|
||||
un_positioning_data: Array<any> = [],
|
||||
un_positioning_undata: Array<any> = [];
|
||||
const in_positioning_id = get_in_positioning_id(GSAArr);
|
||||
|
||||
GSVArr.forEach(({ satellites }) => {
|
||||
satellites.forEach(({ id, elevationDeg, azimuthTrue, SNRdB }) => {
|
||||
if (in_positioning_id.indexOf(parseInt(id)) < 0) {
|
||||
un_positioning_data.push([parseInt(elevationDeg) * -1, azimuthTrue, id, SNRdB])
|
||||
if (SNRdB > 0) {
|
||||
un_positioning_data.push([
|
||||
parseInt(elevationDeg) * -1,
|
||||
azimuthTrue,
|
||||
id,
|
||||
SNRdB,
|
||||
]);
|
||||
} else {
|
||||
un_positioning_undata.push([
|
||||
parseInt(elevationDeg) * -1,
|
||||
azimuthTrue,
|
||||
id,
|
||||
SNRdB,
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
in_positioning_data.push([parseInt(elevationDeg) * -1, azimuthTrue, id, SNRdB])
|
||||
if (SNRdB > 0) {
|
||||
in_positioning_data.push([
|
||||
parseInt(elevationDeg) * -1,
|
||||
azimuthTrue,
|
||||
id,
|
||||
SNRdB,
|
||||
]);
|
||||
} else {
|
||||
in_positioning_undata.push([
|
||||
parseInt(elevationDeg) * -1,
|
||||
azimuthTrue,
|
||||
id,
|
||||
SNRdB,
|
||||
]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const planisphereOption = {
|
||||
series: [{
|
||||
data: un_positioning_data
|
||||
}, {
|
||||
data: in_positioning_data
|
||||
}]
|
||||
}
|
||||
|
||||
return planisphereOption
|
||||
const planisphereOption = {
|
||||
series: [
|
||||
{ data: un_positioning_data },
|
||||
{ data: un_positioning_undata },
|
||||
{ data: in_positioning_data },
|
||||
{ data: in_positioning_undata },
|
||||
],
|
||||
};
|
||||
|
||||
return planisphereOption;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
defineExpose({ update })
|
||||
</script>
|
||||
defineExpose({ update });
|
||||
</script>
|
||||
|
|
|
@ -7,39 +7,252 @@ import { use } from "echarts/core";
|
|||
import { CanvasRenderer } from "echarts/renderers";
|
||||
import { LegendComponent } from "echarts/components";
|
||||
import { PieChart } from "echarts/charts";
|
||||
import "echarts-gl";
|
||||
|
||||
import VChart from "vue-echarts";
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
LegendComponent,
|
||||
PieChart
|
||||
]);
|
||||
use([CanvasRenderer, LegendComponent, PieChart]);
|
||||
|
||||
const emit = defineEmits(['changeColor']);
|
||||
|
||||
const ring = ref(null);
|
||||
|
||||
// 生成环形的曲面参数方程,用于 series-surface.parametricEquation
|
||||
const getParametricEquation = (
|
||||
startRatio,
|
||||
endRatio,
|
||||
isSelected,
|
||||
isHovered,
|
||||
k,
|
||||
height,
|
||||
size
|
||||
) => {
|
||||
// 计算
|
||||
let midRatio = (startRatio + endRatio) / 2;
|
||||
|
||||
let startRadian = startRatio * Math.PI * 2;
|
||||
let endRadian = endRatio * Math.PI * 2;
|
||||
let midRadian = midRatio * Math.PI * 2;
|
||||
|
||||
// 如果只有一个环形,则不实现选中效果。
|
||||
if (startRatio === 0 && endRatio === 1) {
|
||||
isSelected = false;
|
||||
}
|
||||
|
||||
// 通过环形内径/外径的值,换算出辅助参数 k(默认值 1/3)
|
||||
k = typeof k !== "undefined" ? k : 1 / 3;
|
||||
|
||||
// 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
|
||||
let offsetX = isSelected ? Math.cos(midRadian) * 0.2 : 0;
|
||||
let offsetY = isSelected ? Math.sin(midRadian) * 0.2 : 0;
|
||||
// 计算选中效果在 z 轴方向上的位移(未选中,位移均为 0)
|
||||
let offsetZ = isSelected ? 0.15 : 0;
|
||||
// 计算高亮效果的放大比例(未高亮,则比例为 1)
|
||||
let hoverRate = isHovered ? size[0] : size[1];
|
||||
|
||||
// 返回曲面参数方程
|
||||
return {
|
||||
u: {
|
||||
min: -Math.PI,
|
||||
max: Math.PI * 3,
|
||||
step: Math.PI / 32,
|
||||
},
|
||||
|
||||
v: {
|
||||
min: 0,
|
||||
max: Math.PI * 2,
|
||||
step: Math.PI / 20,
|
||||
},
|
||||
|
||||
x: function (u, v) {
|
||||
if (u < startRadian) {
|
||||
return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
if (u > endRadian) {
|
||||
return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
},
|
||||
|
||||
y: function (u, v) {
|
||||
if (u < startRadian) {
|
||||
return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
if (u > endRadian) {
|
||||
return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
},
|
||||
|
||||
z: function (u, v) {
|
||||
if (u < -Math.PI * 0.5) {
|
||||
return Math.sin(u);
|
||||
}
|
||||
if (u > Math.PI * 2.5) {
|
||||
return Math.sin(u);
|
||||
}
|
||||
return Math.sin(v) > 0 ? 1 * height : -1;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const zeroEquation = getParametricEquation(0, 0, false, false, 1 / 2, 0, [0.8, 0.75]);
|
||||
|
||||
const option = reactive({
|
||||
legend: {
|
||||
bottom: '10%',
|
||||
left: 'center',
|
||||
selectedMode: false,
|
||||
itemGap: 12,
|
||||
itemWidth: 35,
|
||||
itemHeight: 20,
|
||||
textStyle: {
|
||||
color: 'white',
|
||||
fontSize: 16
|
||||
}
|
||||
bottom: '10%',
|
||||
left: 'center',
|
||||
selectedMode: false,
|
||||
itemGap: 12,
|
||||
itemWidth: 35,
|
||||
itemHeight: 20,
|
||||
textStyle: {
|
||||
color: 'auto',
|
||||
fontSize: 16
|
||||
}
|
||||
},
|
||||
xAxis3D: {
|
||||
min: -1,
|
||||
max: 1,
|
||||
},
|
||||
yAxis3D: {
|
||||
min: -1,
|
||||
max: 1,
|
||||
},
|
||||
zAxis3D: {
|
||||
min: -1,
|
||||
max: 1,
|
||||
},
|
||||
grid3D: {
|
||||
show: false,
|
||||
boxHeight: 20, // 厚度
|
||||
top: 0,
|
||||
left: 0,
|
||||
boxWidth: 100,
|
||||
viewControl: {
|
||||
//3d效果可以放大、旋转等,请自己去查看官方配置
|
||||
alpha: 45, // 角度
|
||||
beta: 135, // 环块开始位置角度
|
||||
rotateSensitivity: 0,
|
||||
zoomSensitivity: 0,
|
||||
panSensitivity: 0,
|
||||
autoRotate: false
|
||||
},
|
||||
light: {
|
||||
main: {
|
||||
color: "rgb(85, 84, 84)", // 主光源的颜色。
|
||||
shadow: true, // 主光源是否投射阴影
|
||||
alpha: 80, // 主光源绕 x 轴,即上下旋转的角度
|
||||
},
|
||||
},
|
||||
},
|
||||
color: ['#FF801C', '#F5FF46', '#00FE65', '#00FEFF', '#ffa800', '#ff5b00', '#ff3000'],
|
||||
series: [
|
||||
{
|
||||
name: "北 斗",
|
||||
type: "surface",
|
||||
parametric: true,
|
||||
wireframe: {
|
||||
show: false,
|
||||
},
|
||||
shading: "realistic",
|
||||
itemStyle: {
|
||||
color: "#ff3232",
|
||||
opacity: 0.5,
|
||||
},
|
||||
pieData: {
|
||||
name: "北 斗",
|
||||
value: 0,
|
||||
startRatio: 0,
|
||||
endRatio: 0,
|
||||
},
|
||||
pieStatus: {
|
||||
selected: false,
|
||||
hovered: false,
|
||||
},
|
||||
parametricEquation: zeroEquation,
|
||||
},
|
||||
{
|
||||
name: "G P S",
|
||||
type: "surface",
|
||||
parametric: true,
|
||||
wireframe: {
|
||||
show: false,
|
||||
},
|
||||
shading: "realistic",
|
||||
itemStyle: {
|
||||
color: "#00ffff",
|
||||
opacity: 0.5,
|
||||
},
|
||||
pieData: {
|
||||
name: "G P S",
|
||||
value: 0,
|
||||
startRatio: 0,
|
||||
endRatio: 0,
|
||||
},
|
||||
pieStatus: {
|
||||
selected: false,
|
||||
hovered: false,
|
||||
},
|
||||
parametricEquation: zeroEquation,
|
||||
},
|
||||
{
|
||||
name: "GLONASS",
|
||||
type: "surface",
|
||||
parametric: true,
|
||||
wireframe: {
|
||||
show: false,
|
||||
},
|
||||
shading: "realistic",
|
||||
itemStyle: {
|
||||
color: "#6600ff",
|
||||
opacity: 0.5,
|
||||
},
|
||||
pieData: {
|
||||
name: "GLONASS",
|
||||
value: 0,
|
||||
startRatio: 0,
|
||||
endRatio: 0,
|
||||
},
|
||||
pieStatus: {
|
||||
selected: false,
|
||||
hovered: false,
|
||||
},
|
||||
parametricEquation: zeroEquation,
|
||||
},
|
||||
{
|
||||
name: "Galileo",
|
||||
type: "surface",
|
||||
parametric: true,
|
||||
wireframe: {
|
||||
show: false,
|
||||
},
|
||||
shading: "realistic",
|
||||
itemStyle: {
|
||||
color: "#00ff66",
|
||||
opacity: 0.5,
|
||||
},
|
||||
pieData: {
|
||||
name: "Galileo",
|
||||
value: 0,
|
||||
startRatio: 0,
|
||||
endRatio: 0,
|
||||
},
|
||||
pieStatus: {
|
||||
selected: false,
|
||||
hovered: false,
|
||||
},
|
||||
parametricEquation: zeroEquation,
|
||||
},
|
||||
{
|
||||
color: ['#ff323200', '#00ffff00', '#6600ff00', '#00ff6600'],
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
startAngle: 180,
|
||||
silent: true,
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
position: 'center',
|
||||
},
|
||||
emphasis: {
|
||||
scaleSize: 25,
|
||||
|
@ -48,7 +261,9 @@ const option = reactive({
|
|||
color: 'white',
|
||||
fontSize: '28',
|
||||
fontWeight: 'bold',
|
||||
formatter: '{c}\n\n{b}'
|
||||
formatter: '{c}\n\n{b}',
|
||||
textBorderWidth: 1,
|
||||
textShadowBlur: 24,
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
|
@ -61,37 +276,84 @@ const option = reactive({
|
|||
{ value: 0, name: 'Galileo' }
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
});
|
||||
|
||||
const ring = ref(null)
|
||||
const COUNT = option.series[0].data.length
|
||||
let highlightIndex = -1
|
||||
const highlight = () => {
|
||||
ring.value.dispatchAction({
|
||||
type: 'downplay',
|
||||
dataIndex: highlightIndex
|
||||
})
|
||||
const getPie3D = (sumValue, pieValue, internalDiameterRatio, height, size) => {
|
||||
let startValue = 0;
|
||||
let endValue = 0;
|
||||
// internalDiameterRatio(0~1之间的浮点数):内径/外径的值(默认值 1/2)
|
||||
let k =
|
||||
typeof internalDiameterRatio !== "undefined"
|
||||
? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
|
||||
: 1 / 3;
|
||||
// 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个环形。
|
||||
for (let i = option.series.length - 2; i >= 0; i--) {
|
||||
endValue = startValue + pieValue[i];
|
||||
option.series[i].pieData.startRatio = startValue / sumValue;
|
||||
option.series[i].pieData.endRatio = endValue / sumValue;
|
||||
option.series[i].parametricEquation = getParametricEquation(
|
||||
option.series[i].pieData.startRatio,
|
||||
option.series[i].pieData.endRatio,
|
||||
option.series[i].pieStatus.selected,
|
||||
option.series[i].pieStatus.hovered,
|
||||
k,
|
||||
height,
|
||||
size
|
||||
);
|
||||
startValue = endValue;
|
||||
}
|
||||
};
|
||||
|
||||
let highlightIndex = 0;
|
||||
let reset = false;
|
||||
const highlight = () => {
|
||||
let colorPie = ['#ff3232', '#00ffff', '#6600ff', '#00ff66'];
|
||||
reset = !reset;
|
||||
for (let i = 0; i < option.series.length - 1; i++) {
|
||||
option.series[i].itemStyle.opacity = 0.5;
|
||||
option.series[i].pieStatus.selected = false;
|
||||
option.series[i].pieStatus.hovered = false;
|
||||
emit('changeColor',false);
|
||||
ring.value.dispatchAction({
|
||||
type: 'downplay',
|
||||
dataIndex: i
|
||||
})
|
||||
}
|
||||
if (reset) {
|
||||
option.series[highlightIndex].itemStyle.opacity = 1;
|
||||
option.series[highlightIndex].pieStatus.selected = true;
|
||||
option.series[highlightIndex].pieStatus.hovered = true;
|
||||
emit('changeColor',true,highlightIndex);
|
||||
ring.value.dispatchAction({
|
||||
type: 'highlight',
|
||||
dataIndex: highlightIndex
|
||||
})
|
||||
option.series[4].emphasis.label.color = colorPie[highlightIndex];
|
||||
option.series[4].emphasis.label.textBorderColor = colorPie[highlightIndex];
|
||||
option.series[4].emphasis.label.textShadowColor = colorPie[highlightIndex];
|
||||
highlightIndex++;
|
||||
if (highlightIndex >= option.series.length - 1) highlightIndex = 0;
|
||||
}
|
||||
};
|
||||
|
||||
highlightIndex++
|
||||
if (highlightIndex >= COUNT) highlightIndex = 0
|
||||
|
||||
ring.value.dispatchAction({
|
||||
type: 'highlight',
|
||||
dataIndex: highlightIndex
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
setInterval(highlight, 3000)
|
||||
})
|
||||
setInterval(highlight, 2500);
|
||||
});
|
||||
|
||||
const update = (bd_val: number, gp_val: number, gl_val: number, ga_val: number) => {
|
||||
option.series[0].data[0].value = bd_val
|
||||
option.series[0].data[1].value = gp_val
|
||||
option.series[0].data[2].value = gl_val
|
||||
option.series[0].data[3].value = ga_val
|
||||
}
|
||||
option.series[0].pieData.value = bd_val;
|
||||
option.series[1].pieData.value = gp_val;
|
||||
option.series[2].pieData.value = gl_val;
|
||||
option.series[3].pieData.value = ga_val;
|
||||
option.series[4].data[0].value = bd_val;
|
||||
option.series[4].data[1].value = gp_val;
|
||||
option.series[4].data[2].value = gl_val;
|
||||
option.series[4].data[3].value = ga_val;
|
||||
let sum_val = bd_val + gp_val + gl_val + ga_val;
|
||||
let pie_val = [bd_val, gp_val, gl_val, ga_val];
|
||||
getPie3D(sum_val, pie_val, 7 / 10, 1, [0.8, 0.75]);
|
||||
};
|
||||
|
||||
|
||||
defineExpose({ update })
|
||||
</script>
|
||||
defineExpose({ update });
|
||||
</script>
|
||||
|
|
|
@ -5,154 +5,158 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from "vue"
|
||||
import { reactive } from "vue";
|
||||
import { use, graphic } from "echarts/core";
|
||||
import { CanvasRenderer } from "echarts/renderers";
|
||||
import { BarChart } from "echarts/charts";
|
||||
import { TitleComponent, GridComponent, DataZoomComponent } from "echarts/components";
|
||||
import VChart from "vue-echarts";
|
||||
import { get_in_positioning_id } from '../api/util'
|
||||
import { get_in_positioning_id } from "../api/util";
|
||||
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
BarChart,
|
||||
TitleComponent,
|
||||
GridComponent,
|
||||
DataZoomComponent
|
||||
]);
|
||||
use([CanvasRenderer, BarChart, TitleComponent, GridComponent, DataZoomComponent]);
|
||||
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
color: String,
|
||||
})
|
||||
let LinearStart!: string
|
||||
let LinearEnd!: string
|
||||
});
|
||||
let LinearStart!: string;
|
||||
let LinearEnd!: string;
|
||||
switch (props.color) {
|
||||
case 'rgb(0,204,255)':
|
||||
LinearStart = '#00ffff'
|
||||
LinearEnd = '#0033ff'
|
||||
break;
|
||||
case 'rgb(255,255,0)':
|
||||
LinearStart = '#ffffcc'
|
||||
LinearEnd = '#ffff00'
|
||||
break;
|
||||
case 'rgb(102,0,255)':
|
||||
LinearStart = '#6699ff'
|
||||
LinearEnd = '#6600ff'
|
||||
break;
|
||||
case 'rgb(0,204,102)':
|
||||
LinearStart = '#00cccc'
|
||||
LinearEnd = '#00ff66'
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case "rgb(255,50,50)":
|
||||
LinearStart = "#ffc864";
|
||||
LinearEnd = "#ff3232";
|
||||
break;
|
||||
|
||||
case "rgb(0,204,255)":
|
||||
LinearStart = "#00ffff";
|
||||
LinearEnd = "#0033ff";
|
||||
break;
|
||||
|
||||
const BAR_COUNT = 30
|
||||
const UN_POSITIONING_COLOR = '#9ca3af'
|
||||
const IN_POSITIONING_COLOR = new graphic.LinearGradient(
|
||||
0, 1, 0, 0,
|
||||
[
|
||||
{offset: 0, color: LinearStart},
|
||||
{offset: 1, color: LinearEnd}
|
||||
]
|
||||
)
|
||||
case "rgb(102,0,255)":
|
||||
LinearStart = "#6699ff";
|
||||
LinearEnd = "#6600ff";
|
||||
break;
|
||||
|
||||
const option = reactive({
|
||||
case "rgb(0,204,102)":
|
||||
LinearStart = "#00cccc";
|
||||
LinearEnd = "#00ff66";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const BAR_COUNT = 30;
|
||||
const UN_POSITIONING_COLOR = "#9ca3af";
|
||||
const IN_POSITIONING_COLOR = new graphic.LinearGradient(0, 1, 0, 0, [
|
||||
{ offset: 0, color: LinearStart },
|
||||
{ offset: 1, color: LinearEnd },
|
||||
]);
|
||||
|
||||
const option = reactive({
|
||||
title: {
|
||||
text: props.title,
|
||||
left: 'center',
|
||||
left: "center",
|
||||
top: 36,
|
||||
textStyle: {
|
||||
color: 'white',
|
||||
fontSize:36,
|
||||
color: "white",
|
||||
fontSize: 36,
|
||||
textBorderColor: props.color,
|
||||
textBorderWidth: 2,
|
||||
textShadowColor: props.color,
|
||||
textShadowBlur: 12,
|
||||
}
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
axisTick: {show: false},
|
||||
axisLine: {show: false},
|
||||
type: "category",
|
||||
axisTick: { show: false },
|
||||
axisLine: { show: false },
|
||||
axisLabel: {
|
||||
show:true,
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: 'white',
|
||||
fontSize:12,
|
||||
textBorderColor: props.color,
|
||||
textBorderWidth: 1,
|
||||
textShadowColor: props.color,
|
||||
textShadowBlur: 1
|
||||
}
|
||||
}
|
||||
color: "white",
|
||||
fontSize: 12,
|
||||
textBorderColor: props.color,
|
||||
textBorderWidth: 1,
|
||||
textShadowColor: props.color,
|
||||
textShadowBlur: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
show: false,
|
||||
max: 60
|
||||
max: 60,
|
||||
},
|
||||
|
||||
series: [{
|
||||
type: 'bar',
|
||||
barCategoryGap: '50%',
|
||||
label: {
|
||||
show: true,
|
||||
color: 'white',
|
||||
position: 'top',
|
||||
textBorderColor: props.color,
|
||||
textBorderWidth: 1,
|
||||
textShadowColor: props.color,
|
||||
textShadowBlur: 1,
|
||||
formatter: function ({ value }) {
|
||||
return !value || value[1] === 0 ? '' : value[1];
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
|
||||
series: [
|
||||
{
|
||||
type: "bar",
|
||||
// barMinHeight: 10,
|
||||
barCategoryGap: "50%",
|
||||
label: {
|
||||
show: true,
|
||||
color: "white",
|
||||
position: "top",
|
||||
textBorderColor: props.color,
|
||||
textBorderWidth: 1,
|
||||
textShadowColor: props.color,
|
||||
textShadowBlur: 1,
|
||||
formatter: function ({ value }) {
|
||||
// return !value || value[1] === 0 ? '0' : value[1];
|
||||
return !value || value[1] === 0 ? "" : value[1];
|
||||
},
|
||||
},
|
||||
itemStyle: {
|
||||
barBorderRadius: [50, 50, 0, 0],
|
||||
color: IN_POSITIONING_COLOR,
|
||||
color: function ({ value }) {
|
||||
return !value || value[1] === 0 ? UN_POSITIONING_COLOR : IN_POSITIONING_COLOR;
|
||||
},
|
||||
shadowColor: props.color,
|
||||
shadowBlur: 6
|
||||
shadowBlur: 6,
|
||||
},
|
||||
},
|
||||
}]
|
||||
})
|
||||
const update = (GSVArr: Array<any>, GSAArr: Array<any>, lineMax:String) => {
|
||||
const SNROption: any = getSNROption(GSVArr, GSAArr, lineMax)
|
||||
if (!SNROption) return
|
||||
|
||||
],
|
||||
});
|
||||
const update = (GSVArr: Array<any>, GSAArr: Array<any>, lineMax: String) => {
|
||||
const SNROption: any = getSNROption(GSVArr, GSAArr, lineMax);
|
||||
if (!SNROption) return;
|
||||
|
||||
if (SNROption.xAxis.data.length !== SNROption.series[0].data.length) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const length = SNROption.xAxis.data.length
|
||||
|
||||
const length = SNROption.xAxis.data.length;
|
||||
if (length < BAR_COUNT) {
|
||||
const fill_num = BAR_COUNT - length
|
||||
SNROption.xAxis.data = SNROption.xAxis.data.concat(new Array(fill_num).fill(''))
|
||||
SNROption.series[0].data = SNROption.series[0].data.concat(new Array(fill_num).fill(0))
|
||||
const fill_num = BAR_COUNT - length;
|
||||
SNROption.xAxis.data = SNROption.xAxis.data.concat(new Array(fill_num).fill(""));
|
||||
SNROption.series[0].data = SNROption.series[0].data.concat(
|
||||
new Array(fill_num).fill(0)
|
||||
);
|
||||
}
|
||||
|
||||
Object.assign(option, SNROption)
|
||||
}
|
||||
const getSNROption = (GSVArr: Array<any>, GSAArr: Array<any>, lineMax:String) => {
|
||||
|
||||
Object.assign(option, SNROption);
|
||||
};
|
||||
const descend = (x, y) => {
|
||||
return x[0] - y[0]; //按照数组的第1个值降序排列
|
||||
};
|
||||
const getSNROption = (GSVArr: Array<any>, GSAArr: Array<any>, lineMax: String) => {
|
||||
try {
|
||||
let xAxis_max : String = ''
|
||||
let xAxis_data : Array<any> = []
|
||||
let series_data : Array<any> = []
|
||||
const in_positioning_id = get_in_positioning_id(GSAArr)
|
||||
|
||||
let xAxis_max: String = "";
|
||||
let xAxis_data: Array<any> = [];
|
||||
let series_data: Array<any> = [];
|
||||
const in_positioning_id = get_in_positioning_id(GSAArr);
|
||||
|
||||
GSAArr.forEach(({ satellites }) => {
|
||||
in_positioning_id.push(...satellites)
|
||||
in_positioning_id.push(...satellites);
|
||||
});
|
||||
|
||||
GSVArr.forEach(({ satellites }) => {
|
||||
satellites.forEach(({ id, SNRdB }) => {
|
||||
xAxis_data.push(id)
|
||||
xAxis_data.push(id);
|
||||
if (in_positioning_id.indexOf(parseInt(id)) < 0) {
|
||||
series_data.push([id, SNRdB, false])
|
||||
series_data.push([id, SNRdB, false]);
|
||||
} else {
|
||||
series_data.push([id, SNRdB, true])
|
||||
series_data.push([id, SNRdB, true]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -161,18 +165,20 @@ const getSNROption = (GSVArr: Array<any>, GSAArr: Array<any>, lineMax:String) =>
|
|||
const SNROption = {
|
||||
xAxis: {
|
||||
max: xAxis_max,
|
||||
data: xAxis_data
|
||||
data: xAxis_data.sort(),
|
||||
},
|
||||
series: [{
|
||||
data: series_data
|
||||
}]
|
||||
}
|
||||
series: [
|
||||
{
|
||||
data: series_data.sort(descend),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return SNROption
|
||||
return SNROption;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
defineExpose({ update })
|
||||
</script>
|
||||
defineExpose({ update });
|
||||
</script>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<VChart :option="option" />
|
||||
<VChart id="myWaterLevel" :option="option" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from "vue";
|
||||
import { reactive, onMounted } from "vue";
|
||||
import { use } from "echarts/core";
|
||||
import { CanvasRenderer } from "echarts/renderers";
|
||||
import { TitleComponent } from "echarts/components";
|
||||
|
@ -16,6 +16,11 @@ use([
|
|||
TitleComponent
|
||||
]);
|
||||
|
||||
onMounted(() => {
|
||||
var mychart = document.getElementById("myWaterLevel");
|
||||
mychart.firstChild.style.margin = "auto";
|
||||
});
|
||||
|
||||
|
||||
const option = reactive({
|
||||
title: {
|
||||
|
|
|
@ -17,88 +17,194 @@
|
|||
<WaterLevel ref="waterLevel" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="block-right-content ml-2 flex flex-1">
|
||||
<div class="block-right-content mx-2 flex flex-1">
|
||||
<Map ref="map" />
|
||||
</div>
|
||||
<div class="block-right-content w-1/5 flex flex-col py-2 px-2">
|
||||
<div id="animationList" class="animationText mb-2">
|
||||
</div>
|
||||
<div id="newnmeaList" class="animationText">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</full-screen-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import FullScreenContainer from '../components/Layout/FullScreenContainer.vue'
|
||||
import TheHeader from '../components/Layout/TheHeader.vue'
|
||||
import DigitalFlopContainer from '../components/DigitalFlopContainer.vue'
|
||||
import Clock from '../components/Clock.vue'
|
||||
import Compass from '../components/Compass.vue'
|
||||
import WaterLevel from '../components/WaterLevel.vue'
|
||||
import Map from '../components/Map.vue'
|
||||
import FullScreenContainer from "../components/Layout/FullScreenContainer.vue";
|
||||
import TheHeader from "../components/Layout/TheHeader.vue";
|
||||
import DigitalFlopContainer from "../components/DigitalFlopContainer.vue";
|
||||
import Clock from "../components/Clock.vue";
|
||||
import Compass from "../components/Compass.vue";
|
||||
import WaterLevel from "../components/WaterLevel.vue";
|
||||
import Map from "../components/Map.vue";
|
||||
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { Helpers } from 'nmea'
|
||||
import { getNMEAObj } from '../api/util'
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
import { Helpers } from "nmea";
|
||||
import { getNMEAObj } from "../api/util";
|
||||
|
||||
const digitalFlopContainer = ref(null)
|
||||
const clock = ref(null)
|
||||
const compass = ref(null)
|
||||
const waterLevel = ref(null)
|
||||
const map = ref(null)
|
||||
const deepmsg = ref(null)
|
||||
const update = (nmeaStr: string) => {
|
||||
const data: any = getMonitoringData(nmeaStr)
|
||||
if (!data) return
|
||||
const digitalFlopContainer = ref(null);
|
||||
const clock = ref(null);
|
||||
const compass = ref(null);
|
||||
const waterLevel = ref(null);
|
||||
const map = ref(null);
|
||||
const deepmsg = ref(null);
|
||||
const animationValue = ref('');
|
||||
const colorId = ref(0);
|
||||
const stagingObj = reactive({
|
||||
dataTime: null,
|
||||
longitude: NaN,
|
||||
latitude: NaN,
|
||||
alt: 0,
|
||||
variation: null,
|
||||
variationPole: null,
|
||||
numSat: 0,
|
||||
});
|
||||
|
||||
const { dateTime, longitude, latitude, alt, variation, variationPole, numSat } = data
|
||||
digitalFlopContainer.value.update(dateTime, longitude, latitude, alt, numSat)
|
||||
clock.value.update(dateTime)
|
||||
compass.value.update(variation, variationPole)
|
||||
waterLevel.value.update(alt)
|
||||
console.log(deepmsg.value)
|
||||
map.value.update(longitude, latitude, deepmsg.value)
|
||||
}
|
||||
|
||||
const deepset = (deepArr: Array<string|boolean>) => {
|
||||
deepmsg.value = deepArr
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if ('ipcRenderer' in window) {
|
||||
ipcRenderer.receive('deep', deepset)
|
||||
ipcRenderer.receive('nmea', update)
|
||||
|
||||
ipcRenderer.send('APP_MOUNTED')
|
||||
}
|
||||
})
|
||||
const getDate = (date, timestamp) => {
|
||||
const year = date.substring(4);
|
||||
const month = date.substring(2, 4);
|
||||
const day = date.substring(0, 2);
|
||||
const hours = timestamp.substring(0, 2);
|
||||
const minutes = timestamp.substring(2, 4);
|
||||
const seconds = timestamp.substring(4, 6);
|
||||
const dateTimeStr = `20${year}-${month}-${day}T${hours}:${minutes}:${seconds}+00:00`;
|
||||
const dateTime = new Date(dateTimeStr);
|
||||
return dateTime;
|
||||
};
|
||||
|
||||
const getMonitoringData = (nmeaStr: string) => {
|
||||
const nmeaObj: any = getNMEAObj(nmeaStr)
|
||||
console.log(nmeaObj, '================')
|
||||
if (!nmeaObj || !nmeaObj.RMC || !nmeaObj.GGA) return null
|
||||
const nmeaObj: any = getNMEAObj(nmeaStr);
|
||||
console.log(nmeaObj, "================");
|
||||
if (!nmeaObj || !nmeaObj.RMC || !nmeaObj.GGA) return null;
|
||||
|
||||
const { RMC, GGA } = nmeaObj
|
||||
const { RMC, GGA } = nmeaObj;
|
||||
// 日期,时间,磁偏角,磁偏角方向
|
||||
const { date, timestamp, variation, variationPole } = RMC
|
||||
const { date, timestamp, variation, variationPole } = RMC;
|
||||
// 经度,经度方向,纬度,纬度方向,海拔,用于定位的卫星数目
|
||||
const { lon, lonPole, lat, latPole, alt, numSat } = GGA
|
||||
const { lon, lonPole, lat, latPole, alt, numSat } = GGA;
|
||||
|
||||
const year = date.substring(4)
|
||||
const month = date.substring(2, 4)
|
||||
const day = date.substring(0, 2)
|
||||
const hours = timestamp.substring(0, 2)
|
||||
const minutes = timestamp.substring(2, 4)
|
||||
const seconds = timestamp.substring(4, 6)
|
||||
const dateTimeStr = `20${year}-${month}-${day}T${hours}:${minutes}:${seconds}+00:00`
|
||||
const dateTime = new Date(dateTimeStr)
|
||||
const dateTime = getDate(date, timestamp);
|
||||
|
||||
const longitude = Helpers.parseLongitude(lon, lonPole)
|
||||
const latitude = Helpers.parseLatitude(lat, latPole)
|
||||
const longitude = Helpers.parseLongitude(lon, lonPole);
|
||||
const latitude = Helpers.parseLatitude(lat, latPole);
|
||||
|
||||
return { dateTime, longitude, latitude, alt, variation, variationPole, numSat }
|
||||
}
|
||||
return { dateTime, longitude, latitude, alt, variation, variationPole, numSat };
|
||||
};
|
||||
|
||||
const update = (nmeaStr: string) => {
|
||||
const data: any = getMonitoringData(nmeaStr);
|
||||
if (!data) return;
|
||||
|
||||
const { dateTime, longitude, latitude, alt, variation, variationPole, numSat } = data;
|
||||
if (longitude != NaN && latitude != NaN && longitude != "NaN" && latitude != "NaN") {
|
||||
stagingObj.dateTime = dateTime;
|
||||
stagingObj.longitude = longitude;
|
||||
stagingObj.latitude = latitude;
|
||||
stagingObj.alt = alt;
|
||||
stagingObj.variation = variation;
|
||||
stagingObj.variationPole = variationPole;
|
||||
stagingObj.numSat = numSat;
|
||||
} else {
|
||||
stagingObj.dateTime = new Date();
|
||||
}
|
||||
digitalFlopContainer.value.update(
|
||||
stagingObj.dateTime,
|
||||
stagingObj.longitude,
|
||||
stagingObj.latitude,
|
||||
stagingObj.alt,
|
||||
stagingObj.numSat
|
||||
);
|
||||
clock.value.update(stagingObj.dateTime);
|
||||
compass.value.update(stagingObj.variation, stagingObj.variationPole);
|
||||
waterLevel.value.update(stagingObj.alt);
|
||||
console.log(deepmsg.value);
|
||||
map.value.update(stagingObj.longitude, stagingObj.latitude, deepmsg.value);
|
||||
};
|
||||
|
||||
var nmeaList;
|
||||
var newList;
|
||||
|
||||
const animate = (options) => {
|
||||
var start = performance.now();
|
||||
|
||||
requestAnimationFrame(function animate(time) {
|
||||
// timeFraction 的值从 0 到 1 变化
|
||||
var timeFraction = (time - start) / options.duration;
|
||||
if (timeFraction > 1) timeFraction = 1;
|
||||
|
||||
// 动画的当前状态
|
||||
var progress = options.timing(timeFraction);
|
||||
|
||||
options.draw(progress);
|
||||
|
||||
if (timeFraction < 1) {
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const add = (timeFraction) => {
|
||||
return 1 - Math.sin(Math.acos(timeFraction));
|
||||
};
|
||||
|
||||
const animateText = (nmeaNode, nmeaMsg) => {
|
||||
let text = nmeaMsg,
|
||||
textArr = text.split("\r\n"),
|
||||
showText = textArr.slice(0,20).join("\r\n"),
|
||||
to = showText.length;
|
||||
|
||||
animate({
|
||||
duration: 1000,
|
||||
timing: add,
|
||||
draw: function (progress) {
|
||||
nmeaNode.innerText = text.substr(0, to*progress);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
let colorPie = ['#DAE3F3','#FBE5D6','#EDEDED','#FFF2CC','#DEEBF7','#E2F0D9'];
|
||||
const nmeaAnmiation = async (nmeaOrigin: string) => {
|
||||
if (nmeaOrigin != undefined) {
|
||||
nmeaList.innerText = animationValue.value;
|
||||
nmeaList.style.color = colorPie[colorId.value];
|
||||
animateText(newList, nmeaOrigin);
|
||||
colorId.value++;
|
||||
if(colorId.value == 6){
|
||||
colorId.value = 0;
|
||||
}
|
||||
newList.style.color = colorPie[colorId.value];
|
||||
animationValue.value = nmeaOrigin;
|
||||
}
|
||||
};
|
||||
|
||||
const deepset = (deepArr: Array<string | boolean>) => {
|
||||
deepmsg.value = deepArr;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if ("ipcRenderer" in window) {
|
||||
ipcRenderer.receive("deep", deepset);
|
||||
ipcRenderer.receive("nmea", update);
|
||||
ipcRenderer.receive("NMEA_RECEIVED", nmeaAnmiation);
|
||||
|
||||
ipcRenderer.send("APP_MOUNTED");
|
||||
}
|
||||
nmeaList = document.getElementById("animationList");
|
||||
newList = document.getElementById("newnmeaList");
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.clock-content, .compass-content, .water-level-content, .block-right-content {
|
||||
background-color: rgba(6,30,93,.5);
|
||||
.clock-content,
|
||||
.compass-content,
|
||||
.water-level-content,
|
||||
.block-right-content {
|
||||
background-color: rgba(6, 30, 93, 0.5);
|
||||
}
|
||||
</style>
|
||||
.animationText {
|
||||
font-size: 0.5rem;
|
||||
line-height: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<ScrollBoardTable ref="BDScrollBoardTable" title="北 斗" />
|
||||
</border-box-3>
|
||||
<border-box-3>
|
||||
<ScrollBoardTable ref="GAScrollBoardTable" title="Galileo" />
|
||||
<ScrollBoardTable ref="GLScrollBoardTable" title="GLONASS" />
|
||||
</border-box-3>
|
||||
</div>
|
||||
<div class="w-1/2 px-2">
|
||||
|
@ -21,7 +21,7 @@
|
|||
<ScrollBoardTable ref="GPScrollBoardTable" title="G P S" />
|
||||
</border-box-3>
|
||||
<border-box-3>
|
||||
<ScrollBoardTable ref="GLScrollBoardTable" title="GLONASS" />
|
||||
<ScrollBoardTable ref="GAScrollBoardTable" title="Galileo" />
|
||||
</border-box-3>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
<div class="main-content flex-1 grid grid-cols-2 grid-rows-2">
|
||||
<div class="w-11/12 justify-self-end">
|
||||
<SNRView ref="BDSNRView" color="rgb(0,204,255)" title="北斗" />
|
||||
<SNRView ref="BDSNRView" color="rgb(255,50,50)" title="北斗" />
|
||||
</div>
|
||||
<div class="w-11/12 justify-self-start">
|
||||
<SNRView ref="GPSNRView" color="rgb(255,255,0)" title="GPS" />
|
||||
<SNRView ref="GPSNRView" color="rgb(0,204,255)" title="GPS" />
|
||||
</div>
|
||||
<div class="w-11/12 justify-self-end">
|
||||
<SNRView ref="GLSNRView" color="rgb(102,0,255)" title="GLONASS" />
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
|
||||
<div class="main-content flex-1 grid grid-cols-2 grid-rows-2">
|
||||
<div class="w-5/6 justify-self-end">
|
||||
<PlanisphereView ref="BDPlanisphereView" color="rgb(0,204,255)" title="北斗" />
|
||||
<PlanisphereView ref="BDPlanisphereView" color="rgb(255,50,50)" title="北斗" baseUrl="beidou" />
|
||||
</div>
|
||||
<div class="w-5/6 justify-self-start">
|
||||
<PlanisphereView ref="GPPlanisphereView" color="rgb(255,255,0)" title="GPS" />
|
||||
<PlanisphereView ref="GPPlanisphereView" color="rgb(10,40,100)" title="GPS" baseUrl="gps" />
|
||||
</div>
|
||||
<div class="w-5/6 justify-self-end">
|
||||
<PlanisphereView ref="GLPlanisphereView" color="rgb(102,0,255)" title="GLONASS" />
|
||||
<PlanisphereView ref="GLPlanisphereView" color="rgb(10,60,170)" title="GLONASS" baseUrl="glonass" />
|
||||
</div>
|
||||
<div class="w-5/6 justify-self-start">
|
||||
<PlanisphereView ref="GAPlanisphereView" color="rgb(0,204,102)" title="Galileo" />
|
||||
<PlanisphereView ref="GAPlanisphereView" color="rgb(10,60,160)" title="Galileo" baseUrl="galileo" />
|
||||
</div>
|
||||
</div>
|
||||
</full-screen-container>
|
||||
|
|