// @ts-nocheck class WsLabel { constructor() { this.name = 'label'; this.id = 'id'; this.bg_color = '#fff'; this.fore_color = '#ddd'; this.location = 0; this.width = 1000; } } //this.area_x //绘图区域 起始X //this.area_y //绘图区域 起始Y //this.area_width //绘图区域 宽度 //this.area_height //绘图区域 高度 //this.spectrogram_y //频谱区域 起始Y //this.spectrogram_x //频谱区域 起始X //this.spectrogram_width //频谱区域 宽度 //this.spectrogram_height //频谱区域 高度 //this.waterfall_y //瀑布区域 起始Y //this.waterfall_x //瀑布区域 起始X //this.waterfall_width //瀑布区域 宽度 //this.waterfall_height //瀑布区域 高度 //新增数据 waterfallwidget.prototype.addData = function (d, time) { if (this.willFitDbRange == true) { this.willFitDbRange = false; var max = Math.max(...d) + 10; var min = Math.min(...d) - 10; if (-200 > min) { min = -200; } if (0 < max) { max = 0; } this.changeDBRange(min, max, true); return; } this.drawWaterFall(d); this.drawAllSpectrogram(d); //时间 if (time) { if (this.timeIndex > this.waterfall_height) { this.timeQueue.splice(this.timeQueue.length - this.time_span, this.time_span); this.timeIndex = this.timeIndex - this.time_span; } this.timeQueue.unshift(time); this.drawCoorTime(); this.timeIndex++; } }; waterfallwidget.prototype.addCompareCurLineData = function (d) { this.CompareCurLineBuff = d; }; waterfallwidget.prototype.lastPeakMarker = false; waterfallwidget.prototype.drawAllSpectrogram = function (bins) { var size = this.visual_MapLen; //bins.length; var top = this.spectrogram_y; var left = this.spectrogram_x; var width = this.spectrogram_width; var height = this.spectrogram_height; this.drawSpectrogrambg(); this.drawAfterglow(bins, this.waveAfterglow_color); this._drawSpectrogram(bins, this.wave_color, peakMarkIndex); //峰值标注 var peakMarkIndex = 0; if (this.showPeakMarker) { if (bins.length < 100) { console.log('waterfall len cannot < 100'); } var band = this.max_db - this.min_db; var max = -10000; peakMarkIndex = 50; for (var i = 5; i < bins.length - 5; i++) { if (bins[i] > max) { max = bins[i]; peakMarkIndex = i; } } //var max = Math.max(...bins); //peakMarkIndex = bins.indexOf(max); var markv = max; var marky = top + height - ((markv - this.min_db) / band) * height; var markx = left + width * (peakMarkIndex / bins.length); var markfre = this.getFreqByPoint(markx); var textfre = `${(markfre / 1000000).toFixed(6)} MHz`; var context = this.layer_info2.getContext(); context.clearRect(0, 0, this.layer_info2.getWidth(), this.layer_info2.getHeight()); context.beginPath(); context.moveTo(markx - 3, marky - 15); context.lineTo(markx + 3, marky - 15); context.lineTo(markx, marky - 5); context.fillStyle = '#ff0000'; context.fill(); context.strokeStyle = this.fore_color; context.font = '13px serif'; context.strokeText(textfre, markx + 5, marky - 15); context.strokeText(markv.toFixed(2) + ' dBm', markx + 5, marky - 1); } //最大保持 if (this.showSpectrogramMax) { if (this.SpectrogramMaxBuff.length == 0 || this.SpectrogramMaxBuff.length != bins.length) { this.SpectrogramMaxBuff = new Array(bins.length); for (var i = 0; i < bins.length; i++) { this.SpectrogramMaxBuff[i] = bins[i]; } } else { for (var i = 0; i < bins.length; i++) { this.SpectrogramMaxBuff[i] = Math.max(this.SpectrogramMaxBuff[i], bins[i]); } } this._drawSpectrogram(this.SpectrogramMaxBuff, this.wave_color_max); } //最小保持 if (this.showSpectrogramMin) { if (this.SpectrogramMinBuff.length == 0 || this.SpectrogramMinBuff.length != bins.length) { this.SpectrogramMinBuff = new Array(bins.length); for (var i = 0; i < bins.length; i++) { this.SpectrogramMinBuff[i] = bins[i]; } } else { for (var i = 0; i < bins.length; i++) { this.SpectrogramMinBuff[i] = Math.min(this.SpectrogramMinBuff[i], bins[i]); } } this._drawSpectrogram(this.SpectrogramMinBuff, this.wave_color_min); } //平均保持 if (this.showSpectrogramAvg) { if (this.SpectrogramBuff.length >= this.SpectrogramBuffCount) { this.SpectrogramBuff.shift(); } this.SpectrogramBuff.push(bins); var count = this.SpectrogramBuff.length; var len = this.SpectrogramBuff[0].length; var ls = new Array(len); var sum = 0; for (var i = 0; i < len; i++) { sum = 0; for (var j = 0; j < count; j++) { sum += this.SpectrogramBuff[j][i]; } ls[i] = Math.round(sum / count); } this._drawSpectrogram(ls, this.wave_color_avg); } //Make功能 if (this.showPeakMarker) { this.setShowMake(bins, this.layer_info3, 0); this.setShowMake(bins, this.layer_info4, 1); this.showInfoMakeDb(); //this.setShowMake(bins, this.layer_info5, 2); //this.setShowMake(bins, this.layer_info6, 3); //this.setShowMake(bins, this.layer_info7, 4); } //显示对比频谱 if (this.showCompareCurLine) { if (this.CompareCurLineBuff != null) { let _first = this.CompareCurLineBuff; this._drawSpectrogram(_first, this.wave_color_compare); } } this.layer_wf.getContext().drawImage(this.ctx_spec.canvas, 0, 0, size, height, left, top, width, height); }; waterfallwidget.prototype.drawSpectrogrambg = function () { var size = this.visual_MapLen; var height = this.spectrogram_height; this.ctx_spec.fillStyle = this.bg_color; this.ctx_spec.fillRect(0, 0, size, height); }; //余晖图 waterfallwidget.prototype.drawAfterglow = function (bins, color) { if (!this.afterglowBuff) { this.afterglowBuff = []; } if (this.delayAfterglow == 0) { this.afterglowBuff = []; return; } var delayTime = Math.min(this.delayAfterglow, 5000); var removeCount = 0; for (var i = 0; i < this.afterglowBuff.length; i++) { if (Date.now() - this.afterglowBuff[i].time.getTime() > delayTime) { removeCount++; } } for (var i = 0; i < removeCount; i++) { this.afterglowBuff.shift(); } if (this.afterglowBuff.length > 0) { var alpaStep = 1 / (this.afterglowBuff.length + 1); for (var i = 0; i < this.afterglowBuff.length; i++) { this._drawSpectrogram( this.afterglowBuff[i].data, this.hexToRGBA(this.afterglowBuff[i].color, alpaStep * (i + 1)), ); } } this.afterglowBuff.push({ time: new Date(), data: bins, color: color, }); }; waterfallwidget.prototype._drawSpectrogram = function (bins, color) { this.ctx_spec.strokeStyle = color; var size = this.visual_MapLen; //var top = this.spectrogram_y; //var left = this.spectrogram_x; //var width = this.spectrogram_width; var height = this.spectrogram_height; if (height == 0) return; if (bins.length < 2) { return; } this.ctx_spec.beginPath(); this.ctx_spec.moveTo(0, height - ((bins[0] - this.min_db) / band) * height); var band = this.max_db - this.min_db; var per = size / bins.length; for (var j = 0; j < bins.length - 1; j++) { var val = bins[j]; var i = Math.floor(per * j); if (val < this.min_db) val = this.min_db; if (val > this.max_db) val = this.max_db; var y = 0; y = height - ((val - this.min_db) / band) * height; this.ctx_spec.lineTo(i, y); } this.ctx_spec.stroke(); }; /** * 十六进制颜色值转为带透明度的颜色 * @param _color 十六进制颜色 * @param _opacity 透明度 * @returns {string} rgba */ waterfallwidget.prototype.hexToRGBA = function (_color, _opacity) { var sColor = _color.toLowerCase(); //十六进制颜色值的正则表达式 var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; // 如果是16进制颜色 if (sColor && reg.test(sColor)) { if (sColor.length === 4) { var sColorNew = '#'; for (var i = 1; i < 4; i += 1) { sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); } sColor = sColorNew; } //处理六位的颜色值 var sColorChange = []; for (var i = 1; i < 7; i += 2) { sColorChange.push(parseInt('0x' + sColor.slice(i, i + 2))); } return 'rgba(' + sColorChange.join(',') + ',' + _opacity + ')'; } return sColor; }; waterfallwidget.prototype.drawWaterFall = function (bins) { var size = this.visual_MapLen; // bins.length; var row = this.waterfall_height; var width = this.waterfall_width; if (row == 0) return; if (this.ctx_wf.canvas.width != size || this.ctx_wf.canvas.height != row) { this.ctx_wf.canvas.width = size; this.ctx_wf.canvas.height = row; } // Shift waterfall 1 row down this.ctx_wf.drawImage(this.ctx_wf.canvas, 0, 0, size, row - 1, 0, 1, size, row - 1); // Draw new line on waterfall canvas var imgData = this.rowToImageData(this.ctx_wf, bins); this.ctx_wf.putImageData(imgData, 0, 0); // Copy scaled FFT canvas to screen this.layer_wf .getContext() .drawImage(this.ctx_wf.canvas, 0, 0, size, row, this.waterfall_x, this.waterfall_y, width, row); }; waterfallwidget.prototype.squeeze = function (value) { if (value < this.min_db) { value = this.min_db; } else if (value > this.max_db) { value = this.max_db; } value = value + Math.abs(this.min_db); //value= (value - this.min_db) / (this.max_db - this.min_db) * 200; //value = value * 200 / (this.max_db - this.min_db); value = Math.round(value); return value; }; waterfallwidget.prototype.rowToImageData = function (c, bins) { var colors = this.color_map.getMapColors(); var size = this.visual_MapLen; var imgData = c.createImageData(size, 1); var per = bins.length / size; if (per > 1) { for (var p = 0; p < size; p++) { var binStart = Math.floor(p * per); var binEnd = Math.min(Math.floor(p * per + per), bins.length - 1); var vals = []; for (var q = binStart; q < binEnd; q++) { vals.push(bins[q]); } var cindex = this.squeeze(Math.max(...vals)); if (cindex > Math.abs(this.min_db) || 0) { console.log(cindex + '-' + colors.length); return imgData; } var color = colors[cindex]; var i = p * 4; if (color) { imgData.data[i + 0] = color[0]; imgData.data[i + 1] = color[1]; imgData.data[i + 2] = color[2]; imgData.data[i + 3] = 255; } } } else { per = size / bins.length; for (var j = 0; j < bins.length; j++) { var i = Math.floor(j * per) * 4; var cindex = this.squeeze(bins[j]); if (cindex > Math.abs(this.min_db) || 0) { console.log(cindex + '-' + colors.length); return imgData; } var color = colors[cindex]; if (color) { for (var m = 0; m < Math.ceil(per); m++) { imgData.data[i + m * 4 + 0] = color[0]; imgData.data[i + m * 4 + 1] = color[1]; imgData.data[i + m * 4 + 2] = color[2]; imgData.data[i + m * 4 + 3] = 255; } } } } //var per = size / bins.length; //for (var j = 0; j < bins.length; j++) { // var i = Math.floor(j * per)*4; // var cindex = this.squeeze(bins[j]); // if (cindex > Math.abs(this.min_db) || 0) console.log(cindex + "-" + colors.length); // var color = colors[cindex]; // if (color) { // imgData.data[i + 0] = color[0]; // imgData.data[i + 1] = color[1]; // imgData.data[i + 2] = color[2]; // imgData.data[i + 3] = 255; // } //} return imgData; }; waterfallwidget.prototype.fitDbRange = function () { this.willFitDbRange = true; }; waterfallwidget.prototype.changeDBRange = function (min_db, max_db, force = false) { min_db = Math.max(-200, min_db); max_db = Math.min(0, max_db); if (this.min_db != min_db || this.max_db != max_db || force == true) { this.min_db = min_db; this.max_db = max_db; this.drawCoor(); this.color_map.setDbRange(max_db - min_db); //this.drawMap(); //this.drawRuler(); this.setColorMapGravity(Math.round(this.min_db + (this.max_db - this.min_db) * 0.31415926), this.showRuler); this.drawCarryLine(); this.fireGravityEvent(); } }; waterfallwidget.prototype.drawCoor = function () { var layer = this.layer_coor; layer.destroyChildren(); layer.add( new Konva.Rect({ x: 0, y: 0, width: layer.getWidth(), height: layer.getHeight(), fill: this.bg_color, listening: false, }), ); layer.add( new Konva.Rect({ x: this.margin_left, y: this.margin_top, width: this.getwf_CtWidth(), height: this.getwf_CtHeight(), stroke: this.fore_color, //fill:this.bg_color, strokeWidth: 1, listening: false, }), ); layer.add( new Konva.Line({ points: [this.waterfall_x, this.waterfall_y - 1, this.waterfall_x + this.waterfall_width, this.waterfall_y - 1], stroke: this.fore_color, strokeWidth: 1, listening: false, }), ); var spanSpec = this.spectrogram_height / this.db_counter; var span = this.waterfall_height / this.db_counter; var spanValue = Math.round((this.max_db - this.min_db) / this.db_counter); for (var i = 0; i < this.db_counter; i += 1) { if (i < this.db_counter) { if (this.spectrogram_height > 0) { layer.add( new Konva.Text({ x: 0, y: this.spectrogram_y + spanSpec * i - 5, text: this.max_db - i * spanValue ? this.max_db - i * spanValue : '0', fontSize: 11, fontFamily: 'Calibri', fill: this.fore_color, width: this.margin_left - 30, align: 'right', listening: false, }), ); } if (this.waterfall_height > 0) { layer.add( new Konva.Line({ points: [ this.margin_left - 28, this.spectrogram_y + spanSpec * i, this.margin_left - 23, this.spectrogram_y + spanSpec * i, ], stroke: this.fore_color, strokeWidth: 1, listening: false, }), ); } } ///////////////////////////////// layer.add( new Konva.Text({ x: 0, y: this.waterfall_y + span * i - 5, text: this.max_db - i * spanValue ? this.max_db - i * spanValue : '0', fontSize: 11, fontFamily: 'Calibri', fill: this.fore_color, width: this.margin_left - 30, align: 'right', listening: false, }), ); layer.add( new Konva.Line({ points: [ this.margin_left - 28, this.waterfall_y + span * i, this.margin_left - 23, this.waterfall_y + span * i, ], stroke: this.fore_color, strokeWidth: 1, listening: false, }), ); } layer.draw(); }; waterfallwidget.prototype.drawCoorTime = function () { if (this.timeQueue.length == 0) return; var layer = this.layer_coor; var arrtext = layer.find('.time-text'); var arrline = layer.find('.time-line'); for (var i = 0; i < arrtext.length; i++) { arrtext[i].destroy(); } for (var i = 0; i < arrline.length; i++) { arrline[i].destroy(); } var timeY = this.waterfall_y; var timeValue = ''; var cIndex = this.timeIndex; var timeX = this.stage.getWidth() - this.margin_right + 1; while (cIndex > 0) { timeY = cIndex + this.waterfall_y; timeValue = this.timeQueue[cIndex]; cIndex -= this.time_span; layer.add( new Konva.Text({ x: timeX + 8, y: timeY - 5, text: timeValue, fontSize: 11, fontFamily: 'Calibri', fill: this.fore_color, width: 100, align: 'left', listening: false, name: 'time-text', }), ); layer.add( new Konva.Line({ points: [timeX, timeY, timeX + 5, timeY], stroke: this.fore_color, strokeWidth: 1, listening: false, name: 'time-line', }), ); } //var lines = 1000 / this.time_out; //var zoom = Math.floor(20 / lines); //while (timeY < this.getwf_CtHeight() + this.margin_top) { // layer.add( // new Konva.Text({ // x: timeX + 8, // y: timeY - 5, // text: (timeValue) + ' s', // fontSize: 11, // fontFamily: 'Calibri', // fill: this.fore_color, // width: 100, // align: 'left', // listening: false, // }) // ); // layer.add( // new Konva.Line({ // points: [timeX, timeY, timeX + 5, timeY], // stroke: this.fore_color, // strokeWidth: 1, // listening: false, // }) // ); // timeValue += zoom; // timeY += zoom * lines; //} layer.draw(); }; waterfallwidget.prototype.drawCoorFreq = function () { var layer = this.layer_coorFreq; layer.destroyChildren(); layer.removeChildren(); var count = this.zoomOption; var freSpan = this.getwf_CtWidth() / count; var freValueSpan = Math.round((this.freq_end - this.freq_start) / count); var fre_y = this.margin_top; if (this.coorFreqType == 1) { fre_y = this.waterfall_y; } var msFreSpan = freSpan / 10; var msFreValueSpan = freValueSpan / 10; for (var i = 0; i < count + 1; i++) { var v = this.freq_start + i * freValueSpan; var dim = 'Hz'; if (v >= 1000000000) { v = v / 1000000000; dim = 'G'; } else if (v >= 1000000) { v = v / 1000000; dim = 'M'; } else if (v >= 1000) { v = v / 1000; dim = 'K'; } if (count <= 8) { v = v.toFixed(3); } else { v = v.toFixed(3); } layer.add( new Konva.Text({ x: this.margin_left + i * freSpan - 12, y: fre_y - 12, text: v + ' ' + dim, fontSize: 11, fontFamily: 'Calibri', fill: this.fore_color, width: 100, align: 'left', listening: false, }), ); layer.add( new Konva.Line({ points: [this.margin_left + i * freSpan, fre_y - 22, this.margin_left + i * freSpan, fre_y - 13], stroke: this.fore_color, strokeWidth: 1, listening: false, }), ); if (this.show_msFreq && i != count) { for (var j = 0; j < 9; j++) { var msX = Math.round(this.margin_left + i * freSpan + (j + 1) * msFreSpan); layer.add( new Konva.Line({ points: [msX, fre_y - 20, msX, fre_y - 15], stroke: this.fore_color, strokeWidth: 1, listening: false, }), ); if (count == 1) { var msv = this.freq_start + i * freValueSpan + (j + 1) * msFreValueSpan; var dimms = 'Hz'; if (msv >= 1000000000) { msv = msv / 1000000000; dimms = 'G'; } else if (msv >= 1000000) { msv = msv / 1000000; dimms = 'M'; } else if (msv >= 1000) { msv = msv / 1000; dimms = 'K'; } msv = msv.toFixed(3); layer.add( new Konva.Text({ x: msX - 12, y: fre_y - 12, text: msv + ' ' + dimms, fontSize: 11, fontFamily: 'Calibri', fill: this.fore_color, width: 100, align: 'left', listening: false, }), ); } } } } layer.batchDraw(); }; waterfallwidget.prototype.setZoomCenter = function (freq, force = true) { if (this.freq_start < freq && this.freq_end > freq && force == false) { return; } var range = this.freq_end - this.freq_start; var nstart = freq - range / 2; var nend = freq + range / 2; if (nstart < this.min_freq || nend > this.max_freq) { return; } this.setFreqZoom(nstart, nend); }; waterfallwidget.prototype.drawCoorFreqWheel = function () { var layer = this.layer_coorFreqWeel; //双击频点居中 layer.on('dblclick', (e) => { var x = e.evt.offsetX; var freq = this.getFreqByPoint(x); this.setZoomCenter(freq); }); if (this.allowRunMode == 1) { this.drawCoorFreqWheel_RT(); } else if (this.allowRunMode == 0) { this.drawCoorFreqWheel_Slide(); } //左侧增益动作 var wheelRect = new Konva.Rect({ x: 0, y: 0, width: this.margin_left - 20, height: this.stage.getHeight(), fill: 'transparent', // name: 'wheelReactDbCt', }); wheelRect.on('wheel', (evt) => { var min_db = this.min_db; var max_db = this.max_db; if (evt.evt.wheelDelta > 0) { if (this.max_db - this.min_db > 30) { min_db += 5; max_db -= 5; } else { return; } } else { min_db -= 5; max_db += 5; } this.changeDBRange(min_db, max_db); evt.evt.preventDefault(); evt.evt.stopPropagation(); return false; }); wheelRect.on('mousedown', (e) => { if (e.evt.button === 2) { return; } else if (e.evt.button === 0) { //buttonLR = 'left'; } var span = this.waterfall_height / this.db_counter; var distanceY = e.evt.offsetY; var oDbMin = this.min_db; var oDbMax = this.max_db; if (distanceY < this.waterfall_y) { span = this.spectrogram_height / this.db_counter; } this.stage.on('mousemove', (e) => { var yy = e.evt.offsetY - distanceY; var change = Math.floor(yy / span) * 10; var desMin = oDbMin + change; var desMax = oDbMax + change; var min_db = Math.max(-200, desMin); var max_db = Math.min(0, desMax); this.changeDBRange(min_db, max_db); }); this.stage.on('mouseup', (e) => { this.stage.off('mousemove'); this.stage.off('mouseup'); }); }); //增益区域鼠标移入鼠标图标变化 wheelRect.on('mouseover', (e) => { this.stage.container().style.cursor = 'pointer'; }); wheelRect.on('mouseout', (e) => { this.stage.container().style.cursor = 'default'; }); //增益动作结束 layer.add(wheelRect); layer.batchDraw(); }; //鼠标操作层 实时模式 waterfallwidget.prototype.drawCoorFreqWheel_RT = function () { var _self = this; var layer = this.layer_coorFreqWeel; layer.destroyChildren(); layer.removeChildren(); var wheelRect = new Konva.Rect({ x: this.area_x, y: this.area_y - 20, width: this.area_width, height: this.area_height + 20, fill: 'transparent', name: 'wheelReact', }); var buttonLR; wheelRect.on('mousedown', function (e) { var distanceX = e.evt.offsetX; var distanceY = e.evt.offsetY; _self.hideContextMenu(); if (e.evt.button === 2) { buttonLR = 'right'; _self.adj_show = true; // } else if (e.evt.button === 0) { buttonLR = 'left'; } var o_start = _self.freq_start; _self.stage.on('mousemove', async function (e) { //只有鼠标左键移动 if (buttonLR === 'left') { _self.drawCoverRect(distanceX, distanceY, e.evt.offsetX, e.evt.offsetY); } else if (buttonLR === 'right') { if (e.evt.offsetX - distanceX > 0) { if (this.isUHF) { _self.adj_end = _self.getFreqByPoint(e.evt.offsetX); _self.drawAdjLocation(); } } } }); _self.stage.on('mouseup', async function (e) { _self.clearCoverLayer(); if (buttonLR === 'left') { if (_self.disableZoom != true) { var dx = e.evt.offsetX; var dy = e.evt.offsetY; if (Math.abs(dx - distanceX) < 10) { } else if (dx > distanceX) { var freqStart = _self.getFreqByPoint(distanceX); var freqend = _self.getFreqByPoint(e.evt.offsetX); if (freqend - freqStart < 1000) { var selectBw = 1000 / 2; var selectCenter = Math.round(freqStart + (freqend - freqStart) / 2); freqStart = Math.max(selectCenter - selectBw, _self.min_freq); freqend = Math.min(selectCenter + selectBw, _self.max_freq); } _self.setFreqZoomUp(freqStart, freqend); } else { _self.setFreqZoomDown(); } } if (e.evt.altKey) { //频率信息标注 var x = e.evt.offsetX; var y = e.evt.offsetY; var freq = _self.getFreqByPoint(x); if (_self.wfFreqPointLable) { _self.AddFreqPointLable(freq); return; } } } else if (buttonLR === 'right') { var dx = e.evt.offsetX; var dy = e.evt.offsetY; //右键点击 if (Math.abs(dx - distanceX) < 10) { _self.setAdjCenter(_self.getFreqByPoint(distanceX), true); } } buttonLR = null; _self.stage.off('mousemove'); _self.stage.off('mouseup'); }); }); wheelRect.on('mouseenter', (enter) => { wheelRect.on('mousemove', async function (move) { //显示悬浮信息 var freq = _self.getFreqByPoint(move.evt.offsetX); var db = _self.getDbByPoint(move.evt.offsetY); var text = `${(freq / 1000000).toFixed(6)} MHz`; if (db) { text = text + `\r\n${db} dBm`; } _self.showInfo( { x: move.evt.offsetX, y: move.evt.offsetY, text: text, }, true, ); }); wheelRect.on('mouseleave', async function (leave) { wheelRect.off('mouseleave'); wheelRect.off('mousemove'); _self.hideInfo(); }); }); this.drawWheelZoom(wheelRect); layer.add(wheelRect); layer.batchDraw(); }; //鼠标操作层 侦察模式 waterfallwidget.prototype.drawCoorFreqWheel_Slide = function () { var _self = this; var layer = this.layer_coorFreqWeel; layer.destroyChildren(); layer.removeChildren(); var wheelRect = new Konva.Rect({ x: this.area_x, y: this.area_y - 20, width: this.area_width, height: this.area_height + 20, fill: 'transparent', name: 'wheelReact', }); var buttonLR; //放大缩小菜单等 wheelRect.on('mousedown', function (e) { var distanceX = e.evt.offsetX; var distanceY = e.evt.offsetY; _self.hideContextMenu(); if (e.evt.button === 2) { buttonLR = 'right'; _self.adj_show = true; _self.adj_start = _self.getFreqByPoint(distanceX); } else if (e.evt.button === 0) { buttonLR = 'left'; } else if (e.evt.button === 1) { buttonLR = 'center'; } //var o_start = _self.freq_start; //多级频点标注功能 if (e.evt.buttons == 1) { if (e.evt.ctrlKey) { if (_self.MakeShow.length >= 2) { _self.MakeShow.splice(0, 1); } var freq = _self.getFreqByPoint(e.evt.offsetX); _self.MakeShow[_self.MakeShow.length] = freq; for (var i = 0; i < _self.MakeShow.length; i++) { for (var j = i + 1; j < _self.MakeShow.length; j++) { if (_self.MakeShow[i] == _self.MakeShow[j]) { _self.MakeShow.splice(j, 1); j--; } } } } else if (e.evt.altKey) { //频率信息标注 var x = e.evt.offsetX; var y = e.evt.offsetY; var freq = _self.getFreqByPoint(x); if (_self.wfFreqPointLable) { _self.AddFreqPointLable(freq); return; } } } if (e.evt.buttons == 2) { if (e.evt.ctrlKey) { _self.MakeShow.splice(0, _self.MakeShow.length); } } //多级频点标注功能 _self.stage.on('mousemove', async function (e) { //只有鼠标左键移动 if (buttonLR === 'left') { _self.drawCoverRect(distanceX, distanceY, e.evt.offsetX, e.evt.offsetY); } else if (buttonLR === 'right') { if (_self.adj_show) { _self.setCtrFc(_self.adj_start + (_self.adj_end - _self.adj_start) / 2); _self.adj_end = _self.getFreqByPoint(e.evt.offsetX); _self.drawAdjLocation(); } } }); _self.stage.on('mouseup', async function (e) { _self.clearCoverLayer(); if (buttonLR === 'left') { var dx = e.evt.offsetX; var dy = e.evt.offsetY; if (Math.abs(dx - distanceX) < 10) { } else if (dx > distanceX) { var freqStart = _self.getFreqByPoint(distanceX); var freqend = _self.getFreqByPoint(e.evt.offsetX); if (freqend - freqStart < 2000) { var selectBw = 2000 / 2; var selectCenter = Math.round(freqStart + (freqend - freqStart) / 2); freqStart = Math.max(selectCenter - selectBw, _self.min_freq); freqend = Math.min(selectCenter + selectBw, _self.max_freq); } _self.setFreqZoomUp(freqStart, freqend); } else { _self.setFreqZoomDown(); } } else if (buttonLR === 'right') { var dx = e.evt.offsetX; var dy = e.evt.offsetY; //右键点击 if (Math.abs(dx - distanceX) < 10) { if (_self.adj_show) { _self.adj_show = false; _self.drawAdjLocation(); } } else { if (_self.adj_end - _self.adj_start > 1) { _self.setCtrBw(_self.adj_end - _self.adj_start); } _self.setParamsToHistory({ fc: _self.currentFc, bw: _self.currentBw, }); if (_self.isUHF) { _self.onAutomaticAdjustment(); _self.gather_show = true; _self.drawGather(); } } } else if (buttonLR === 'center') { var dx = e.evt.offsetX; var dy = e.evt.offsetY; if (_self.CarryLineMode == 1) { var currectX = _self.getFreqByPoint(dx); var currentY = _self.getDbByPoint(dy); if (currectX && currentY) { var arr = []; var bk = false; if (dx < 65) { //点的特别左边直接取消 bk = true; } else { for (var i = 0; i < _self.CarryLineList.length; i += 2) { var xx = _self.CarryLineList[i]; var yy = _self.CarryLineList[i + 1]; if (xx < currectX) { arr.push(xx); arr.push(yy); } else { bk = true; break; } } } if (!bk) { arr.push(currectX); arr.push(currentY); } _self.setCarryLineList(arr); } } } buttonLR = null; _self.stage.off('mousemove'); _self.stage.off('mouseup'); }); }); //显示信息 wheelRect.on('mouseenter', (enter) => { wheelRect.on('mousemove', async function (move) { if (!_self.adj_show) { var freq = _self.getFreqByPoint(move.evt.offsetX); var db = _self.getDbByPoint(move.evt.offsetY); var text = `${(freq / 1000000).toFixed(6)} MHz`; if (db) { text = text + `\r\n${db} dBm`; } _self.showInfo( { x: move.evt.offsetX, y: move.evt.offsetY, text: text, }, true, ); } // 修改为悬浮在款选带宽内才显示提示 //else if (_self.alwaysShowAdj) { // _self.showAdjInfo(_self.adj_x, _self.adj_y); //} }); wheelRect.on('mouseleave', async function (leave) { wheelRect.off('mouseleave'); wheelRect.off('mousemove'); _self.hideInfo(); }); }); this.drawWheelZoom(wheelRect); layer.add(wheelRect); layer.batchDraw(); }; waterfallwidget.prototype.adj_x = 65; waterfallwidget.prototype.adj_y = 25; waterfallwidget.prototype.alwaysShowAdj = true; //添加滚轮放大动作 waterfallwidget.prototype.drawWheelZoom = function (wheelRect) { var _self = this; wheelRect.on('wheel', (evt) => { if (_self.disableZoom) { return; } var scale = Math.exp((-evt.evt.wheelDelta * 1.0) / 200); var freq = this.getFreqByPoint(evt.evt.offsetX); //var range = this.freq_end - this.freq_start; //var nrange = range * scale; var start = freq - (freq - this.freq_start) * scale; var end = freq + (this.freq_end - freq) * scale; this.throttleSetFreqZoomUp(start, end, false); evt.evt.preventDefault(); evt.evt.stopPropagation(); return false; }); }; //底部滚动条 waterfallwidget.prototype.drawBottomScroll = function () { var bottom_scroll_height = 15; var layer = this.layer_botscroll; layer.destroyChildren(); layer.removeChildren(); this._debounceSetStart = _.debounce(() => { var x = thunk.x() - this.area_x; var freq = this.min_freq + (this.max_freq - this.min_freq) * (x / this.area_width); var freqend = freq + (this.freq_end - this.freq_start); this.setFreqZoom(freq, freqend); }, 100); layer.add( new Konva.Rect({ x: this.area_x, y: this.area_y + this.area_height - bottom_scroll_height, width: this.area_width, height: bottom_scroll_height, fill: '#fff', opacity: 0.9, visible: false, name: 'bottom-scroll-bg', }), ); var thunk = new Konva.Rect({ x: this.area_x, y: this.area_y + this.area_height - bottom_scroll_height, width: 1, height: bottom_scroll_height, fill: '#524E63', opacity: 0.7, visible: false, name: 'bottom-scroll-thunk', //draggable: true, //dragBoundFunc: (pos) => { // var xx = pos.x; // if (pos.x < this.area_x) { // xx = this.area_x; // } // else if (pos.x + thunk.width() > this.area_x + this.area_width) { // xx = this.area_x + this.area_width - thunk.width(); // } // return { // x: xx, // y: this.area_y + this.area_height - bottom_scroll_height, // } //} }); thunk.on('mouseenter', (enter) => { thunk.opacity(0.9); document.body.style.cursor = 'pointer'; layer.draw(); }); thunk.on('mouseout', (enter) => { thunk.opacity(0.6); document.body.style.cursor = 'default'; layer.draw(); }); thunk.on('mousedown', (e) => { var ox = e.evt.offsetX; var ol = thunk.x(); this.stage.on('contentMousemove', (ee) => { var xx = ol + (ee.evt.offsetX - ox); if (xx < this.area_x) { xx = this.area_x; } else if (xx + thunk.width() > this.area_x + this.area_width) { xx = this.area_x + this.area_width - thunk.width(); } thunk.x(xx); layer.draw(); this._debounceSetStart(); }); this.stage.on('mouseup', (ee) => { this.stage.off('contentMousemove'); this.stage.off('mouseup'); }); }); //thunk.on('dragend', () => { // var x = thunk.x() - this.area_x; // var freq = this.min_freq+(this.max_freq - this.min_freq) * (x / this.area_width); // var freqend = freq + (this.freq_end - this.freq_start); // this.setFreqZoom(freq , freqend); //}); layer.add(thunk); layer.batchDraw(); }; waterfallwidget.prototype.drawBottomScrollLocal = function () { var range = this.max_freq - this.min_freq; var x = ((this.freq_start - this.min_freq) / range) * this.area_width; var x2 = ((this.freq_end - this.min_freq) / range) * this.area_width; var width = x2 - x; if (width < 10) { width = 10; } var thunk = this.layer_botscroll.find('.bottom-scroll-thunk'); thunk.width(width); thunk.x(this.area_x + x); if (Math.abs(this.freq_start - this.min_freq) < 0.1 && Math.abs(this.freq_end - this.max_freq) < 0.1) { thunk.hide(); this.layer_botscroll.find('.bottom-scroll-bg').hide(); } else { thunk.show(); this.layer_botscroll.find('.bottom-scroll-bg').show(); } this.layer_botscroll.draw(); }; waterfallwidget.prototype.clearCoverLayer = function () { var layer = this.layer_cover; layer.destroyChildren(); layer.removeChildren(); layer.batchDraw(); }; waterfallwidget.prototype.drawCoverRect = function (sx, sy, dx, dy) { var layer = this.layer_cover; layer.destroyChildren(); layer.removeChildren(); var x = sx > dx ? dx : sx; var y = sy > dy ? dy : sy; var x1 = sx > dx ? sx : dx; var y1 = sy > dy ? sy : dy; var minx = this.area_x; var maxx = this.area_x + this.area_width; var miny = this.area_y; var maxy = this.area_y + this.area_height; x = Math.min(x, maxx); x = Math.max(x, minx); x1 = Math.min(x1, maxx); x1 = Math.max(x1, minx); y = Math.min(y, maxy); y = Math.max(y, miny); y1 = Math.min(y1, maxy); y1 = Math.max(y1, miny); layer.add( new Konva.Rect({ x: x, y: y, width: x1 - x, height: y1 - y, fill: '#fff', opacity: 0.3, name: 'cover-react', }), ); layer.batchDraw(); }; //瞬时带宽 waterfallwidget.prototype.setInstant = function (start, end) { this.instant_start = start; this.instant_end = end; this.drawInstant(); }; waterfallwidget.prototype.clearInstant = function () { this.instant_start = 0; this.instant_end = 0; this.drawInstant(); }; waterfallwidget.prototype.openInstant = function () { this.instant_show = true; this.drawInstant(); }; waterfallwidget.prototype.closeInstant = function () { this.instant_show = false; this.drawInstant(); }; waterfallwidget.prototype.drawInstant = function () { var layer = this.layer_instant; layer.destroyChildren(); layer.removeChildren(); layer.draw(); if (!this.instant_show) return; if (!this.instant_start && !this.instant_end) return; var start = this.getPointByFreq(this.instant_start); var end = this.getPointByFreq(this.instant_end); if (end < this.area_x) return; if (start > this.area_x + this.area_width) return; var width = end - start; if (start < this.area_x) start = this.area_x; if (width > this.area_x + this.area_width - start) width = this.area_x + this.area_width - start; //console.log(start + "-" + width); layer.add( new Konva.Rect({ x: start, y: this.area_y, width: width, height: this.area_height, fill: this.instant_color, opacity: 0.05, name: 'cover-react', }), ); layer.batchDraw(); }; waterfallwidget.prototype.setChanel = function (start, end) { //console.log("setchanel " + start + "-" + end); this.chanel_start = start; this.chanel_end = end; this.drawChanel(); }; waterfallwidget.prototype.clearChanel = function () { this.chanel_start = 0; this.chanel_end = 0; this.drawChanel(); }; waterfallwidget.prototype.openChanel = function () { this.chanel_show = true; this.drawChanel(); }; waterfallwidget.prototype.closeChanel = function () { this.chanel_show = false; this.drawChanel(); }; waterfallwidget.prototype.drawChanel = function () { var layer = this.layer_chanel; layer.destroyChildren(); layer.removeChildren(); layer.draw(); //if (this.showFreqLable) { // var context = this.layer_info6.getContext(); // context.clearRect(0, 0, this.layer_info6.getWidth(), this.layer_info6.getHeight()); //} if (!this.chanel_show) return; if (!this.chanel_start && !this.chanel_end) return; var start = this.getPointByFreq(this.chanel_start); var end = this.getPointByFreq(this.chanel_end); if (end < this.area_x) return; if (start > this.area_x + this.area_width) return; var width = end - start; if (start < this.area_x) start = this.area_x; if (width > this.area_x + this.area_width - start) width = this.area_x + this.area_width - start; if (width < 2) { width = 2; } layer.add( new Konva.Rect({ x: start, y: this.area_y, width: width, height: this.area_height, fill: this.chanel_color, opacity: 0.3, name: 'cover-react', }), ); layer.batchDraw(); //显示频率标签 //if (this.showFreqLable) { // let markfre = (start + end) / 2; // var freq = this.getFreqByPoint(markfre); // var textfre = `${(freq / 1000000).toFixed(6)} MHz`; // context.strokeStyle = this.fore_color; // context.font = "13px serif"; // context.strokeText(textfre, end + 5, this.area_y + 30); //} }; //标尺 waterfallwidget.prototype.drawMap = function () { if (this.waterfall_height == 0) return; var _self = this; var layer = this.layer_map; layer.destroyChildren(); layer.removeChildren(); var rect = new Konva.Rect({ x: this.margin_left - 15, y: this.waterfall_y, width: 10, height: this.waterfall_height, fill: 'transparent', //stroke: this.fore_color, }); rect.on('click', function () { if (_self.showRuler) { _self.showRuler = false; _self.layer_mapRuler.findOne('.map_ruler').hide(); } else { _self.showRuler = true; _self.layer_mapRuler.findOne('.map_ruler').show(); } _self.layer_mapRuler.batchDraw(); _self.fireGravityEvent(); }); layer.add(rect); layer.draw(); this.drawMapColor(); }; waterfallwidget.prototype.drawMapColor = function () { if (this.waterfall_height == 0) return; var cx = this.layer_map.getContext(); cx.clearRect(0, 0, this.layer_map.width, this.layer_map.height); var nwidth = this.getDrawWHByPixelRatio(10); var nheight = this.getDrawWHByPixelRatio(this.waterfall_height); var imgData = cx.createImageData(nwidth, nheight); this.color_map.count = nheight; //this.waterfall_height; var colors = this.color_map.getColors(); var colors_len = colors.length; if (colors_len != 0) { for (var i = 0; i < imgData.data.length; i += 4) { var cindex = colors_len - parseInt(i / 4 / nwidth) - 1; var color = colors[cindex]; imgData.data[i + 0] = color[0]; imgData.data[i + 1] = color[1]; imgData.data[i + 2] = color[2]; imgData.data[i + 3] = 255; } } var nx = this.getDrawWHByPixelRatio(this.margin_left - 15); var ny = this.getDrawWHByPixelRatio(this.waterfall_y); cx.putImageData(imgData, nx, ny); }; waterfallwidget.prototype.drawRuler = function () { if (this.waterfall_height == 0) return; var _self = this; var layer = this.layer_mapRuler; layer.destroyChildren(); layer.removeChildren(); var group = new Konva.Group({ x: this.margin_left - 15, y: this.waterfall_y + (1 - _self.getGravityPerByLocation()) * _self.waterfall_height, rotation: 0, draggable: true, dragBoundFunc: function (pos) { var newY = pos.y; if (newY < _self.waterfall_y) { newY = _self.waterfall_y; } else if (newY > _self.waterfall_y + _self.waterfall_height) { newY = _self.waterfall_y + _self.waterfall_height; } return { x: this.getAbsolutePosition().x, y: newY, }; }, shadowOffsetX: 10, shadowOffsetY: 15, shadowBlur: 40, opacity: 0.8, visible: _self.showRuler, name: 'map_ruler', }); var lastY = -1; group.on('dragmove', function (e) { var ny = e.target.y() - _self.waterfall_y; var nvalue = 1 - ny / _self.waterfall_height; var ndb = _self.min_db + (_self.max_db - _self.min_db) * nvalue; _self.gravity_location = ndb; if (ny != lastY) { lastY = ny; _self.color_map.gravity_value = nvalue; if (_self.color_map.gravity) { _self.drawMapColor(); } } _self.fireGravityEvent(); }); group.add( new Konva.Rect({ x: 60, y: -20, width: 80, height: 20, fill: this.fore_color, stroke: this.fore_color, strokeWidth: 1, cornerRadius: 3, }), ); group.add( new Konva.Text({ x: 70, y: -15, text: 'Gravity', fontSize: 12, fontFamily: 'Calibri', fill: this.bg_color, }), ); var checked = new Konva.Rect({ x: 120, y: -17, width: 15, height: 15, fill: this.bg_color, }); group.add( new Konva.Line({ points: [0, 0, 60, 0], stroke: this.fore_color, strokeWidth: 1, lineCap: 'round', lineJoin: 'round', }), ); checked.on('click', function () { if (_self.color_map.gravity) { layer.findOne('.check_ico').hide(); _self.color_map.gravity = false; } else { layer.findOne('.check_ico').show(); _self.color_map.gravity = true; } _self.drawMapColor(); layer.batchDraw(); _self.fireGravityEvent(); }); group.add(checked); //2021-09-10 梁海祥 (瀑布色尺坐标位置地布遮挡问题,坐标整体上移) var checkico = new Konva.Line({ points: [123, -10, 128, -5, 133, -15], stroke: this.fore_color, strokeWidth: 2, lineCap: 'round', lineJoin: 'round', name: 'check_ico', visible: _self.color_map.gravity, }); group.add(checkico); layer.add(group); layer.batchDraw(); }; waterfallwidget.prototype.setColorMapGravity = function (val, enable) { if (this.gravity_location !== val || this.color_map.gravity !== enable) { this.gravity_location = val; this.showRuler = enable; this.color_map.gravity_value = this.getGravityPerByLocation(); this.color_map.gravity = enable; this.drawMap(); this.drawRuler(); } }; waterfallwidget.prototype.fireGravityEvent = function () { this.fire('gravity-ruler-change', { gravityData: { enable: this.showRuler, checked: this.color_map.gravity, val: this.gravity_location, min_db: this.min_db, max_db: this.max_db, }, }); }; //根据重力尺值得到百分比位置 waterfallwidget.prototype.getGravityPerByLocation = function () { if (this.gravity_location == 0) { return 0; } if (this.gravity_location <= this.min_db) { return 1; } else if (this.gravity_location >= this.max_db) { return 0; } return (this.min_db - this.gravity_location) / (this.min_db - this.max_db); }; //2021.05.07 西部需求拖动更改频谱窗口大小,李伟添加; waterfallwidget.prototype.split_draw = function () { var _self = this; var layer = this.layer_split; if (!layer) { return; } layer.destroyChildren(); layer.removeChildren(); var leftLine = new Konva.Rect({ x: 0, y: 100, width: this.area_x, height: 10, fill: this.adj_color, name: 'SplitLine', }); if (this.allowRunMode == 0) { leftLine.on('mouseenter', (e) => { if (this.adj_disabled == true) return; _self.stage.container().style.cursor = 'e-resize'; }); leftLine.on('mouseleave', (e) => { if (this.adj_disabled == true) return; _self.stage.container().style.cursor = 'default'; }); leftLine.on('mousedown', (e) => { if (this.adj_disabled == true) return; var oevent = e.evt; var distanceX = oevent.clientX - leftLine.x(); _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); _self.stage.on('contentMousemove', function (e) { var freq = _self.getFreqByPoint(e.evt.offsetX); if (freq < _self.adj_end) { _self.adj_start = freq; _self.drawAdjLocation(); } _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); }); _self.stage.on('mouseup', function (e) { _self.stage.off('contentMousemove'); _self.stage.off('mouseup'); _self.hideInfo(); _self.fire('adj-manu-change', { start: _self.adj_start, end: _self.adj_end }); }); }); } /* var rightLine = new Konva.Rect({ x: 0, y: this.area_y, width: this.adj_lineWidth, height: this.area_height, fill: this.adj_color, name: 'rightLine', }); if (this.allowRunMode == 0) { rightLine.on('mouseenter', e => { if (this.adj_disabled == true) return; _self.stage.container().style.cursor = 'e-resize'; }); rightLine.on('mouseleave', e => { if (this.adj_disabled == true) return; _self.stage.container().style.cursor = 'default'; }); rightLine.on('mousedown', e => { if (this.adj_disabled == true) return; var oevent = e.evt; var distanceX = oevent.clientX - rightLine.x(); _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); _self.stage.on('contentMousemove', function (e) { var freq = _self.getFreqByPoint(e.evt.offsetX); if (freq > _self.adj_start) { _self.adj_end = freq; _self.drawAdjLocation(); } _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); }); _self.stage.on('mouseup', function (e) { _self.stage.off('contentMousemove'); _self.stage.off('mouseup'); _self.hideInfo(); _self.fire("adj-manu-change", { start: _self.adj_start, end: _self.adj_end }); }); }); } var rect = new Konva.Rect({ x: 0, y: this.area_y, width: 0, height: this.area_height, fill: this.adj_color, opacity: 0.1, name: 'rect' }); if (this.allowRunMode == 0) { rect.on("mousedown", function (e) { if (e.evt.button === 2) { //显示右键菜单 _self.showContextMenu(e.evt.clientX, e.evt.clientY); } else { _self.hideContextMenu(); } }) } //layer.add(rect); //layer.add(leftLine); //layer.add(rightLine); */ var group = new Konva.Group({ x: 0, y: 0, }); //group.add(rect); group.add(leftLine); //group.add(rightLine); //实时模式可拖动 if (this.allowRunMode == 1) { group.on('mouseenter', (e) => { if (this.adj_disabled == true) return; _self.stage.container().style.cursor = 'e-resize'; var oevent = e.evt; var distanceX = oevent.clientX - rightLine.x(); _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); _self.stage.on('contentMousemove', function (e) { _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); }); group.on('mouseleave', function (e) { _self.stage.container().style.cursor = 'default'; _self.stage.off('contentMousemove'); group.off('mouseleave'); _self.hideInfo(); }); }); group.on('mousedown', (e) => { if (this.adj_disabled == true) return; if (e.evt.button !== 0) return; var distanceX = e.evt.clientX; //_self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); var freq = _self.getAdjCenter(); var ncenter = 0; _self.stage.on('mousemove', function (e) { var xx = e.evt.clientX - distanceX; var change = _self.getFreqBySpanPoint(xx); ncenter = freq + change; _self.setAdjCenter(ncenter, false); }); _self.stage.on('mouseup', function (e) { _self.setAdjCenter(ncenter, true); _self.stage.off('mousemove'); _self.stage.off('mouseup'); _self.hideInfo(); console.log('off'); }); }); } else if (this.allowRunMode == 0) { //非实时模式可穿透放大缩小 var buttonLR = null; /* rect.on('mousedown', function (e) { var distanceX = e.evt.offsetX; var distanceY = e.evt.offsetY; if (e.evt.button === 0) { buttonLR = 'left'; } _self.stage.on('mousemove', async function (e) { //只有鼠标左键移动 if (buttonLR === 'left') { _self.drawCoverRect(distanceX, distanceY, e.evt.offsetX, e.evt.offsetY); } }); _self.stage.on('mouseup', async function (e) { _self.clearCoverLayer(); if (buttonLR === "left") { var dx = e.evt.offsetX; var dy = e.evt.offsetY; if (Math.abs(dx - distanceX) < 10) { } else if (dx > distanceX) { var freqStart = _self.getFreqByPoint(distanceX); var freqend = _self.getFreqByPoint(e.evt.offsetX); if (freqend - freqStart < 10000) { var selectBw = 10000 / 2 var selectCenter = Math.round(freqStart + (freqend - freqStart) / 2); freqStart = Math.max(selectCenter - selectBw, _self.min_freq); freqend = Math.min(selectCenter + selectBw, _self.max_freq); } _self.setFreqZoomUp(freqStart, freqend); } else { _self.setFreqZoomDown(); } } buttonLR = null; _self.stage.off('mousemove'); _self.stage.off('mouseup'); }); }); */ } layer.add(group); _self.split_drawLocation(); }; waterfallwidget.prototype.split_show = function () { this.split_show = true; this.split_drawLocation(); }; waterfallwidget.prototype.split_hidden = function () { this.split_show = false; this.split_drawLocation(); }; waterfallwidget.prototype.split_enable = function () { this.split_disabled = false; }; waterfallwidget.prototype.split_disable = function () { this.split_disabled = true; }; waterfallwidget.prototype.split_drawLocation = function () { if (!this.layer_split) { return; } var layer = this.layer_split; var leftLine = layer.findOne('.leftLine'); var rightLine = layer.findOne('.rightLine'); var rect = layer.findOne('.rect'); if (!leftLine || !rightLine || !rect) { return; } leftLine.visible(this.split_show); rightLine.visible(this.split_show); rect.visible(this.split_show); if (this.split_show) { var left = this.getPointByFreq(this.adj_start); var right = this.getPointByFreq(this.adj_end); var lineWidth = this.adj_lineWidth; leftLine.x(left - lineWidth); rightLine.x(right); rect.x(left); rect.width(right - left + lineWidth); } layer.batchDraw(); }; //2021.05.07 西部需求拖动更改频谱窗口大小,李伟添加 end; waterfallwidget.prototype.showAdjInfo = function (x, y) { this.showInfo({ x: x, y: y, text: `中心:${((this.adj_start + (this.adj_end - this.adj_start) / 2) / 1000000).toFixed(3)}MHz\r\n起始:${(this.adj_start / 1000000).toFixed(3)} MHz\r\n结束:${(this.adj_end / 1000000).toFixed(3)} MHz\r\n带宽:${((this.adj_end - this.adj_start) / 1000).toFixed(3)} kHz`, }); }; waterfallwidget.prototype.toHzStr = function (v, d = -1, dw = 'Hz') { if (!v) return ''; if (v >= 1000000000) { if (d != -1) { v = (v / 1000000000).toFixed(d) + ' G' + dw; } else { v = (v / 1000000000).toFixed(9) + ' G' + dw; } } else if (v >= 1000000) { if (d != -1) { v = (v / 1000000).toFixed(d) + ' M' + dw; } else { v = (v / 1000000).toFixed(6) + ' M' + dw; } } else if (v >= 1000) { if (d != -1) { v = (v / 1000).toFixed(d) + ' K' + dw; } else { v = (v / 1000).toFixed(3) + ' K' + dw; } } else { v = v.toFixed(0) + dw; } return v; }; waterfallwidget.prototype.setCtrBw = function (bw, reConn = true, fftmodel = 0) { bw = +bw; var panelBwText = $('#text_bw'); if (reConn && bw == this.currentBw) { panelBwText.val(this.toHzStr(bw)); return; } if (!Number.isFinite(bw)) { bootbox.erro('带宽格式不正确'); panelBwText.val(this.toHzStr(this.currentBw)); return; } if (bw < 1) { bootbox.erro('带宽不能小于1kHz'); panelBwText.val(this.toHzStr(this.currentBw)); return; } //这里判断currentFc>0是因为在初始化时带宽参数优先初始化 if (this.currentFc > 0 && this.isAdjCenterInRange(this.currentFc, bw) == false) { if (fftmodel == 0) { //全景频谱才弹出提示,控守频谱时不管 bootbox.erro('带宽超出扫频范围'); } panelBwText.val(this.toHzStr(this.currentBw)); return; } this.currentBw = bw; panelBwText.val(bw); }; waterfallwidget.prototype.setCtrFc = function (fc, reConn = true) { var panelFcText = $('#panel-text-freq'); if (reConn && fc == this.currentFc) { panelFcText.val(this.toHzStr(fc)); return; } if (isNaN(fc)) { panelFcText.val(this.toHzStr(this.currentFc)); return; } if (!Number.isFinite(fc)) { bootbox.erro('中心频率格式不正确'); panelFcText.val(this.toHzStr(this.currentFc)); return; } this.currentFc = fc; panelFcText.val(this.toHzStr(fc)); }; waterfallwidget.prototype.setParamsToHistory = function (dto) { dto = Object.assign( { fc: 0, bw: 0, fs: 0, pdem: 0, sys: 0, }, dto, ); localStorage.setItem('fc', dto.fc); localStorage.setItem('bw', dto.bw); }; waterfallwidget.prototype.drawAdj = function () { var _self = this; var layer = this.layer_adj; layer.destroyChildren(); layer.removeChildren(); var yStart = this.margin_top - 45; var leftLine = new Konva.Rect({ x: 0, y: this.area_y, width: this.adj_lineWidth, height: this.area_height, fill: this.adj_color, name: 'leftLine', }); if (this.allowRunMode == 0) { leftLine.on('mouseenter', (e) => { if (this.adj_disabled == true) return; _self.stage.container().style.cursor = 'e-resize'; }); leftLine.on('mouseleave', (e) => { if (this.adj_disabled == true) return; _self.stage.container().style.cursor = 'default'; }); leftLine.on('mousedown', (e) => { if (this.adj_disabled == true) return; var oevent = e.evt; var distanceX = oevent.clientX - leftLine.x(); _self.alwaysShowAdj || _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); _self.stage.on('contentMousemove', function (e) { var freq = _self.getFreqByPoint(e.evt.offsetX); if (freq < _self.adj_end) { _self.adj_start = freq; _self.drawAdjLocation(); } _self.alwaysShowAdj || _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); }); _self.stage.on('mouseup', function (e) { _self.stage.off('contentMousemove'); _self.stage.off('mouseup'); _self.alwaysShowAdj || _self.hideInfo(); _self.fire('adj-manu-change', { start: _self.adj_start, end: _self.adj_end }); }); }); } var rightLine = new Konva.Rect({ x: 0, y: this.area_y, width: this.adj_lineWidth, height: this.area_height, fill: this.adj_color, name: 'rightLine', }); var centerLine = new Konva.Rect({ x: 0, y: this.area_y, width: this.adj_lineWidth, height: this.area_height, fill: this.adjcenter_color, name: 'centerLine', }); if (this.allowRunMode == 0) { rightLine.on('mouseenter', (e) => { if (this.adj_disabled == true) return; _self.stage.container().style.cursor = 'e-resize'; }); rightLine.on('mouseleave', (e) => { if (this.adj_disabled == true) return; _self.stage.container().style.cursor = 'default'; }); rightLine.on('mousedown', (e) => { if (this.adj_disabled == true) return; var oevent = e.evt; var distanceX = oevent.clientX - rightLine.x(); _self.alwaysShowAdj || _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); _self.stage.on('contentMousemove', function (e) { var freq = _self.getFreqByPoint(e.evt.offsetX); if (freq > _self.adj_start) { _self.adj_end = freq; _self.drawAdjLocation(); } _self.alwaysShowAdj || _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); }); _self.stage.on('mouseup', function (e) { _self.stage.off('contentMousemove'); _self.stage.off('mouseup'); _self.alwaysShowAdj || _self.hideInfo(); _self.fire('adj-manu-change', { start: _self.adj_start, end: _self.adj_end }); }); }); } var rect = new Konva.Rect({ x: 0, y: this.area_y, width: 0, height: this.area_height, fill: this.adj_color, opacity: 0.1, name: 'rect', }); if (this.allowRunMode == 0) { rect .on('mouseenter', (e) => { if (this.adj_disabled == true) return; _self.alwaysShowAdj && _self.showAdjInfo(_self.adj_x, _self.adj_y); }) .on('mouseleave', (e) => { _self.hideInfo(); }); rect.on('mousedown', function (e) { if (e.evt.button === 2) { //显示右键菜单 _self.showContextMenu(e.evt.clientX, e.evt.clientY); } else { _self.hideContextMenu(); } }); } //layer.add(rect); //layer.add(leftLine); //layer.add(rightLine); var group = new Konva.Group({ x: 0, y: 0, }); group.add(rect); group.add(leftLine); group.add(rightLine); if (this.allowRunMode == 1) { group.add(centerLine); } //实时模式可拖动 if (this.allowRunMode == 1) { group.on('mouseenter', (e) => { if (this.adj_disabled == true) return; _self.stage.container().style.cursor = 'e-resize'; var oevent = e.evt; var distanceX = oevent.clientX - rightLine.x(); _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); _self.stage.on('contentMousemove', function (e) { _self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); }); group.on('mouseleave', function (e) { _self.stage.container().style.cursor = 'default'; _self.stage.off('contentMousemove'); group.off('mouseleave'); _self.hideInfo(); }); }); group.on('mousedown', (e) => { if (this.adj_disabled == true) return; if (e.evt.button !== 0) return; var distanceX = e.evt.clientX; //_self.showAdjInfo(e.evt.offsetX, e.evt.offsetY); var freq = _self.getAdjCenter(); var ncenter = 0; _self.stage.on('mousemove', function (e) { var xx = e.evt.clientX - distanceX; var change = _self.getFreqBySpanPoint(xx); ncenter = freq + change; _self.setAdjCenter(ncenter, false); }); _self.stage.on('mouseup', function (e) { _self.setAdjCenter(ncenter, true); _self.stage.off('mousemove'); _self.stage.off('mouseup'); _self.hideInfo(); }); }); } else if (this.allowRunMode == 0) { //非实时模式可穿透放大缩小 var buttonLR = null; rect.on('mousedown', function (e) { var distanceX = e.evt.offsetX; var distanceY = e.evt.offsetY; if (e.evt.button === 0) { buttonLR = 'left'; } _self.stage.on('mousemove', async function (e) { //只有鼠标左键移动 if (buttonLR === 'left') { _self.drawCoverRect(distanceX, distanceY, e.evt.offsetX, e.evt.offsetY); } }); _self.stage.on('mouseup', async function (e) { _self.clearCoverLayer(); if (buttonLR === 'left') { var dx = e.evt.offsetX; var dy = e.evt.offsetY; if (Math.abs(dx - distanceX) < 10) { } else if (dx > distanceX) { var freqStart = _self.getFreqByPoint(distanceX); var freqend = _self.getFreqByPoint(e.evt.offsetX); if (freqend - freqStart < 10000) { var selectBw = 10000 / 2; var selectCenter = Math.round(freqStart + (freqend - freqStart) / 2); freqStart = Math.max(selectCenter - selectBw, _self.min_freq); freqend = Math.min(selectCenter + selectBw, _self.max_freq); } _self.setFreqZoomUp(freqStart, freqend); } else { _self.setFreqZoomDown(); } } buttonLR = null; _self.stage.off('mousemove'); _self.stage.off('mouseup'); }); }); } layer.add(group); _self.drawAdjLocation(); }; waterfallwidget.prototype.showAdj = function () { this.adj_show = true; this.drawAdjLocation(); }; waterfallwidget.prototype.hiddenAdj = function () { this.adj_show = false; this.gather_show = false; this.drawGatherLocation(); this.drawAdjLocation(); }; waterfallwidget.prototype.enableAdj = function () { this.adj_disabled = false; }; waterfallwidget.prototype.disableAdj = function () { this.adj_disabled = true; }; waterfallwidget.prototype.drawAdjLocation = function () { var layer = this.layer_adj; var leftLine = layer.findOne('.leftLine'); var rightLine = layer.findOne('.rightLine'); var centerLine = layer.findOne('.centerLine'); var rect = layer.findOne('.rect'); if (!leftLine || !rightLine || !rect) { return; } if (this.adj_start > this.adj_end) { this.adj_end = this.adj_start; } leftLine.visible(this.adj_show); rightLine.visible(this.adj_show); rect.visible(this.adj_show); if (this.adj_show) { var left = this.getPointByFreq(this.adj_start); var right = this.getPointByFreq(this.adj_end); var lineWidth = this.adj_lineWidth; leftLine.x(left - lineWidth); rightLine.x(right); if (centerLine) { if (this.adj_lineType == 0 || !this.adj_lineType) { //cener centerLine.x((right + left) / 2 - lineWidth / 2); } else if (this.adj_lineType == 1) { //LSB centerLine.x(right); } else if (this.adj_lineType == 2) { //USB centerLine.x(left - lineWidth); } } this.allowRunMode == 0 && this.alwaysShowAdj && this.showAdjInfo(this.adj_x, this.adj_y); rect.x(left); rect.width(right - left + lineWidth); } layer.batchDraw(); }; waterfallwidget.prototype.getAdjCenter = function () { var freq = this.adj_start + (this.adj_end - this.adj_start) / 2; if (this.adj_lineType == 1) { freq = this.adj_end; } else if (this.adj_lineType == 2) { freq = this.adj_start; } return freq; }; waterfallwidget.prototype.getCDBAdjCenter = function () { var freq = this.min_freq + (this.max_freq - this.min_freq) / 2; if (this.adj_lineType == 1) { freq = this.max_freq; } else if (this.adj_lineType == 2) { freq = this.min_freq; } return freq; }; waterfallwidget.prototype.getAdjBw = function () { return this.adj_end - this.adj_start; }; waterfallwidget.prototype.setAdjCenter = function (freq, fireEvent = false) { var adjbw = this.getAdjBw(); var adjcenter = freq; if (fireEvent) { //修正adjcenter if (this.adj_step > 0) { adjcenter = Math.round(adjcenter / this.adj_step) * this.adj_step; } } if (this.validataAdj(adjcenter, adjbw, this.adj_lineType) == false) { return { result: false, message: '频点超出范围' }; } this.setAdjLeftRight(adjcenter, adjbw, this.adj_lineType); if (fireEvent) { this.fire('pointer-change', { fc: adjcenter }); } this.drawAdjLocation(); return { result: true }; }; waterfallwidget.prototype.isAdjCenterInRange = function (freq, bw) { var _self = this; var adjbw = Math.min(bw, _self.adj_maxbw); var adjcenter = freq; var left = adjcenter - adjbw / 2; var right = adjcenter + adjbw / 2; console.log( 'freq=' + freq + '_____bw=' + bw + '___adjbw=' + adjbw + '____self.adj_maxbw=' + _self.adj_maxbw + '__left=' + left + '__right=' + right + '__this.min_freq=' + this.min_freq + '___this.max_freq=' + this.max_freq, ); if (left < this.min_freq || left > this.max_freq || right < this.min_freq || right > this.max_freq) { return false; } return true; }; waterfallwidget.prototype.setAdjBand = function (bw) { var _self = this; var point = this.getAdjCenter(); var adjbw = Math.min(bw, _self.adj_maxbw); if (this.validataAdj(point, adjbw, this.adj_lineType) == false) { return { result: false, message: '频点超出范围' }; } this.setAdjLeftRight(point, adjbw, this.adj_lineType); this.drawAdjLocation(); return { result: true }; }; //0正常 1 LSB 2 USB waterfallwidget.prototype.setAdjPointType = function (adjlinetype = 0) { var bw = this.adj_end - this.adj_start; var point = this.adj_start + bw / 2; if (this.validataAdj(point, bw, adjlinetype) == false) { return { result: false, message: '频点超出范围' }; } this.adj_lineType = adjlinetype; this.drawAdjLocation(); return { result: true }; }; waterfallwidget.prototype.validataAdj = function (pointer, bw, type) { var arr = this.getAdjLeftRight(pointer, bw, type); var left = arr[0]; var right = arr[1]; if (left < this.min_freq || left > this.max_freq || right < this.min_freq || right > this.max_freq) { return false; } else { return true; } }; waterfallwidget.prototype.getAdjLeftRight = function (pointer, bw, type) { var left = pointer - bw / 2; var right = pointer + bw / 2; if (type == 2) { left = pointer; right = pointer + bw; } else if (type == 1) { right = pointer; left = pointer - bw; } return [left, right]; }; waterfallwidget.prototype.setAdjLeftRight = function (pointer, bw, type) { var arr = this.getAdjLeftRight(pointer, bw, type); var left = arr[0]; var right = arr[1]; this.adj_start = left; this.adj_end = right; }; waterfallwidget.prototype.drawGather = function () { var _self = this; var layer = this.layer_gather; layer.destroyChildren(); layer.removeChildren(); _self.gather_fc = this.adj_start + (this.adj_end - this.adj_start) / 2; var leftLine = new Konva.Rect({ x: 0, y: this.area_y, width: this.adj_lineWidth, height: this.area_height, fill: '#F37570', name: 'leftLine', }); var rightLine = new Konva.Rect({ x: 0, y: this.area_y, width: this.adj_lineWidth, height: this.area_height, fill: '#F37570', name: 'rightLine', }); var rect = new Konva.Rect({ x: 0, y: this.area_y, width: 0, height: this.area_height, fill: '#F37570', opacity: 0.1, name: 'rect', }); var group = new Konva.Group({ x: 0, y: 0, }); group.add(rect); group.add(leftLine); group.add(rightLine); layer.add(group); }; waterfallwidget.prototype.drawGatherLocation = function () { var layer = this.layer_gather; var _self = this; var leftLine = layer.findOne('.leftLine'); var rightLine = layer.findOne('.rightLine'); var rect = layer.findOne('.rect'); if (!leftLine || !rightLine) { return; } leftLine.visible(this.gather_show); rightLine.visible(this.gather_show); rect.visible(this.gather_show); if (this.gather_show) { var left = this.getPointByFreq(this.gather_fc + _self.gather_bw / 2); var right = this.getPointByFreq(this.gather_fc - _self.gather_bw / 2); var lineWidth = this.adj_lineWidth; leftLine.x(left - lineWidth); rightLine.x(right); rect.x(left); rect.width(right - left + lineWidth); } layer.batchDraw(); }; waterfallwidget.prototype.setGatherBwFc = function (bw, fc) { var _self = this; _self.gather_show = true; _self.gather_bw = bw; _self.gather_fc = fc; _self.drawGatherLocation(); }; waterfallwidget.prototype.hiddenGather = function () { this.gather_show = false; _self.drawGatherLocation(); }; /*像素单位转css单位,该函数返回当前浏览器缩放比例所影响的 x y width height 的绘图位置 仅适用putImageData getImageData等函数*/ waterfallwidget.prototype.getDrawWHByPixelRatio = function (xory) { if (xory == 0) return 0; if (!xory) return xory; var ret = Math.ceil(window.devicePixelRatio * xory); //console.log(`xory=${xory} ratio=${window.devicePixelRatio} ret=${ret}`); return ret; }; waterfallwidget.prototype.getwf_CtWidth = function () { return this.stage.getWidth() - this.margin_left - this.margin_right; }; waterfallwidget.prototype.getwf_CtHeight = function () { return this.stage.getHeight() - this.margin_top - this.margin_bottom; }; waterfallwidget.prototype.setFreqZoomDown = function () { if (this.zoomQueue.length > 0) { var d = this.zoomQueue.shift(); this.setFreqZoom(d.start, d.end); return true; } else { this.setFreqZoom(this.min_freq, this.max_freq); } }; waterfallwidget.prototype.setFreqZoomUp = function (start, end, record = true) { //if (this.allowRunMode == 1 && this.adj_show && end - start < this.getAdjBw() * 1.5) { // return false; //} if (record) { this.zoomQueue.unshift({ start: this.freq_start, end: this.freq_end }); } this.setFreqZoom(start, end); return true; }; waterfallwidget.prototype.setFreqZoom = function (start, end) { if (!start && !end) { start = this.min_freq; end = this.max_freq; } //if (this.adj_show) { // var adjBand = this.getAdjBw(); // if (end - start < adjBand * 1.5) { // var adjCenter = this.getAdjCenter(); // var nstart = adjCenter - adjBand * 0.8; // var nend = adjCenter + adjBand * 0.8; // start = nstart; // end = nend; // } //} setTimeout(() => { this.SpectrogramBuff = []; this.SpectrogramMinBuff = []; this.SpectrogramMaxBuff = []; this.CompareCurLineBuff = null; this.afterglowBuff = []; }, 200); this.changeStart(start, end, true); //o_zoom >= 0代表不是第一次显示 this.drawInstant(); this.drawAdjLocation(); this.drawGatherLocation(); this.drawChanel(); this.drawCarryLine(); this.drawFreqPointLables(); return true; }; waterfallwidget.prototype.clearSpectrogram = function () { setTimeout(() => { this.SpectrogramBuff = []; this.SpectrogramMinBuff = []; this.SpectrogramMaxBuff = []; this.CompareCurLineBuff = null; this.afterglowBuff = []; }, 200); }; waterfallwidget.prototype.changeStart = async function (start, end, reDrawLabel = true) { var lastStart = this.freq_start; var lastEnd = this.freq_end; var changeUi = true; if (start < this.min_freq) start = this.min_freq; if (end > this.max_freq) end = this.max_freq; this.freq_start = Math.floor(start); this.freq_end = Math.floor(end); if (lastStart !== this.freq_start || lastEnd !== this.freq_end) { if (changeUi) { this.drawCoorFreq(); //this.drawAdjLocation(); this.drawBottomScrollLocal(); this.drawWFOffset(lastStart, lastEnd); //await this.drawWfBuff(); } if (reDrawLabel) { // var ret = await $.post('/setting/getIsShowLabelMasker'); // 注释掉接口请求 this.darwLabel(true); // 使用模拟数据 true this.drawWhiteList(); this.zoomChange(); } return true; } else { return false; } }; //将当前的画布做缩放重新绘制 waterfallwidget.prototype.drawWFOffset = function (lastStart, lastEnd) { var size = this.visual_MapLen; var row = this.waterfall_height; if (row == 0) return; var newStart = this.getPointByFreq(lastStart, true); var newWidth = size; if (lastEnd) { var newEnd = this.getPointByFreq(lastEnd, true); newWidth = Math.round(newEnd - newStart); } if (this.ctx_wf.canvas.width != size || this.ctx_wf.canvas.height != row) { this.ctx_wf.canvas.width = size; this.ctx_wf.canvas.height = row; } // Copy scaled FFT canvas to screen var width = this.waterfall_width; var height = this.waterfall_height; var temp = document.createElement('canvas'); temp.height = row; temp.width = size; var ctx_temp = temp.getContext('2d'); ctx_temp.drawImage(this.ctx_wf.canvas, 0, 0, size, row - 1, 0, 0, size, row - 1); this.ctx_wf.fillRect(0, 0, size, row); this.ctx_wf.drawImage(ctx_temp.canvas, 0, 0, size, row - 1, newStart, 0, newWidth, row - 1); this.layer_wf .getContext() .drawImage(this.ctx_wf.canvas, 0, 0, size, row, this.waterfall_x, this.waterfall_y, width, height); }; waterfallwidget.prototype.drawWfBuff = async function () { //console.log("drawWfBuff"); if (this.fucFFTBuff) { var buff = await this.fucFFTBuff( this.freq_start, this.freq_end, this.waterfall_height, this.unitBuffId, this.fftModelId, ); if (buff) { if (buff.length == 0) return; var colors = this.color_map.getMapColors(); var size = this.visual_MapLen; var imgData = this.ctx_wf.createImageData(size, buff.length); //var spectrumBuff = null; for (var row = 0; row < buff.length; row++) { var bins = buff[row]; var per = bins.length / size; var rowImgIndex = size * row * 4; if (per > 1) { var binVal = 0; for (var p = 0; p < size; p++) { var binStart = Math.floor(p * per); var binEnd = Math.min(Math.floor(p * per + per), bins.length - 1); if (binEnd - binStart <= 1) { binVal = bins[binStart]; } else { var vals = []; for (var q = binStart; q < binEnd; q++) { vals.push(bins[q]); } binVal = Math.max(...vals); } //解决雪花问题 太小最后反而变为0导致 if (binVal >= 200) { for (var qq = binStart; qq < Math.min(binStart + 10, bins.length); qq++) { if (bins[qq] < 200 && bins[qq] > 10) { binVal = bins[qq]; } } } var cindex = this.squeeze(binVal - 200); if (cindex > Math.abs(this.min_db) || 0) { console.log(cindex + '-' + colors.length); return imgData; } var color = colors[cindex]; var i = p * 4; if (color) { imgData.data[rowImgIndex + i + 0] = color[0]; imgData.data[rowImgIndex + i + 1] = color[1]; imgData.data[rowImgIndex + i + 2] = color[2]; imgData.data[rowImgIndex + i + 3] = 255; } } } else { per = size / bins.length; for (var j = 0; j < bins.length; j++) { var i = Math.floor(j * per) * 4; var cindex = this.squeeze(bins[j] - 200); if (cindex > Math.abs(this.min_db) || 0) { console.log(cindex + '-' + colors.length); return imgData; } var color = colors[cindex]; if (color) { for (var m = 0; m < Math.ceil(per); m++) { imgData.data[rowImgIndex + i + m * 4 + 0] = color[0]; imgData.data[rowImgIndex + i + m * 4 + 1] = color[1]; imgData.data[rowImgIndex + i + m * 4 + 2] = color[2]; imgData.data[rowImgIndex + i + m * 4 + 3] = 255; } } } } } this.ctx_wf.putImageData(imgData, 0, 0); // Copy scaled FFT canvas to screen this.layer_wf .getContext() .drawImage( this.ctx_wf.canvas, 0, 0, size, this.waterfall_height, this.waterfall_x, this.waterfall_y, this.waterfall_width, this.waterfall_height, ); //if (spectrumBuff) { // this.drawAllSpectrogram(spectrumBuff); //} } } }; //标签 waterfallwidget.prototype.darwLabel = async function (status) { if (!this.options.label_manager) return; //this.unitBuffId var start = this.freq_start; var end = this.freq_end; var layer = this.layer_label; layer.destroyChildren(); layer.removeChildren(); var _self = this; var rowCount = 2; var rowHeight = 12; var opaNormal = 0.5; var opaSelected = 0.9; var opaLine = 0.5; var row = 0; var rowStart = this.spectrogram_y + 1; var labels = await this.options.label_manager.load(start, end); if (!status) { labels = []; } for (var i = 0; i < labels.length; i++) { var label = labels[i]; var text = new Konva.Text({ x: 2, y: 2, text: label.name, fontSize: 10, fill: '#B3BAC5', //label.fore_color }); var rect = new Konva.Rect({ x: 0, y: 0, fill: label.bg_color, //'#686A78', width: text.width() > 0 ? text.width() + 4 : 0, height: text.height() > 0 ? text.height() + 4 : 0, cornerRadius: 0, //stroke: label.bg_color, strokeWidth: 0, name: 'rect', }); var bw = label.bw; var bwWidth = this.getWidthByBw(bw); var line = new Konva.Rect({ x: 0, y: 0, fill: label.bg_color, //'#B3BAC5', width: bwWidth, height: this.area_height, cornerRadius: 0, name: 'line', opacity: opaLine, }); var group = new Konva.Group({ x: _self.getPointByFreq(label.location - bw / 2), y: rowStart, //+ row * rowHeight, opacity: opaNormal, }); group.label = label; group.add(line); //group.add(rect);//信号标签标题 //group.add(text); layer.add(group); if (this.currentLabel && label.id === this.currentLabel.label.id) { group.opacity = opaNormal; } row++; if (row > rowCount - 1) { row = 0; } } layer.batchDraw(); layer.find('Group').on('click', (evt) => { var current = evt.currentTarget.label; this.label_manager.onclick(current); }); layer.find('Group').on('mouseenter', (evt) => { evt.currentTarget.opacity(opaSelected); layer.draw(); evt.currentTarget.on('mouseleave', (evt2) => { var label = evt2.currentTarget.label; if (!this.currentLabel || this.currentLabel.label.id !== label.id) { evt2.currentTarget.opacity(opaNormal); } evt2.currentTarget.off('mouseleave'); layer.draw(); }); //鼠标滚动放大缩小 evt.currentTarget.on('wheel', (evt) => { if (_self.disableZoom) { return; } var scale = Math.exp((-evt.evt.wheelDelta * 1.0) / 200); var freq = this.getFreqByPoint(evt.evt.offsetX); //var range = this.freq_end - this.freq_start; //var nrange = range * scale; var start = freq - (freq - this.freq_start) * scale; var end = freq + (this.freq_end - freq) * scale; this.throttleSetFreqZoomUp(start, end, false); evt.evt.preventDefault(); evt.evt.stopPropagation(); return false; }); //鼠标左键 var buttonLR; //放大缩小菜单等 evt.currentTarget.on('mousedown', function (e) { var distanceX = e.evt.offsetX; var distanceY = e.evt.offsetY; _self.hideContextMenu(); if (e.evt.button === 2) { buttonLR = 'right'; _self.adj_show = true; _self.adj_start = _self.getFreqByPoint(distanceX); } else if (e.evt.button === 0) { buttonLR = 'left'; } _self.stage.on('mousemove', async function (e) { //只有鼠标右键键移动 if (buttonLR === 'right') { if (_self.adj_show && e.evt.offsetX - distanceX > 0) { _self.adj_end = _self.getFreqByPoint(e.evt.offsetX); _self.drawAdjLocation(); } //_self.stage.off('mouseup'); } }); _self.stage.on('mouseup', async function (e) { _self.clearCoverLayer(); if (buttonLR === 'right') { var dx = e.evt.offsetX; var dy = e.evt.offsetY; if (!_self.adj_show || e.evt.offsetX - distanceX <= 0) { //_self.showLabelsMenu(e);//信号标签右键菜单 } //右键点击 if (Math.abs(dx - distanceX) < 10) { if (_self.adj_show) { _self.adj_show = false; _self.drawAdjLocation(); } } } buttonLR = null; _self.stage.off('mousemove'); _self.stage.off('mouseup'); }); }); }); //layer.find('Group').on('click', evt => { // //_self._setAdjPointer(evt.currentTarget.label.location, true); // //移除以往 // if (this.currentLabel && this.currentLabel.label.id !== evt.currentTarget.label.id) { // //判断是因为有可能因为缩放原因,虽然保留引用但是实际已消失了 // //if (this.currentLabel.findOne('.rect')) { // // this.currentLabel.findOne('.rect').stroke(this.currentLabel.label.bg_color); // // this.currentLabel.findOne('.line').fill(this.currentLabel.label.bg_color); // //} // this.currentLabel.attrs.opacity = 0.4; // } // evt.currentTarget.attrs.opacity = 0.8; // //evt.currentTarget.findOne('.rect').stroke(this.fore_color); // //evt.currentTarget.findOne('.line').fill(this.fore_color); // layer.draw(); // if (!this.currentLabel || this.currentLabel.label.id !== evt.currentTarget.label.id) { // _self.fire('label-change', evt.currentTarget.label); // } // this.currentLabel = evt.currentTarget; //}); }; waterfallwidget.prototype.getDbByPoint = function (point) { if (point > this.spectrogram_y + this.spectrogram_height) { return null; } var perPoint = (this.max_db - this.min_db) / this.spectrogram_height; var db = Number(this.max_db - (point - this.spectrogram_y) * perPoint); return Math.floor(db); }; waterfallwidget.prototype.getPointByDb = function (db) { var perPoint = (this.max_db - this.min_db) / this.spectrogram_height; var h = (this.max_db - db) / perPoint; var point = Number(this.spectrogram_y + h); return Math.floor(point); }; waterfallwidget.prototype.getPointByFreq = function (freq, visual) { if (visual) { var perPoint = (this.freq_end - this.freq_start) / this.visual_MapLen; var point = (freq - this.freq_start) / perPoint; return point; } else { var per = (this.freq_end - this.freq_start) / this.waterfall_width; var pointr = (freq - this.freq_start) / per; return this.margin_left + pointr + 1; } }; waterfallwidget.prototype.getFreqByPoint = function (point) { var perPoint = (this.freq_end - this.freq_start) / this.waterfall_width; var freq = Number(this.freq_start + (point - this.margin_left - 1) * perPoint); freq = Math.min(freq, this.freq_end); freq = Math.max(freq, this.freq_start); return Math.floor(freq); }; waterfallwidget.prototype.getFreqBySpanPoint = function (span) { var perPoint = (this.freq_end - this.freq_start) / this.waterfall_width; return Math.floor(perPoint * span); }; waterfallwidget.prototype.getWidthByBw = function (bw, visual) { if (visual) { var perPoint = (this.freq_end - this.freq_start) / this.visual_MapLen; var point = bw / perPoint; return point; } else { var per = (this.freq_end - this.freq_start) / this.waterfall_width; var pointr = bw / per; return pointr + 1; } }; waterfallwidget.prototype.getFreqByPointInZoom = function (point) { var count = this.zoomOption[this.freq_zoom].count; var per = this.zoomPer; var perPoint = (count * per) / this.waterfall_width; return perPoint * point; }; waterfallwidget.prototype.getPointByBand = function (hz) { //200p --4000hz //return hz / (4000*1.0/200); //按真实比例来算 var count = this.zoomOption[this.freq_zoom].count; var per = this.zoomPer; var perPoint = (count * per) / this.waterfall_width; return (hz * 0.001) / perPoint; }; waterfallwidget.prototype.getBandByPoint = function (p) { //200p --4000hz return p * ((4000 * 1.0) / 200); }; waterfallwidget.prototype._showInfo = function (opt) { if (this.info_Position < 0) return; var layer = this.layer_info; var textInfo = (opt && opt.text) || 'message'; var x = (opt && opt.x) || 0; var y = (opt && opt.y) || 0; var centerp = (opt && opt.centerp) || false; var textcolor = (opt && opt.textcolor) || this.info_Position == 0 ? this.bg_color : this.fore_color; var bgcolor = (opt && opt.bgcolor) || this.info_Position == 0 ? this.fore_color : this.bg_color; var text = new Konva.Text({ x: 10, y: 10, text: textInfo, fontSize: 13, fill: textcolor, }); var rect = new Konva.Rect({ x: 0, y: 0, fill: bgcolor, width: text.width() + 20, height: text.height() + 20, cornerRadius: 5, shadowColor: this.bg_color, shadowBlur: 10, shadowOffset: [10, 10], shadowOpacity: 0.2, stroke: this.bg_color, strokeWidth: 2, }); var group = new Konva.Group({ x: 0, y: 0, }); group.add(rect); group.add(text); if (x == 0 && y == 0) { x = this.stage.getWidth() / 2 - rect.getWidth() / 2; y = this.stage.getHeight() / 2 - rect.getHeight() / 2; } else if (centerp) { x = x - rect.width() / 2; } group.x(x); group.y(y); layer.add(group); layer.draw(); }; waterfallwidget.prototype.showInfoAuto = function (opt) { var delay = (opt && opt.delay) || 1000; var _self = this; _self.hideInfo(); _self.showInfo(opt); _self.infoTimeout = setTimeout(function () { _self.hideInfo(); }, delay); }; waterfallwidget.prototype.hideInfo = function () { var layer = this.layer_info; var layer5 = this.layer_info5; if (this.infoTimeout) { clearTimeout(this.infoTimeout); this.infoTimeout = null; } layer.destroyChildren(); layer.removeChildren(); layer.draw(); }; waterfallwidget.prototype.showInfo = function (opt, canSetting = false) { if (this.infoTimeout) { clearTimeout(this.infoTimeout); this.infoTimeout = null; } var _self = this; var layer = this.layer_info; var message = (opt && opt.text) || 'message'; var x = (opt && opt.x) || 0; var y = (opt && opt.y) || 0; var curX = x; var curY = y; if (canSetting && this.info_Position == 1) { x = this.container.clientWidth - this.margin_right - 140; y = this.margin_top + 2; opt.x = x; opt.y = y; } var centerp = (opt && opt.centerp) || false; var text = layer.findOne('Text'); if (!text) { _self._showInfo(opt); } else { var rect = layer.findOne('Rect'); var group = layer.findOne('Group'); text.text(message); rect.width(text.width() + 20); rect.height(text.height() + 20); if (x == 0 && y == 0) { x = this.stage.getWidth() / 2 - rect.getWidth() / 2; y = this.stage.getHeight() / 2 - rect.getHeight() / 2; } else if (centerp) { x = x - rect.width() / 2; } group.x(x); group.y(y); if (this.showCurLine) { var linex = layer.findOne('.linex'); if (linex) { linex.remove(); } var liney = layer.findOne('.liney'); if (liney) { liney.remove(); } linex = new Konva.Line({ points: [this.waterfall_x, curY, this.waterfall_x + this.waterfall_width, curY], stroke: this.fore_color, strokeWidth: 1, listening: false, name: 'linex', }); liney = new Konva.Line({ points: [curX, this.margin_top, curX, this.stage.getHeight() - this.margin_bottom], stroke: this.fore_color, strokeWidth: 1, listening: false, name: 'liney', }); layer.add(linex); layer.add(liney); } layer.draw(); } }; waterfallwidget.prototype.showInfoMakeDb = function () { if (this.infoTimeout) { clearTimeout(this.infoTimeout); this.infoTimeout = null; } var layer5 = this.layer_info5; //Mak频差 和 电平差动态改变 所属参数不能为空值 if (this.MakeShow != null && this.MakeShow.length == 2) { var text1 = layer5.findOne('Text'); var info = '频差:' + Math.ceil(Math.abs(this.MakeShow[0] - this.MakeShow[1]) / 1000000) + 'MHz\n电平差:' + Math.abs(this.MakeDb - this.MakeDb1) + 'dBm'; if (!text1) { ////Mak频差 和 电平差 模型初始化 if (this.MakeShow != null && this.MakeShow.length == 2) { var layer5 = this.layer_info5; var text1 = new Konva.Text({ x: 10, y: 10, text: info, fontSize: 13, fill: this.info_Position == 0 ? this.bg_color : this.fore_color, }); var rect1 = new Konva.Rect({ x: 0, y: 0, fill: this.info_Position == 0 ? this.fore_color : this.bg_color, width: text1.width() + 20, height: text1.height() + 20, cornerRadius: 5, shadowColor: this.bg_color, shadowBlur: 10, shadowOffset: [10, 10], shadowOpacity: 0.2, stroke: this.bg_color, strokeWidth: 2, }); var group1 = new Konva.Group({ x: 0, y: 0, }); group1.add(rect1); group1.add(text1); group1.x(70); group1.y(22); layer5.add(group1); layer5.draw(); } } else { var rect1 = layer5.findOne('Rect'); var group1 = layer5.findOne('Group'); rect1.width(text1.width() + 20); rect1.height(text1.height() + 20); text1.text(info); group1.x(this.margin_left + 10); group1.y(22); if (this.showCurLine) { var linex = layer5.findOne('.linex'); if (linex) { linex.remove(); } var liney = layer5.findOne('.liney'); if (liney) { liney.remove(); } linex = new Konva.Line({ points: [this.waterfall_x, curY, this.waterfall_x + this.waterfall_width, curY], stroke: this.fore_color, strokeWidth: 1, listening: false, name: 'linex', }); liney = new Konva.Line({ points: [curX, this.margin_top, curX, this.stage.getHeight() - this.margin_bottom], stroke: this.fore_color, strokeWidth: 1, listening: false, name: 'liney', }); layer5.add(linex); layer5.add(liney); } layer5.draw(); } } else { layer5.destroyChildren(); layer5.removeChildren(); layer5.draw(); } }; waterfallwidget.prototype.showFreqInfo = function (p, auto) { //var _self = this; //p = p || 'pointer'; //var x = _self.getPointByFreq(_self.adj_Pointer); //var y = _self.margin_top - 80; //var text = _self.adj_Pointer + "kHz"; //if (p == 'band') { // text = "BAND:" + _self.adj_Band + "Hz"; //} //var d = { // text: text, // y: y, // x: x, // centerp: true //}; //if (auto) { // _self.showInfoAuto(d); //} //else { // _self.showInfo(d); //} }; waterfallwidget.prototype.initContextMenu = function () { var p0 = `
`; var p11 = ''; if (this.showCheckSignal) { p11 = `