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('  '); $('#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, }