You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1366 lines
47 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { drawAxis, drawAxis2D, draw2DText } from './draw.js';
import { loadOption, GIL1, GIL2, GIL3, GIL4, CPD, CPD1 } from './echartsOptions.js';
let renderer, scene, camera, controls, renderer2D, scene2D, camera2D, controls2D;
//let socket = null;
let axis = new THREE.Group();
let axis2D = new THREE.Group();
let initAxis = 80;//正值最大值
let maxNum = [];//上一次的最大值
let minNum = 0;//负值最大值
let planes = [];//截断面
let i18n;
let viewType = 1;//窗口显示状态1初始状态PRPSorPRPD只显示一个且可以切换 2半屏状态3其他窗口半屏状态
const paramsStr = window.location.search
const params = new URLSearchParams(paramsStr)
let viewIndex = params.get('viewIndex') || 0;//视窗序号
let productId = params.get('productId') || 2;//产品id
let deviceId = params.get('deviceId') || '50100001_1';//设备id
let win;//窗口序列
let isReconnect = false;
let socket;
let token = 'c9343e83005e1f2b458d66628ddff98b'
let url = `ws://192.168.1.88:8844/messaging/${token}`
//const stats = new Stats();
//document.body.appendChild(stats.dom);
let box2D6 = document.getElementById('box2D6');
let box2D6chart = '';
let maxRange = 100;
let clearHistory = 30;
// //打点统计次数颜色
let realTime = {
channelFiltering: 0,//频段过滤 //必填
switch: 1,//开关1、启动、0、关闭 //必填
mapCategory: 3,//图谱类型1、PRPS、2、PRPD、3、PRPS/PRPD //必填
monitorType: 1,// GIS 1 GIL故障定位 2 GIL局放 3 电缆 4 //必填
cumulativeDot: 1,//累计打点时长 默认1秒-1则无限累计 //必填
correlationDenoising: 0,//关联降噪1、启动、0、关闭 //不必填
adaptiveNoise: 0,//自适应降噪1、启动、0、关闭 //不必填
groundNoise: 0,//手动降噪 //不必填
migrationPhase: 0,//偏移相位//不必填
waveSwitch: 0,//录播开关1、开始、0、停止 //不必填
atlasType: 1,
}
//电缆局放1 PRPS/PRPD 2 折现图
let atlasType = 1;
// monitorType GIS 1 GIL故障定位 2 GIL局放 3 电缆 4
// atlasType 1 PRPS/PRPD 2 飞行模式/脉冲数据 3 连续模式
const lut = new THREE.Lut();
lut.addColorMap('axis', [[0.0, 0x00ee00], [0.25, 0xeeee00], [0.75, 0xee0000], [1.0, 0x4e0211]],);
lut.setColorMap('axis', 500)
let meshList = new THREE.Group();//图例柱子
const dummy = new THREE.Object3D();
meshList.name = 'chartsMesh';
let pointsList = new THREE.Group();//图例散点
pointsList.name = 'chartsPoint';
let axisTextGroup = new THREE.Group();
axisTextGroup.name = 'axisText';
let axisTextGroup2D = new THREE.Group();
axisTextGroup2D.name = 'axisText';
// 周期,相位 柱子数
let period = 50, phase = 128, count = period * phase;
const geometry = new THREE.BoxGeometry(0.6, 1, 2.5);
geometry.computeVertexNormals()
//非光泽表面的材质,没有镜面高光
//const initInstancedMesh = new THREE.InstancedMesh(geometry, new THREE.MeshLambertMaterial(), count);
//最佳性能材质
const initInstancedMesh = new THREE.InstancedMesh(geometry, new THREE.MeshBasicMaterial(), count);
initInstancedMesh.name = 'initInstancedMesh';
/* prpd初始Instanced点 */
let initInstancedPoints,//prpd实例
pointPositions, pointColors,//PRPS位置及颜色的集合
pointsGeometry = new THREE.BufferGeometry(),
pointCount;
//pointsGeometry = new THREE.BoxGeometry(0, 0.8, (360 / initAxis) * 0.8,),// prpd位置属性数组
//pointsGeometry.computeVertexNormals()
let counter = 1;
const switchFun = {
showHistory: {
open() {
initTrendChart()
},
close() {
}
}
};
$('.switch').on('click', function () {
$(this).toggleClass('active');
if ($(this).hasClass('active')) {
console.log('开关已打开');
} else {
console.log('开关已关闭');
}
});
$('#setting-btn').click(function () {
$(this).toggleClass('ready')
$('#setting').toggle()
})
//菜单展示隐藏
$('#show').click(function () {
$('.LinkANC').toggle();
$('#associated-noise-box').toggle()
$('.eventList').toggle();
$('#record-btn-box').toggle();
$('.refreshtitle').toggle();
$('#total').toggle();
$('.noisy-slide-box').toggle();
$('#addPointNumDiv').toggle();
$(this).toggleClass('ready')
})
//prps or prpd 切换
$('#prps').click(function () {
updateParams('mapCategory', $(this), 1)
$('#box3D1').toggle();
$('#box2D1').toggle();
$('#prpd').toggleClass('ready')
})
$('#prpd').click(function () {
updateParams('mapCategory', $(this), 2)
$('#box2D1').toggle();
$('#box3D1').toggle();
$('#prps').toggleClass('ready')
})
//暂停or开启
$('#start').click(function () {
updateParams('switch', $(this))
})
//图谱放大缩小
$('.scale').click(function () {
if ($(this).hasClass('big')) {
maxRange = maxRange + 25;
$('.small').removeClass('ready')
if (maxRange == 100) {
$(this).toggleClass('ready')
}
} else {
maxRange = maxRange - 25;
$('.big').removeClass('ready')
if (maxRange == 25) {
$(this).toggleClass('ready')
}
}
drawAxis((maxRange / 100) * initAxis, 0);
clearPoints()
let constant = (360 / (maxRange)) * maxRange + 1
planes[0].constant = constant
})
//自适应降噪
$('#adaptive-noise').click(function () {
if (!realTime.adaptiveNoise) {//groundNoise
$(".noisy-slide").slider({ value: -80 });
$(".noisy-slide span").attr('data-content', '底噪' + ' ' + -80);
$(".noisy-slide").slider({ disabled: true });
realTime.groundNoise = 0;
} else {
$(".noisy-slide").slider({ disabled: false });
}
updateParams('adaptiveNoise', $(this))
})
//关联传感器降噪
$('#associated-noise').click(function () {
updateParams('correlationDenoising', $(this))
})
// 录播按钮点击
$('.record-btn-box').click(function () {
let $this = $(this).children();
if (socket) {
//初始状态没暂停clss且录播状态为停止的时候添加该class
if (!$this.hasClass('pause') && !realTime.waveSwitch) {
$this.addClass('pause')
}
$this.toggleClass('live')
$this.toggleClass('pause')
}
updateParams('waveSwitch', null)
})
$('.refresh-btn').click(function () {
$('#total').slideToggle()
})
//累计打点时间输入
$("#total-time").on("input", function () { // 使用 "input" 事件可以实现实时过滤
var currentValue = $(this).val();
var filteredValue = currentValue.replace(/[^0-9]/g, ''); // 使用正则表达式过滤非数字字符
if (currentValue !== filteredValue) {
$(this).val(filteredValue); // 如果有变化,则更新输入框的值
}
});
$('#total-time').blur(function () {
const value = $(this).val() || 1
updateParams('cumulativeDot', null, value)
if (value == 1) {
if (!$('.refresh-btn').hasClass('ready')) {
$('.refresh-btn').addClass('ready')
}
} else {
$('.refresh-btn').removeClass('ready')
}
})
//频段切换
$('#channelFiltering').on('change', function () {
let val = $(this).val();
updateParams('channelFiltering', null, val)
})
//更新socket参数
function updateParams(prams, that, value) {
if (socket) {
realTime[prams] = value || (realTime[prams] ? 0 : 1);
that && that.toggleClass('ready')
sendMessage()
}
}
loadOption();
init();
init2D();
render();
render2D();
initTrendChart();
onWindowResize()
function initTrendChart() {
box2D6chart = echarts.init(box2D6)
setTimeout(() => {
box2D6chart.setOption(CPD);
})
}
const generateArray = () => {
const newArray = [];
const step = 360 / phase;
for (let i = 1; i <= phase; i++) {
newArray.push([counter, (360 - parseInt(i * step)), getRandomInt(10, 65)]);
}
counter = (counter % period) + 1;
return newArray;
}
const generateArray1 = () => {
const newArray = [];
for (let i = 0; i < 4000; i++) {
newArray.push([getRandomInt(0, 360), getRandomInt(0, 80), getRandomInt(1, 15)])
}
return newArray
}
function initPointsFun() {
if (initInstancedPoints) {
pointsList.remove(initInstancedPoints);
initInstancedPoints.material.dispose()//map(i => { i.dispose() })
initInstancedPoints.geometry.dispose()//map(i => { i.disponse() })
initInstancedPoints = null;
}
let maxYPointsMap = [800, 10000, 10000, 7000];
let maxYPoints = maxYPointsMap[realTime.monitorType - 1];
pointCount = phase * maxYPoints;
pointPositions = new Float32Array(pointCount * 3) // x, y, z
pointColors = new Float32Array(pointCount * 3) // r, g, b
// 初始化点的位置和颜色
for (let i = 0; i < pointCount; i++) {
const x = i
const y = 9999
const z = 10
pointPositions[i * 3] = x
pointPositions[i * 3 + 1] = y
pointPositions[i * 3 + 2] = z
pointColors[i * 3] = Math.random()
pointColors[i * 3 + 1] = Math.random()
pointColors[i * 3 + 2] = Math.random()
}
pointsGeometry.setAttribute('position', new THREE.BufferAttribute(pointPositions, 3))
pointsGeometry.setAttribute('color', new THREE.BufferAttribute(pointColors, 3))
// 创建 ShaderMateria
const material = new THREE.PointsMaterial({ size: 2, vertexColors: true })
// 创建 Points 对象
initInstancedPoints = new THREE.Points(pointsGeometry, material)
initInstancedPoints.name = 'initInstancedPoints';
// const object1 = meshList.getObjectByName('initInstancedMesh');
// if (!object1) {
pointsList.add(initInstancedPoints);
//}
}
initCharts()
function initCharts(type) {
if (type == 'open') {
meshList.visible = true;
return;
} else if (type == 'close') {
meshList.visible = false;
let k = 1, s = 1;
for (let j = 0; j < period; j++) {
for (let i = 0; i < phase; i++) {
initInstancedMesh.getMatrixAt(k, dummy.matrix);
dummy.position.setFromMatrixPosition(dummy.matrix);
dummy.scale.setFromMatrixScale(dummy.matrix);
dummy.position.y = 99999;
dummy.scale.y = Math.abs(1);
const color = lut.getColor(Math.abs(0) / initAxis);
initInstancedMesh.setColorAt(k, color);
dummy.updateMatrix();
initInstancedMesh.setMatrixAt(k, dummy.matrix);
k++;
}
}
initInstancedMesh.instanceMatrix.needsUpdate = true;
initInstancedMesh.instanceColor.needsUpdate = true;
for (let i = 0; i < pointCount; i++) {
pointPositions[i * 3 + 1] = 9999999 // Y//移到y轴高出隐藏多余的点
}
// 通知 Three.js 更新 BufferGeometry
pointsGeometry.attributes.position.needsUpdate = true
return;
}
let k = 0, initList = [];
for (let i = 0; i < period; i++) {
initList.push(generateArray());
}
for (let j = 0; j < initList.length; j++) {
for (let i = 0; i < initList[j].length; i++) {
const [a, b, c] = initList[j][i];
dummy.position.set(j, 99999, b);
dummy.scale.y = 0;
dummy.updateMatrix();
initInstancedMesh.setMatrixAt(k, dummy.matrix);
const color = lut.getColor(Math.abs(c) / initAxis);
initInstancedMesh.setColorAt(k, color);
k++;
}
}
initInstancedMesh.instanceMatrix.needsUpdate = true;
initInstancedMesh.instanceColor.needsUpdate = true;
const object = meshList.getObjectByName('initInstancedMesh');
if (!object) {
meshList.add(initInstancedMesh);
}
initPointsFun()
}
function drawPRPD(list, clear) {
if (clear) {
if (initInstancedPoints) {
for (let i = 0; i < pointCount; i++) {
pointPositions[i * 3 + 1] = 9999999 // Y//移到y轴高出隐藏多余的点
}
// 通知 Three.js 更新 BufferGeometry
pointsGeometry.attributes.position.needsUpdate = true
}
}
const colors = [
{
color: new THREE.Color(0x50A3BA),
num: 5,
},
{
color: new THREE.Color(0x9DB578),
num: 7,
},
{
color: new THREE.Color(0xEAC736),
num: 10,
},
{
color: new THREE.Color(0xE28B4A),
num: 14,
},
];
const range = realTime.monitorType == 1 ? maxRange : false;
const max = range ? initAxis * (range / 100) : initAxis;
list.forEach((item, index) => {
// 更新颜色
const color = item[2] <= 3 ? new THREE.Color(0x0082df) : (item[2] >= 15 ? new THREE.Color(0xD94E5D) : colors.find(i => item[2] <= i.num).color);
pointPositions[index * 3] = 10 // X
pointPositions[index * 3 + 1] = item[1] > max ? max : item[1] // Y
pointPositions[index * 3 + 2] = 360 - item[0] // Z
pointColors[index * 3] = color.r //R
pointColors[index * 3 + 1] = color.g //G
pointColors[index * 3 + 2] = color.b //B
})
for (let i = list.length - 1; i < pointCount; i++) {
pointPositions[i * 3 + 1] = 9999999 // Y//移到y轴高出隐藏多余的点
}
// 通知 Three.js 更新 BufferGeometry
pointsGeometry.attributes.position.needsUpdate = true
pointsGeometry.attributes.color.needsUpdate = true
}
function drawPRPS(data) {
let k = 0;
let list = JSON.parse(JSON.stringify(data))
list = list.map((i) => ({
h: i[2],
color: lut.getColor(Math.abs((i[2]) / initAxis).toFixed(2)),
}))
for (let j = 0; j < period; j++) {
for (let i = 0; i < list.length; i++) {
initInstancedMesh.getMatrixAt(k, dummy.matrix);
dummy.position.setFromMatrixPosition(dummy.matrix);
dummy.scale.setFromMatrixScale(dummy.matrix);
if (dummy.position.x > 0) {
dummy.position.x -= 1;
} else {
let { h, color } = list[i];
dummy.position.x = 49;
dummy.position.y = h == 0 ? 99999 : h / 2;
dummy.scale.y = Math.abs(h);
initInstancedMesh.setColorAt(k, color);
}
dummy.updateMatrix();
initInstancedMesh.setMatrixAt(k, dummy.matrix);
k++;
}
}
initInstancedMesh.instanceMatrix.needsUpdate = true;
initInstancedMesh.instanceColor.needsUpdate = true;
}
// 在页面加载完成后执行WebSocket连接的代码
document.addEventListener('DOMContentLoaded', function () {
//initSocket()
// aaa()
//bbb()
});
function sendMessage() {
let ws = new WebSocket(url); // 替换成你的WebSocket服务器地址
// 当WebSocket连接打开时执行此函数
ws.onopen = function (event) {
ws.send(JSON.stringify({
"type": "sub",
"topic": `/device-message-sender/${productId}/${deviceId}`,
"parameter": {
"messageType": "INVOKE_FUNCTION",
"inputs": realTime,
"functionId": "requestPrpsData",
"headers": {
"async": true
}
},
"id": "request-id"
}))
}
}
//滑动条初始化
function LoadSlide() {
// 相位偏移滑动条
$(".cdf-slide").slider({
orientation: "horizontal",
animate: "slow",
min: -180,
max: 180,
step: 1,
value: 0,
create: function (event, ui) {
$(this).children('.ui-slider-handle').attr('data-content', '相位偏移' + ` 0 ` + '度')
},
slide: function (event, ui) {
$(this).children('.ui-slider-handle').attr('data-content', '相位偏移' + ` ${ui.value} ` + '度');
$(this).attr('data-price', ui.value);
},
change: function (event, ui) {
updateParams('migrationPhase', null, ui.value)
}
});
// 底噪滑动条
$(".noisy-slide.GIS").slider({
orientation: "vertical",
animate: "slow",
min: -80,
max: 0,
step: 1,
value: -80,
create: function (event, ui) {
$(this).children('.ui-slider-handle').attr('data-content', '底噪' + ` -80`)
},
slide(event, ui) {
$(this).children('.ui-slider-handle').attr('data-content', '底噪' + ` ${ui.value}`);
},
change: function (event, ui) {
updateParams('groundNoise', null, 80 + ui.value)
}
});
$(".noisy-slide.GIL").slider({
orientation: "vertical",
animate: "slow",
min: 0,
max: 80,
step: 1,
value: 0,
create: function (event, ui) {
$(this).children('.ui-slider-handle').attr('data-content', '底噪' + ` 0`)
},
slide(event, ui) {
$(this).children('.ui-slider-handle').attr('data-content', '底噪' + ` ${ui.value}`);
},
change: function (event, ui) {
$(this).attr('data-price', ui.value);
if ($(this).parent().parent().parent().hasClass('realdata')) {
realTime.groundNoise = ui.value;
if (socket != '' && socket != null && !$('#adaptive-noise').hasClass("ready")) {
socket.emit('realTimeSet', realTime);
}
}
}
});
}
//更新趋势图谱
function updataHistory(timestamp, realData) {
let time = timestampToTime(timestamp),
data = [[time, (realData.max).toFixed(2)]],
data1 = [[time, realData.count]],
option = box2D6chart.getOption();
if (option.xAxis[0].data.length > clearHistory) {
box2D6chart.setOption({
xAxis: [{
type: 'category',
data: [time],
}],
series: [
{ seriesIndex: 0, data },
{ seriesIndex: 1, data: data1 }
]
})
} else {
box2D6chart.setOption({
xAxis: [{
type: 'category',
data: [...box2D6chart.getOption().xAxis[0].data, time],
}]
})
box2D6chart.appendData({ seriesIndex: 0, data })
box2D6chart.appendData({ seriesIndex: 1, data: data1 })
box2D6chart.resize()
}
}
function initSocket() {
socket = new WebSocket(url); // 替换成你的WebSocket服务器地址
// 当WebSocket连接打开时执行此函数
socket.onopen = function (event) {
console.log('WebSocket连接已打开');
socket.send(JSON.stringify({
"type": "sub",
"topic": `/device/${productId}/${deviceId}/message/property/report`,
"parameter": {
"messageType": "READ_PROPERTY",
},
"id": "request-id"
}));
$('#start').addClass('ready')
$('.record-btn').addClass('ready')
$('#total-time').prop('disabled', false)
sendMessage()
LoadSlide()
};
// 当接收到服务器发送的消息时,执行此函数
socket.onmessage = function (event) {
const data = JSON.parse(event.data);
const { payload: { properties: { realData }, timestamp } } = data
console.log("🚀 data:", data)
if (realData?.lists2d?.length) {
drawEcharts1(null, realData.lists2d);
$('#maxValue').html(`${(realData.max).toFixed(2)}`);
$('#averageValue').html(`${(realData.avg).toFixed(2)}`);
$('#impulseQuantity').html(`${realData.count}`);
updataHistory(timestamp, realData)
}
if (realData?.lists3d?.length) {
drawEcharts1(realData.lists3d);
}
};
// 当WebSocket连接关闭时执行此函数
socket.onclose = function (event) {
console.log('WebSocket连接已关闭');
};
// 当发生错误时,执行此函数
socket.onerror = function (error) {
console.error('WebSocket错误:', error);
};
}
// 时间戳1637244864707
/* 时间戳转换为时间 */
function timestampToTime(timestamp) {
timestamp = timestamp ? timestamp : null;
let date = new Date(timestamp);//时间戳为10位需*1000时间戳为13位的话不需乘1000
let Y = date.getFullYear() + '-';
let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
let D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
let h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
let m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':';
let s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
return Y + M + D + h + m + s;
}
function bbb() {
setTimeout(() => {
drawPRPD(generateArray1())
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
const seconds = now.getSeconds();
//console.log(box2D6chart.series)
const data1 = [[`${hours}:${minutes}:${seconds}`, getRandomInt(-20, -40)], ...box2D6chart.getOption().series[0].data]
//const data2 = [[`${hours}:${minutes}:${seconds}`, getRandomInt(2000, 4400)],...box2D7chart.getOption().series[0].data]
box2D6chart.setOption({ series: [{ type: 'line', data: data1 }] });
bbb()
}, 1000)
}
function aaa() {
setTimeout(() => {
drawPRPS(generateArray());
aaa();
}, 20);
}
//aaa();
// 生成指定范围内的随机整数
function getRandomInt(min, max) {
const randomNumber = Math.random() * (max - min) + min;
const roundedNumber = randomNumber.toFixed(0);
return parseFloat(roundedNumber);
}
//电缆局放折线图更新提交
$('#form-submit').click(function () {
if ($('#realdata').attr('data-id')) {
socket.emit('getFrequencyData', { wl: $('#form-wl').val(), fltr: $('#form-fltr').val() });
}
})
//dom加载完成时
$(window).ready(function () {
$(window).scrollTop(0, 0);
let maxHeight1 = 500, maxHeight = 273
let h = $(window).height();
let w = $(window).width();
$(".loading-box").css('height', h * 0.75)
$(".loading-box-mini").css('height', h * 0.25)
$('.noisy-slide').css('height', h * 0.4)
$('.toggle--checkbox').attr('checked', 'false');
$('.record-btn').removeClass('ready');
$('#total-time').prop('disabled', true)
let isLoad = { command: 'load', win: win }
// title 国际化
window.parent.postMessage(isLoad, '*');
})
// 页面放大缩小时
$(window).resize(function () {
//window.requestAnimationFrame(function () {
onWindowResize()
// })
})
//清空Three中的Point点位
function clearPoints(type) {
// drawPRPS([], true);
drawPRPD([], true);
}
//量程切换
// 实时数据量程修改
$('#original').on('change', function () {
let val = ($(this).val() / 100) * initAxis;
if (maxRange != val) {
clearPoints();
let $this = $(this);
const max = ($this.val() / 100) * initAxis
$this.parent().addClass('is-checked').parent().addClass('is-checked').siblings().removeClass('is-checked').children().removeClass('is-checked')
$("[name='range']:checked").attr("checked", false);
$("[name='range'][value='" + $this.val() + "']").attr("checked", true);
//initAxis = val;
drawAxis(val, 0);
clearPoints()
maxRange = $this.val();
let constant = (360 / (max)) * max + 1
planes[0].constant = constant
}
})
// 打开事件列表
$('.event-btn').on('click', function () {
if ($(this).hasClass('ready')) {
var isFull = !!(document.webkitIsFullScreen || document.mozFullScreen ||
document.msFullscreenElement || document.fullscreenElement
);
if (isFull) {
var dblChoseAlert = simpleAlert({
"content": i18n.message.exitFullScreen + ` `,
"buttons": {
"确定": function () {
dblChoseAlert.close();
}
}
})
} else {
let deviceNum = $('#realdata').attr('data-deviceNum'),
channelNum = $('#realdata').attr('data-chanel'),
name = $('#realdata').attr('data-name');
let data = { command: 'eventList', win: win, deviceNum: deviceNum, channelNum: channelNum, name: name };
window.parent.postMessage(data, '*');
}
}
})
//全屏
$(".charts").on("dblclick", function () {
if (viewIndex == 88) {
window.parent.postMessage({ command: 'closeFullScreen', index: viewIndex }, '*');
} else {
window.parent.postMessage({ command: 'dblClick', index: viewIndex }, '*');
}
})
$("#prps-img").on('click', function () {
// 获取渲染器renderer的canvas然后调用todataurl方法获取数据URI
let dataUrl = renderer.domElement.toDataURL();
console.log("🚀 renderer.domElement:", renderer.domElement)
// 将DataURL转换为Blob对象
let blob = dataURLtoBlob(dataUrl);
// 创建下载链接
let link = document.createElement('a');
link.setAttribute('download', 'PRPS.png');
let url = URL.createObjectURL(blob);
console.log("🚀 url:", url)
link.href = url//.replace('http', 'https');
// 将下载链接添加到HTML页面
document.body.appendChild(link);
// 触发下载链接的单击事件
link.click();
})
function dataURLtoBlob(dataUrl) {
const arr = dataUrl.split(',');
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
$("#prpd-img").on('click', function () {
// 获取渲染器renderer的canvas然后调用todataurl方法获取数据URI
let dataUrl = renderer2D.domElement.toDataURL('image/png');
// 将DataURL转换为Blob对象
let blob = dataURLtoBlob(dataUrl);
// 创建下载链接
let link = document.createElement('a');
link.setAttribute('download', 'PRPD.png');
link.href = URL.createObjectURL(blob);
// 将下载链接添加到HTML页面
document.body.appendChild(link);
// 触发下载链接的单击事件
link.click();
})
//主页面传递事件
window.addEventListener('message', function (e) {
let data = e.data;
window.parent.postMessage(data, '*');
if (data.command == 'i18n') {
viewIndex = viewIndex ? viewIndex : data.index;
$('.phaseOffset').html('相位偏移')
$('.LinkNC').attr('title', '关联噪声传感器降噪')
$('.LinkANC').attr('title', '自适应降噪')
$('#record-btn-box').attr('title', '录波')
$('#toggle-box').attr('title', '开启/暂停')
$('.noise').html('底噪')
// $('.addPointNum').html(CumulativeRBI)
$('.eventList').attr('title', '事件列表')
$('.refreshtitle').attr('title', '刷新')
$('.channelNum .name').html('监测点' + "")
$('.maxValue .name').html('脉冲最大值' + "")
// $('.pc-tip .name').html(discharge + '')
// $('.avgValue .name').html(data.i18n.content.realTime.gil.averageValue + "")
$('.pulseNumber .name').html('脉冲数量' + "")
} else if (data.command == 'setView') {
viewType = data.viewType;
onWindowResize()
} else if (data.command == 'open') {
$('#box3D1').show();
$('#box3D2').hide();
let { id, name, equipmentId, channelNum, monitorType, ipAddress } = data;
$("#range100").click();
$('#model-tab-dl-1').click();
$('#realdata').attr('data-id', id)
$('#realdata').attr('data-name', name)
$('#realdata').attr('data-deviceNum', equipmentId)
$('#realdata').attr('data-chanel', channelNum)
atlasType = 1;
initChangeType(monitorType)
//不一致 切换图谱
if (realTime.monitorType != monitorType) {
realTime.monitorType = monitorType;
changeEcharts(monitorType);
initPointsFun();
}
initCharts('open');
if ($('#realdata').children('.echarts-btn').first().children('.toggle--knob').children('.toggle--checkbox').is(':checked')) {
// console.log("kai----"+data.win)
// console.log(data)
// console.log($('#toggle--knob1'))
$('#toggle--knob1').click()
}
win = data.win;
initRealTime();
} else if (data.command == 'close') {
if ($('#realdata').attr('data-id') == data.id) {
$('#realdata').attr('data-id', '')
$('#realdata').attr('data-name', '')
$('#realdata').attr('data-deviceNum', '')
$('#realdata').attr('data-chanel', '')
$(".noisy-slide").slider({ disabled: false });
if (!$('#realdata').children('.echarts-btn').first().children('.toggle--knob').children('.toggle--checkbox').is(':checked')) {
$('#toggle--knob1').click()
}
$('#channelNum').html('&nbsp;&nbsp;');
$('#maxValue').html("0");
$('#averageValue').html("0");
$('#impulseQuantity').html("0");
// $('#pc-number').html('0');
$('#clear').click();
$('#model-tab-dl-1').click()
$('#associated-noise').addClass('disabled');
$('#adaptive-noise').addClass('disabled');
clearPoints()
win = undefined;
initCharts('close');
}
} else if (data.command == 'historyPRPD') {
} else if (data.command == 'historyPRPS') {
}
})
function changeEcharts(type) {
upDrawAxis(0, 0, type)
if (type == 1) {
$('.unit').html('dBm')
$(".noisy-slide.GIL").fadeOut(() => {
$(".noisy-slide.GIS").fadeIn();
});
// $('.pc-tip').hide();
$('#model-tab-dl').hide();
} else if (type == 2 || type == 3) {
realTime.atlasType = 1;
$('#model-tab button:first-child').addClass('active').siblings().removeClass('active')
$('.unit').html('mV')
$(".noisy-slide.GIS").fadeOut(() => {
$(".noisy-slide.GIL").fadeIn();
});
//$('.pc-tip').hide();
$('#model-tab-dl').hide();
} else if (type == 4) {
atlasType = 1;
$('#model-tab-dl button:first-child').addClass('active').siblings().removeClass('active')
$('.unit').html('mV');
//$('.pc-tip').show();
$('#model-tab-dl').show()
}
}
function initRealTime() {
$('.associated-noise').removeClass('ready');
$('.adaptive-noise').removeClass('ready');
$("#channelFiltering").val(0);
if (realTime.monitorType == 1) {
$(".noisy-slide").slider({ value: -80 });
$(".noisy-slide span").attr('data-content', i18n.content.realTime.gis.noise1 + ' ' + -80);
} else if (realTime.monitorType == 2 || realTime.monitorType == 3) {
$(".noisy-slide").slider({ value: 0 });
$(".noisy-slide span").attr('data-content', i18n.content.realTime.gis.noise1 + ' ' + 0);
}
realTime.channelFiltering = 0;
realTime.cumulativeDot = 1;
realTime.correlationDenoising = 0;
realTime.adaptiveNoise = 0;
realTime.groundNoise = 0;
}
function downloadPng(type) {
let dataUrl = '';
// 获取渲染器renderer的canvas然后调用todataurl方法获取数据URI
if (type) {
dataUrl = renderer.domElement.toDataURL('image/png');
} else {
dataUrl = renderer2D.domElement.toDataURL('image/png');
}
// 将DataURL转换为Blob对象
let blob = new Blob([dataUrl], { type: 'image/png' });
// 创建下载链接
let link = document.createElement('a');
link.setAttribute('download', 'my_scene_image.png');
link.href = URL.createObjectURL(blob);
// 将下载链接添加到HTML页面
document.body.appendChild(link);
// 触发下载链接的单击事件
link.click();
}
//初始化绘制坐标轴文字
function drawAxisText(textMap, type) {
let setTextMap = '';
if (textMap) {
setTextMap = textMap;
} else {
let {
content: {
analyzeDiagnosis: {
analyzeDiagnosis: { amplitude }
},
},
tip: { period, phase, } } = i18n;
let inifo = {
amplitude,
period,
phase,
};
setTextMap = inifo;
}
if (type == 2 || type == 3) {
setTextMap.amplitude = 'mV';
} else if (type == 4) {
setTextMap.amplitude = 'mV';
}
let infoNum = [
{}, {
w: 60,
h: 32,
cw: 9,
ch: 8,
size: 26.3,
}, {}, {
w: 125,
h: 50,
size: 38.3,
}, {
w: 125,
h: 50,
size: 38.3,
},
{
w: 130,
h: 50,
size: 38.3,
}, {}, {}, {
w: 165,
h: 122,
size: 68.3,
},
]
let axisText = [{
type: 'text',
lang: true,
content: 'amplitude',
rotate: 90,
color: '#000000',
size: 30,
font: 'normal Bold 500px Arial,sans-serif',
xyz: [-60, minNum ? 0 : 120, 382],
},
{
type: 'text',
lang: true,
content: 'period',
xyz: [150, -180, 420],
xyz: [minNum ? 250 : 150, minNum ? -220 : -130, 420],
color: '#000000',
size: 30,
font: 'normal Bold 500px Arial,sans-serif',
},
{
type: 'text',
lang: true,
content: 'phase',
color: '#000000',
size: 30,
font: 'normal Bold 500px Arial,sans-serif',
xyz: [500, -110, 140],
},];
let axis2dText = [{
type: 'text',
lang: true,
content: 'amplitude',
rotate: 10,
color: '#000000',
size: 30,
font: 'normal Bold 500px Arial,sans-serif',
xyz: [-20, minNum ? 0 : 180, 405],
},
{
type: 'text',
lang: true,
content: 'phase',
color: '#000000',
size: 30,
font: 'normal Bold 500px Arial,sans-serif',
xyz: [0, minNum ? -265 : -87, 180],
},];
let setList = (list) => {
let newList = [];
for (let i of list) {
let str = setTextMap[i.content];
i.content = [str];
let { w, h, cw, ch, size } = infoNum[str.length - 1]
i.w = i.rotate ? h : w;
i.h = i.rotate ? w : h;
i.cw = i.rotate ? ch : cw;
i.ch = i.rotate ? cw : ch;
i.size = size;
if (i.rotate) {
i.xyz[2] = 445 + size / 2;
}
newList.push(draw2DText(i))
}
return newList
}
axisTextGroup.children.length && axisTextGroup.remove(...axisTextGroup.children)
axisTextGroup.add(...setList(axisText))
axisTextGroup2D.children.length && axisTextGroup2D.remove(...axisTextGroup2D.children)
axisTextGroup2D.add(...setList(axis2dText))
}
//根据坐标轴类型更新坐标轴
function upDrawAxis(max, min, type) {
if (!type) {
initAxis = max; minNum = min; drawAxis(initAxis, minNum);
return;
}
if (type == 1) {
initAxis = 80; minNum = 0;
drawAxis(initAxis, minNum);
} else if (type == 3 || type == 2) {
initAxis = 500; minNum = 0;
drawAxis(initAxis, minNum)
} else if (type == 4) {
initAxis = 2000; minNum = -2000;
drawAxis(initAxis, minNum);
}
drawAxisText(0, type);
// onWindowResize()
planes[0].constant = (360 / (initAxis)) * initAxis + 1
}
renderer.domElement.addEventListener('webglcontextlost', handleContextLost, false);
function handleContextLost(event) {
event.preventDefault();
init();
}
renderer2D.domElement.addEventListener('webglcontextlost', handleContextLost2, false);
function handleContextLost2(event) {
event.preventDefault();
init2D();
}
function handleVisibilityChange() {
if (document.hidden) {
// 页面被最小化或切换应用程序,暂停渲染并清除 InstancedMesh 相关资源
instancedMesh.dispose();
} else {
// 页面重新显示,重新创建 WebGL 上下文并重新设置 InstancedMesh
init();
}
}
//prps初始化
function init() {
let box = $('#box3D1');
let width = box.width();
let height = box.height();
renderer = new THREE.WebGLRenderer({ logarithmicDepthBuffer: true, antialias: true, preserveDrawingBuffer: true, });//preserveDrawingBuffer保存three.js canvas画布上的信息
renderer.localClippingEnabled = true
let constant = (360 / (initAxis)) * initAxis + 1
planes = [
new THREE.Plane(new THREE.Vector3(0, -1, 0), constant), //y轴正值截取
]
renderer.clippingPlanes = planes
renderer.setSize(width, height);//设置渲染区域尺寸
renderer.setClearColor(0xffffff, 1); //设置背景颜色
//renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
renderer.setPixelRatio(window.devicePixelRatio)//设备像素比,优化渲染效果
box?.append(renderer.domElement); //body元素中插入canvas对象
scene = new THREE.Scene();
scene.add(meshList, axis, pointsList, axisTextGroup);
/* var point = new THREE.PointLight(0xffffff);
point.position.set(600, 600, 600); //点光源位置
scene.add(point); //点光源添加到场景中
var ambient = new THREE.AmbientLight(0x444444);
scene.add(ambient); */
drawAxis(initAxis, minNum, true)
var k = width / height; //窗口宽高比
var s = 420; //三维场景显示范围控制系数,系数越大,显示的范围越大
//创建相机对象
camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1600);
camera.position.set(500, 200, 500); //设置相机位置
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
controls = new THREE.OrbitControls(camera, renderer.domElement);
// 设置左右方向的最大、最小角度限制为 90 度和 0 度
controls.minAzimuthAngle = 0;
controls.maxAzimuthAngle = Math.PI / 2;
// 设置上下方向的最大、最小角度限制为 90 度和 0 度
controls.minPolarAngle = 0;
controls.maxPolarAngle = Math.PI / 2;
//设置放大缩小上下限
controls.minZoom = 0.5;
controls.maxZoom = 2;
//controls.enablePan = false;
//设置控制器中心点
controls.target.set(25, 0, 180);
renderer.render(scene, camera);
//controls.addEventListener('change', render);
}
//prpd初始化
function init2D() {
let box = $('#box2D1');
let width = box.width();
let height = box.height();
renderer2D = new THREE.WebGLRenderer({ logarithmicDepthBuffer: true, antialias: true, preserveDrawingBuffer: true, });//preserveDrawingBuffer保存three.js canvas画布上的信息\
renderer2D.localClippingEnabled = true
let constant = (360 / (initAxis)) * initAxis + 1
planes = [
new THREE.Plane(new THREE.Vector3(0, -1, 0), constant), //y轴正值截取
]
renderer2D.clippingPlanes = planes
renderer2D.setSize(width, height);//设置渲染区域尺寸
renderer2D.setClearColor(0xffffff, 1); //设置背景颜色
renderer2D.setPixelRatio(window.devicePixelRatio)//设备像素比,优化渲染效果
box?.append(renderer2D.domElement); //body元素中插入canvas对象
scene2D = new THREE.Scene();
const List = pointsList.clone()
scene2D.add(axis2D, List, axisTextGroup2D, pointsList)
drawAxis2D(initAxis, minNum)
// 辅助坐标系 参数250表示坐标系大小可以根据场景大小去设置
// let axisHelper = new THREE.AxesHelper(250);
// scene2D.add(axisHelper);
var k = width / height; //窗口宽高比
var s = 380; //三维场景显示范围控制系数,系数越大,显示的范围越大
//创建相机对象
camera2D = new THREE.OrthographicCamera(-s * k - 200, s * k - 200, s + 160, -s + 160, 1, 1200);
camera2D.position.set(600, 0, 0); //设置相机位置
camera2D.lookAt(scene2D.position); //设置相机方向(指向的场景对象)
controls2D = new THREE.OrbitControls(camera2D, renderer2D.domElement);
controls2D.enablePan = false//右键位移禁用
controls2D.enableZoom = false//放大缩小禁用
//设置放大缩小上下限
controls2D.minZoom = 0.5;
controls2D.maxZoom = 2;
controls2D.enableRotate = false
renderer2D.render(scene2D, camera2D);
controls2D.addEventListener('change', render2D);
}
function onWindowResize() {
if (viewType == 1 || viewType == 2) {//全功能PrpsAndPrpd
let h = $(window).height();
$(".loading-box").css('height', h * 0.65)
$(".loading-box-mini").css('height', h * 0.35)
$('.noisy-slide').css('height', h * 0.4)
$('#realdata').show();
$('.noisy-slide-box').show();
$('#echarts-text').show();
$('#addPointNumDiv').show();
$('#box3D1').show();
$('#box2D1').hide();
$('#box2D6').show();
} else if (viewType == 3) {//实时数据仅展示prpd
let h = $(window).height();
$(".loading-box").css('height', h)
$('#realdata').hide();
$('.noisy-slide-box').hide();
$('#echarts-text').hide();
$('#addPointNumDiv').hide();
$('#box3D1').hide();
$('#box2D1').show();
$('#box2D6').hide();
} else if (viewType == 4) {//历史趋势仅展示prps
let h = $(window).height();
$(".loading-box").css('height', h * 0.9)
$('#realdata').hide();
$('.noisy-slide-box').hide();
$('#echarts-text').hide();
$('#addPointNumDiv').hide();
$('#box3D1').hide();
$('#box2D1').show();
} else if (viewType == 5) {//历史趋势仅展示prpd
let h = $(window).height();
$(".loading-box").css('height', h * 0.9)
$('#realdata').hide();
$('.noisy-slide-box').hide();
$('#echarts-text').hide();
$('#addPointNumDiv').hide();
$('#box3D1').hide();
$('#box2D1').show();
}
if (echarts.getInstanceByDom(box2D6) != null) {
box2D6chart.resize();
}
let box = $('#box3D1');
let width = box.width();
let height = box.height();
//console.log("🚀 height:",width, height)
let k = width / height; //窗口宽高比
let s = 350; //三维场景显示范围控制系数,系数越大,显示的范围越大
camera.left = -s * k - 20;
camera.right = s * k - 20;
camera.top = s + (minNum ? -80 : 60);
camera.bottom = -s + (minNum ? -80 : 60);
camera.aspect = k;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
renderer.setPixelRatio(window.devicePixelRatio)//设备像素比,优化渲染效果
let s2D = 270;
camera2D.left = -s2D * k - 200;
camera2D.right = s2D * k - 200;
camera2D.top = s2D + (minNum ? -30 : 155);
camera2D.bottom = -s2D + (minNum ? -30 : 155);
camera2D.aspect = k;
camera2D.updateProjectionMatrix();
renderer2D.setSize(width, height);
renderer2D.setPixelRatio(window.devicePixelRatio)//设备像素比,优化渲染效果
}
function render() {
// 获取摄像机的视锥体
const frustum = new THREE.Frustum();
const cameraViewProjectionMatrix = new THREE.Matrix4();
camera.updateMatrixWorld(); // 确保摄像机的世界矩阵已更新
cameraViewProjectionMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
frustum.setFromProjectionMatrix(cameraViewProjectionMatrix);
// 遍历场景中的每个对象,并根据视锥体进行剔除
scene.traverse((object) => {
if (object.isMesh) {
object.visible = frustum.intersectsObject(object);
}
});
// 更新帧率显示器
//stats.update();
renderer.render(scene, camera);
requestAnimationFrame(render)
}
function render2D() {
//scene.rotateY(0.001);//每次绕y轴旋转0.01弧度
requestAnimationFrame(render2D)
renderer2D.render(scene2D, camera2D);
}
function initChangeType(monitorType) {
gilSwitchChart(1)
cpdSwitchChart(1)
upDrawAxis(0, 0, monitorType)
if (monitorType == 1) {
//$('.avgValue').fadeOut()
$('#model-tab').fadeOut(() => {
$('#channelFiltering').fadeIn()
$('.pm-slide-box').fadeIn()
$('#associated-noise-box').fadeIn()
// $('#record-btn-box').fadeIn()
$('#toggle-box').fadeIn()
$('.noisy-slide-box').fadeIn()
$('.radiogroup').fadeIn()
$('.cdf-slide-box').fadeIn()
$('.eventList').fadeIn()
$('.refreshtitle').fadeIn()
$('#associated-noise').removeClass('disabled');
$('#adaptive-noise').removeClass('disabled');
$(".noisy-slide").slider({ disabled: false });
$("#channelFiltering").val(0);
$('.monitorType').html('UHF')
})
} else if (monitorType == 2 || monitorType == 3) {
$('#channelFiltering').fadeOut(() => {
$('#model-tab').fadeIn()
if (realTime.atlasType == 1) {
$('#model-tab button:first-child').addClass('active').siblings().removeClass('active')
} else if (realTime.atlasType == 2) {
$('#model-tab button:nth-child(2)').addClass('active').siblings().removeClass('active')
} else {
$('#model-tab button:last-child').addClass('active').siblings().removeClass('active')
$('.cdf-slide-box').fadeOut()
$('.noisy-slide-box').fadeOut()
}
})
$('.pm-slide-box').fadeOut()
$('#associated-noise-box').fadeOut()
// $('#record-btn-box').fadeOut()
// $('#toggle-box').fadeOut()
$('.radiogroup').fadeOut()
// $('.eventList').fadeOut()
$('.refreshtitle').fadeOut()
//$('.avgValue').fadeIn()
$('.avgValue .name').html(i18n.content.realTime.gil.averageValue + "")
$('.monitorType').html('AE')
$('#line-btn-box').hide();
$('#form-line').hide();
} else if (monitorType == 4) {
$('#channelFiltering').fadeOut()
$('.pm-slide-box').fadeOut()
$('#associated-noise-box').fadeOut()
// $('#record-btn-box').fadeOut()
// $('#toggle-box').fadeOut()
$('.noisy-slide-box').fadeOut()
$('.radiogroup').fadeOut()
$('.refreshtitle').fadeOut()
$('#model-tab').fadeOut()
$('.cdf-slide-box').fadeIn()
$('.eventList').fadeIn()
//$('.avgValue').fadeIn()
$('.avgValue .name').html(i18n.content.realTime.gis.averageValue + "")
$('.monitorType').html('HFCT')
}
}
// 图表绘制
function drawEcharts1(list1, list2) {
// monitorType GIS 1 GIL故障定位 2 GIL局放 3 电缆 4
// atlasType 1 PRPS/PRPD 2 飞行模式/脉冲数据 3 连续模式
if (list1?.length) {
drawPRPS(list1)
}
if (list2?.length) {
drawPRPD(list2)
}
}
export { scene, axis, meshList, pointsList, axis2D, scene2D, i18n, }