显示效果全面优化

master
qubiaobiao 2024-03-25 14:52:39 +08:00
parent 763a4832b4
commit a36b1dafd6
25 changed files with 1512 additions and 1088 deletions

View File

@ -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",

View File

@ -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])
}

View File

@ -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))

View File

@ -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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -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>

View File

@ -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: {

View File

@ -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: '航向',

View File

@ -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 })

View File

@ -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',
},
series: [
{
nmea: "un-positioning",
coordinateSystem: "polar",
type: "scatter",
symbolSize: 32,
symbol: "image://" + baseImg[props.baseUrl],
label: {
show: true,
color: 'white',
color: "white",
fontSize: 14,
textBorderColor: ({ data } : any) => data[3] > 0 ? props.color : '#ccc',
offset: [0,30],
textBorderColor: props.color,
textBorderWidth: 2,
formatter: '{@[2]}'
formatter: "{@[2]}",
},
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,
color: props.color,
borderColor: props.color,
borderWidth: 2,
shadowColor: props.color,
shadowBlur: 6,
},
}, {
nmea: 'in-positioning',
coordinateSystem: 'polar',
type: 'scatter',
},
{
nmea: "un-positioning-un",
coordinateSystem: "polar",
type: "scatter",
symbolSize: 32,
symbol: "image://" + baseImg["un" + props.baseUrl],
label: {
show: true,
color: 'white',
formatter: '{@[2]}'
color: "white",
fontSize: 14,
offset: [0,30],
textBorderColor: "#ccc",
textBorderWidth: 2,
formatter: "{@[2]}",
},
itemStyle: {
color: ({ data } : any) => data[3] > 0 ? props.color : '#ccc'
color: "#ccc",
borderColor: "#ccc",
borderWidth: 0,
shadowColor: "#ccc",
shadowBlur: 0,
},
}]
})
},
{
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,
},
},
{
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)
}
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 {
in_positioning_data.push([parseInt(elevationDeg) * -1, azimuthTrue, id, SNRdB])
un_positioning_undata.push([
parseInt(elevationDeg) * -1,
azimuthTrue,
id,
SNRdB,
]);
}
} else {
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
}]
}
series: [
{ data: un_positioning_data },
{ data: un_positioning_undata },
{ data: in_positioning_data },
{ data: in_positioning_undata },
],
};
return planisphereOption
return planisphereOption;
} catch (error) {
console.error(error);
}
}
};
defineExpose({ update })
defineExpose({ update });
</script>

View File

@ -7,15 +7,97 @@ 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: {
@ -26,20 +108,151 @@ const option = reactive({
itemWidth: 35,
itemHeight: 20,
textStyle: {
color: 'white',
color: 'auto',
fontSize: 16
}
},
color: ['#FF801C', '#F5FF46', '#00FE65', '#00FEFF', '#ffa800', '#ff5b00', '#ff3000'],
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
},
},
},
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 getPie3D = (sumValue, pieValue, internalDiameterRatio, height, size) => {
let startValue = 0;
let endValue = 0;
// internalDiameterRatio0~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: highlightIndex
dataIndex: i
})
highlightIndex++
if (highlightIndex >= COUNT) highlightIndex = 0
}
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;
}
};
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 })
defineExpose({ update });
</script>

View File

@ -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'
case "rgb(255,50,50)":
LinearStart = "#ffc864";
LinearEnd = "#ff3232";
break;
case 'rgb(255,255,0)':
LinearStart = '#ffffcc'
LinearEnd = '#ffff00'
case "rgb(0,204,255)":
LinearStart = "#00ffff";
LinearEnd = "#0033ff";
break;
case 'rgb(102,0,255)':
LinearStart = '#6699ff'
LinearEnd = '#6600ff'
case "rgb(102,0,255)":
LinearStart = "#6699ff";
LinearEnd = "#6600ff";
break;
case 'rgb(0,204,102)':
LinearStart = '#00cccc'
LinearEnd = '#00ff66'
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 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,
color: "white",
fontSize: 12,
textBorderColor: props.color,
textBorderWidth: 1,
textShadowColor: props.color,
textShadowBlur: 1
}
}
textShadowBlur: 1,
},
},
},
yAxis: {
show: false,
max: 60
max: 60,
},
series: [{
type: 'bar',
barCategoryGap: '50%',
series: [
{
type: "bar",
// barMinHeight: 10,
barCategoryGap: "50%",
label: {
show: true,
color: 'white',
position: 'top',
color: "white",
position: "top",
textBorderColor: props.color,
textBorderWidth: 1,
textShadowColor: props.color,
textShadowBlur: 1,
formatter: function ({ value }) {
return !value || value[1] === 0 ? '' : value[1];
}
// 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,
shadowColor: props.color,
shadowBlur: 6
color: function ({ value }) {
return !value || value[1] === 0 ? UN_POSITIONING_COLOR : IN_POSITIONING_COLOR;
},
}]
})
const update = (GSVArr: Array<any>, GSAArr: Array<any>, lineMax:String) => {
const SNROption: any = getSNROption(GSVArr, GSAArr, lineMax)
if (!SNROption) return
shadowColor: props.color,
shadowBlur: 6,
},
},
],
});
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 })
defineExpose({ update });
</script>

View File

@ -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: {

View File

@ -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);
}
.animationText {
font-size: 0.5rem;
line-height: 1rem;
}
</style>

View File

@ -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>

View File

@ -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" />

View File

@ -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>

1378
yarn.lock

File diff suppressed because it is too large Load Diff