Files
vue-ts-example/public/html-page/waterfallwidget.js
2025-04-10 14:55:44 +08:00

4712 lines
140 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// @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 = `<div id='warterfall-contextmenu' class="dropdown bootstrapMenu" style="z-index: 10000; position: absolute; display: none;">
<ul class="dropdown-menu" style="position:static;display:block;font-size:0.9em;">`;
var p1 = '';
if (this.allowRunMode === 0) {
p1 = `<li class='ddc-item-click ddc-item' ><a href="javascript:void(0);"><span>单次侦察</span></a></li><li class='divider ddc-item' ></li>`;
}
var p1_1 = '';
if (this.allowRunMode === 0) {
p1_1 = `<li class='item-loop-ana ddc-item' ><a href="javascript:void(0);"><span>持续侦察</span></a></li><li class='divider ddc-item' ></li>`;
}
//备份
var p1_1_1 = '';
if (this.allowRunMode === 0) {
p1_1_1 =
`<li class="dropdown-submenu action-info ddc-item">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" data-stopPropagation="true">持续侦察</a>
<ul class="dropdown-menu">
<li class='ddc-item-click-loop ddc-item' ><a href="javascript:void(0);"><span>循环检测</span></a></li>
<li class='ddc-item-click-loop ddc-item d-none' ><a href="javascript:void(0);"><span>数据采集</span></a></li>
<li class='ddc-item-click-loop ddc-item d-none' ><a href="javascript:void(0);"><span>体制识别</span></a></li>
<li class='ddc-item-click-loop ddc-item d-none' ><a href="javascript:void(0);"><span>信号解调</span></a></li>
<li class='ddc-item-click-loop ddc-item d-none' ><a href="javascript:void(0);"><span>编码识别</span></a></li>
<li class='ddc-item-click-loop ddc-item d-none' ><a href="javascript:void(0);"><span>协议识别</span></a></li>` +
(this.menuDoppler
? `<li class='ddc-item-click ddc-item d-none' ><a href="javascript:void(0);"><span>多普勒估计</span></a></li>`
: ``) +
`
</ul>
</li>
<li class='divider ddc-item' ></li>`;
}
var p2 = '';
if (this.allowRunMode == 1) {
p2 = `
<li class="dropdown-submenu action-info ddc-item">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown">实时监视</a>
<ul class="dropdown-menu">
<li data-action="downloadpcm" class="action-info item-sound-add ddc-item">
<a href="javascript:void(0);" ><span class="actionName">音频数据(AM/FM)</span></a>
</li>
<li data-action="downloadfft" class="action-info item-adsb-add ddc-item">
<a href="javascript:void(0);" role="menuitem"><span class="actionName">态势(ADS-B)</span></a>
</li>
<li data-action="downloadfft" class="action-info item-acxx-add ddc-item">
<a href="javascript:void(0);" role="menuitem"><span class="actionName">态势(ACXX)</span></a>
</li>
</ul>
</li>
<li class='divider ddc-item' ></li>`;
}
var p3 = `<li class='ddc-item-click-addExcludes ddc-item' ><a href="javascript:void(0);"><span>添加到黑名单</span></a></li>`;
var p4 = ``;
if (this.allowRunMode === 0) {
p4 = `<li class='divider ddc-item' ></li><li class="dropdown-submenu action-info ddc-item">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" href="javascript:void(0);">数据采集</a>
<ul class="dropdown-menu">`;
if (this.isADGather == true) {
p4 += `<li class='ddc-item-click-adnarrowband ddc-item' ><a href="javascript:void(0);"><span>窄带AD采集</span></a></li>
<li class='ddc-item-click-broadband ddc-item' ><a href="javascript:void(0);"><span>宽带AD采集</span></a></li>`;
}
// p4 += `<li class='ddc-item-click-ddc ddc-item' ><a href="javascript:void(0);"><span>单路持续采集</span></a></li>
//<li class='ddc-item-click-ddc-mut ddc-item ' ><a href="javascript:void(0);"><span>多路持续采集</span></a></li>
//<li class='ddc-item-click-loop-ddc ddc-item' ><a href="javascript:void(0);"><span>能量触发采集</span></a></li>
//<li class='ddc-item-click-loop-ddc-xl ddc-item ' ><a href="javascript:void(0);"><span>同步序列触发采集</span></a></li>
// </ul>
// </li>`;
p4 += `<li class='ddc-item-click-ddc ddc-item' ><a href="javascript:void(0);"><span>单路持续采集</span></a></li>
<li class='ddc-item-click-ddc-mut ddc-item ' ><a href="javascript:void(0);"><span>多路持续采集</span></a></li>
</ul>
</li>`;
}
//短波
var p10 = '';
if (this.isHF) {
p10 = `<li class='ddc-item-click ddc-item' ><a href="javascript:void(0);"><span>单次侦察</span></a></li><li class='divider ddc-item' ></li>`;
}
var p9 = `<li class='ddc-item ddc-item-disable' ><a href="javascript:void(0);"><span>${this.menuDisableText}</span></a></li>
</ul></div>`;
var p11 = '';
if (this.showCheckSignal) {
p11 = `<li class='ddc-item-click-addSignal'><a href="javascript:void(0);"><span>识别选中信号</span></a></li><li class='divider' ></li>`;
}
var p12 = '';
if (this.showHoppingDetect) {
p12 = `<li class='ddc-item-click-hoppdetect'><a href="javascript:void(0);"><span>跳频检测</span></a></li><li class='divider ddc-item' ></li>`;
}
if (this.isHF) {
this.contextMenu = $(p0 + p1 + p1_1 + p2 + p11 + p3 + p4 + p9);
} else if (this.isUHF) {
this.contextMenu = $(p0 + p1 + p1_1 + p2 + p11 + p12 + p3 + p9); //+ p5
} else {
this.contextMenu = $(p0 + p1 + p1_1 + p2 + p11 + p12 + p3 + p4 + p9); //p1_1_2 + p5
}
$('body').append(this.contextMenu);
this.contextMenu.on('click', 'a', (e) => {
var li = $(e.currentTarget).closest('li');
if (li.hasClass('ddc-item-click')) {
this.fire('context-click', { action: $(e.currentTarget).text() });
}
//else if (li.hasClass('ddc-item-click-loop')) {
// this.fire("context-loop-click", { action: $(e.currentTarget).text() });
//}
else if (li.hasClass('ddc-item-click-loop-ddc')) {
this.fire('context-loop-ddc-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('ddc-item-click-loop-ddc-xl')) {
this.fire('context-loop-xl-ddc-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('ddc-item-click-addExcludes')) {
this.fire('context-addExcludes-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('ddc-item-click-ddc')) {
this.fire('context-ddc-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('ddc-item-click-adnarrowband')) {
this.fire('context-adnarrowband-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('ddc-item-click-broadband')) {
this.fire('context-broadband-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('ddc-item-click-ddc-mut')) {
this.fire('context-ddc-mut-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('item-sound-add')) {
this.fire('context-sound-add-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('item-adsb-add')) {
this.fire('context-adsb-add-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('item-acxx-add')) {
this.fire('context-acxx-add-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('item-loop-ana')) {
this.fire('context-loop-ana-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('realtime-monitor')) {
this.fire('context-realtime-monitor', { action: $(e.currentTarget).text() });
} else if (li.hasClass('ddc-item-click-addSignal')) {
this.fire('context-addSignal-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('ddc-item-click-hoppdetect')) {
this.fire('ddc-item-click-hoppdetect', { action: $(e.currentTarget).text() });
}
//else if (li.hasClass('item-loop-control')) {
// this.fire("context-loop-control-click", { action: $(e.currentTarget).text() });
//}
this.hideContextMenu();
});
//屏蔽区域内的右键菜单功能20210916 liujg
this.contextMenu.on('contextmenu', (e) => {
window.event.returnValue = false;
});
//鼠标离开菜单元素后自动隐藏功能菜单
this.contextMenu.on('mouseleave', (e) => {
this.hideContextMenu();
});
};
waterfallwidget.prototype.initLabelsMenu = function () {
_self = this;
var p0 = `<div id='warterfall-labelsmenu' class="dropdown bootstrapMenu" style="z-index: 10000; position: absolute; display: none;">
<ul class="dropdown-menu" style="position:static;display:block;font-size:0.9em;">`;
var p1 = '';
if (this.allowRunMode === 0) {
p1 = `<li class="dropdown-submenu action-info ddc-item">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" data-stopPropagation="true">重新分析</a>
<ul class="dropdown-menu">
<li class='item-resysidentity-ana ddc-item' ><a class='label-menu-item' href="javascript:void(0);"><span>体制识别</span></a></li>
<li class='item-redemodsig-ana ddc-item' ><a class='label-menu-item' href="javascript:void(0);"><span>信号解调</span></a></li>
<li class='item-reencodefy-ana ddc-item' ><a class='label-menu-item' href="javascript:void(0);"><span>编码识别</span></a></li>
<li class='item-redoprotocol-ana ddc-item' ><a class='label-menu-item' href="javascript:void(0);"><span>协议识别</span></a></li>
<li class='item-redoppler-ana ddc-item' ><a class='label-menu-item' href="javascript:void(0);"><span>多普勒估计</span></a></li>
</ul>
</li>
<li class='divider ddc-item' ></li>`;
}
var p2 = '';
p2 += `<li class='item-setcolor-ana ddc-item'><a class='label-menu-item' href="javascript:void(0);" id="specColor" name="specColor"><span>颜色标注</span></a></li><li class='divider ddc-item' ></li>`;
var p3 = `<li class='ddc-item-click-addExcludes ddc-item label-menu-ite' ><a class='label-menu-item' href="javascript:void(0);"><span>添加到黑名单</span></a></li>`;
var p4 = ``;
if (this.allowRunMode === 0) {
p4 = `<li class='divider ddc-item' ></li><li class="dropdown-submenu action-info ddc-item">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" href="javascript:void(0);">下载数据</a>
<ul class="dropdown-menu">`;
p4 += `<li class='ddc-item-click-adnarrowband ddc-item' ><a class='label-menu-item' href="javascript:void(0);"><span>下载DDC/模采数据</span></a></li>
<li class='ddc-item-click-broadband ddc-item' ><a class='label-menu-item' href="javascript:void(0);"><span>下载解调数据</span></a></li>`;
p4 += `<li class='ddc-item-click-ddc ddc-item' ><a class='label-menu-item' href="javascript:void(0);"><span>下载解码数据</span></a></li>
</ul>
</li>`;
}
var p9 = `<li class='ddc-item ddc-item-disable' ><a href="javascript:void(0);"><span></span></a></li>
</ul></div>`;
this.labelsMenu = $(p0 + p1 + p2 + p3 + p4 + p9);
$('body').append(this.labelsMenu);
this.labelsMenu.on('click', 'a', (e) => {
var li = $(e.currentTarget).closest('li');
if (li.hasClass('ddc-item-click')) {
this.fire('context-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('item-setcolor-ana')) {
this.fire('context-setcolor-click', { action: $(e.currentTarget) });
} else if (li.hasClass('item-resysidentity-ana')) {
this.fire('context-resysidentity-click', { action: $(e.currentTarget) });
} else if (li.hasClass('item-redemodsig-ana')) {
this.fire('context-redemodsig-click', { action: $(e.currentTarget) });
} else if (li.hasClass('item-reencodefy-ana')) {
this.fire('context-reencodefy-click', { action: $(e.currentTarget) });
} else if (li.hasClass('item-redoprotocol-ana')) {
this.fire('context-redoprotocol-click', { action: $(e.currentTarget) });
} else if (li.hasClass('item-redoppler-ana')) {
this.fire('context-redoppler-click', { action: $(e.currentTarget) });
} else if (li.hasClass('ddc-item-click-addExcludes')) {
this.fire('context-addExcludes-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('ddc-item-click-loop-ddc')) {
this.fire('context-loop-ddc-click', { action: $(e.currentTarget).text() });
} else if (li.hasClass('ddc-item-click-loop-ddc-xl')) {
this.fire('context-loop-xl-ddc-click', { action: $(e.currentTarget).text() });
}
this.hideContextMenu();
});
//屏蔽区域内的右键菜单功能20210916 liujg
this.labelsMenu.on('contextmenu', (e) => {
window.event.returnValue = false;
});
//鼠标离开菜单元素后自动隐藏功能菜单
this.labelsMenu.on('mouseleave', (e) => {
this.hideContextMenu();
});
};
waterfallwidget.prototype.destroryContextMenu = function () {
this.contextMenu.remove();
//this.labelsMenu.remove();
};
waterfallwidget.prototype.showLabelsMenu = function (el) {
if (el) {
createAttribute(el, 'label-menu-item');
}
this.labelsMenu.css('left', el.evt.clientX).css('top', el.evt.clientY);
setTimeout((ee) => {
//this.labelsMenu.show();
}, 200);
};
createAttribute = function (el, itemId) {
var menuItems = document.getElementsByClassName(itemId);
if (menuItems.length <= 0) return;
for (var i = 0; i < menuItems.length; i++) {
var attr = document.createAttribute('label-id');
attr.nodeValue = el.target.parent.label.id;
menuItems[i].attributes.setNamedItem(attr);
}
};
waterfallwidget.prototype.showContextMenu = function (x, y) {
this.contextMenu.css('left', x).css('top', y);
if (this.adj_show) {
this.contextMenu.find('.ddc-item').removeClass('disabled');
} else {
this.contextMenu.find('.ddc-item').addClass('disabled');
}
var enable = this.menuEnableHandle ? !this.menuEnableHandle() : false;
if (enable) {
this.contextMenu.find('.ddc-item').show();
this.contextMenu.find('.ddc-item-disable').hide();
} else {
this.contextMenu.find('.ddc-item').hide();
this.contextMenu.find('.ddc-item-disable').show();
}
setTimeout((ee) => {
this.contextMenu.show();
}, 200);
};
waterfallwidget.prototype.hideContextMenu = function () {
this.contextMenu.hide();
//this.labelsMenu.hide();
};
waterfallwidget.prototype.zoomChange = function () {
this.fire('zoom-change', { start: this.freq_start, end: this.freq_end });
};
waterfallwidget.prototype.setFreqRange = function (min, max) {
this.min_freq = min;
this.max_freq = max;
//this.adj_Pointer = (this.max_freq - this.min_freq) / 2;
this.zoomPer = (this.max_freq - this.min_freq) / this.zoomOption;
this.setFreqZoom();
this.zoomQueue = [];
};
waterfallwidget.prototype.setShowSpectrogramAvg = function (val) {
this.showSpectrogramAvg = val;
this.SpectrogramBuff = [];
};
waterfallwidget.prototype.setShowSpectrogramMin = function (val) {
this.showSpectrogramMin = val;
this.SpectrogramMinBuff = [];
};
waterfallwidget.prototype.setShowSpectrogramMax = function (val) {
this.showSpectrogramMax = val;
this.SpectrogramMaxBuff = [];
};
waterfallwidget.prototype.setShowPeakMarker = function (val) {
this.showPeakMarker = val;
if (this.showPeakMarker == false) {
var context = this.layer_info2.getContext();
context.clearRect(0, 0, this.layer_info2.getWidth(), this.layer_info2.getHeight());
//清除Make功能图像
var context2 = this.layer_info3.getContext();
context2.clearRect(0, 0, this.layer_info3.getWidth(), this.layer_info3.getHeight());
var context3 = this.layer_info4.getContext();
context3.clearRect(0, 0, this.layer_info4.getWidth(), this.layer_info4.getHeight());
var context = this.layer_info5.getContext();
context.clearRect(0, 0, this.layer_info5.getWidth(), this.layer_info5.getHeight());
//var context = this.layer_info6.getContext();
//context.clearRect(0, 0, this.layer_info6.getWidth(), this.layer_info6.getHeight())
//var context = this.layer_info7.getContext();
//context.clearRect(0, 0, this.layer_info7.getWidth(), this.layer_info7.getHeight())
this.MakeShow = [];
}
};
//JC添加多点标注功能 20210110
waterfallwidget.prototype.setShowMake = function (bins, val, index) {
var top = this.spectrogram_y;
var left = this.spectrogram_x;
var width = this.spectrogram_width;
var height = this.spectrogram_height;
if (this.MakeShow.length <= 0 || this.MakeShow == null) {
var context = val.getContext();
context.clearRect(0, 0, val.getWidth(), val.getHeight());
return;
}
if (this.MakeShow[index] > this.freq_start && this.MakeShow[index] < this.freq_end) {
var band = this.max_db - this.min_db;
var peakMarkIndex = Math.ceil(
(this.MakeShow[index] - this.freq_start) / ((this.freq_end - this.freq_start) / bins.length),
);
var markv = bins[peakMarkIndex];
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(3)} MHz`;
var context = val.getContext();
context.clearRect(0, 0, val.getWidth(), val.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 (index == 0) {
this.MakeDb = markv.toFixed(2);
} else {
this.MakeDb1 = markv.toFixed(2);
}
} else {
var context = val.getContext();
context.clearRect(0, 0, val.getWidth(), val.getHeight());
}
};
//载波检测线
waterfallwidget.prototype.setCarryLineMode = function (val) {
console.log('setCarryLineMode:' + val);
this.CarryLineMode = val;
this.drawCarryLine();
};
waterfallwidget.prototype.setCarryLineList = function (val, fired = true) {
//console.log("setCarryLineList:" + val);
this.CarryLineList = val;
this.drawCarryLine();
if (fired) {
this.throttleFireCarryLineChange(val);
}
};
waterfallwidget.prototype.initCarryLine = function () {
//必须在init调用一次 否则resize会出问题
var layer = this.layer_carryline;
layer.destroyChildren();
layer.removeChildren();
this.throttleFireCarryLineChange = _.throttle((vals) => {
this.fire('carry-line-change', { list: vals });
}, 100);
var groupLine = new Konva.Group({
x: this.area_x,
y: 0,
name: 'line-g',
visible: false,
});
groupLine.add(
new Konva.Line({
points: [0, -10, this.area_width, 0],
stroke: 'transparent',
strokeWidth: 20,
lineCap: 'round',
lineJoin: 'round',
visible: true,
//dash:[10,4]
}),
);
groupLine.add(
new Konva.Line({
points: [0, 0, this.area_width, 0],
stroke: '#1d8cf8',
strokeWidth: 2,
lineCap: 'round',
lineJoin: 'round',
visible: true,
//dash: [10, 4]
}),
);
groupLine.add(
new Konva.Circle({
x: this.area_width,
y: 0,
fill: '#1d8cf8',
radius: 3,
}),
);
groupLine.add(
new Konva.Circle({
x: 0,
y: 0,
fill: '#1d8cf8',
radius: 3,
}),
);
groupLine.on('mousedown', (e) => {
console.log(e.evt.button);
if (e.evt.button != 0) {
return;
}
this.stage.on('mousemove', (e) => {
var ndb = this.getDbByPoint(e.evt.offsetY);
if (ndb < this.min_db) {
ndb = this.min_db;
}
if (ndb > this.max_db) {
ndb = this.max_db;
}
this.setCarryLineList([ndb]);
});
this.stage.on('mouseup', (e) => {
this.stage.off('mousemove');
this.stage.off('mouseup');
});
});
//增益区域鼠标移入鼠标图标变化
groupLine.on('mouseover', (e) => {
this.stage.container().style.cursor = 'row-resize';
});
groupLine.on('mouseout', (e) => {
this.stage.container().style.cursor = 'default';
});
layer.add(groupLine);
this.drawCarryLine();
};
waterfallwidget.prototype.clearCarryLine = function () {
var layer = this.layer_carryline;
var groupLine1 = layer.findOne('.carryline');
if (groupLine1) {
groupLine1.remove();
}
var nodes = layer.find('.carryline-node');
if (nodes) {
for (item of nodes) {
item.remove();
}
}
var groupLine = layer.findOne('.line-g');
if (groupLine) {
groupLine.visible(false);
}
layer.batchDraw();
};
waterfallwidget.prototype.drawCarryLine = function () {
if (this.CarryLineMode == 1) {
this.drawCarryLine1();
} else if (this.CarryLineMode == 2) {
this.drawCarryLine2();
} else {
this.clearCarryLine();
}
};
//折线
waterfallwidget.prototype.drawCarryLine1 = function () {
if (!this.CarryLineList) {
this.CarryLineList = [];
}
if (this.CarryLineList.length == 1) {
//代表是模式2的单值方式
this.CarryLineList = [];
}
var arr = [];
for (var i = 0; i < this.CarryLineList.length; i += 2) {
arr.push(this.getPointByFreq(this.CarryLineList[i]));
arr.push(this.getPointByDb(this.CarryLineList[i + 1]));
}
var layer = this.layer_carryline;
layer.destroyChildren();
layer.removeChildren();
var line = new Konva.Line({
points: arr,
stroke: '#1d8cf8',
strokeWidth: 2,
lineCap: 'round',
lineJoin: 'round',
name: 'carryline',
visible: true,
});
layer.add(line);
for (var i = 0; i < arr.length; i += 2) {
let circle = new Konva.Circle({
x: arr[i],
y: arr[i + 1],
fill: '#1d8cf8',
radius: 3,
name: 'carryline-node',
});
layer.add(circle);
}
layer.batchDraw();
};
//直线
waterfallwidget.prototype.drawCarryLine2 = function () {
if (!this.CarryLineList) {
this.CarryLineList = [-80];
}
if (this.CarryLineList.length != 1) {
this.CarryLineList = [-80];
}
var val = this.CarryLineList[0];
var layer = this.layer_carryline;
var groupLine = layer.findOne('.line-g');
//console.log("drawCarryLine2", val, groupLine);
groupLine.visible(true);
groupLine.y(this.getPointByDb(val));
layer.batchDraw();
};
//频率标注
waterfallwidget.prototype.drawFreqPointLableItem = function (item) {
if (!item) return;
var layer = this.layer_freqpointlable;
var textfre = `${(item.freq / 1000000).toFixed(6)} MHz`;
var id = item.id;
var color = item.txtColor;
var info = item.lableInfo;
var freq = item.freq;
var txt = item.lableType;
let _x = this.getPointByFreq(freq);
if (_x > this.area_x + this.area_width - 5) return;
_x = _x - 9;
let _y = this.waterfall_y - 30;
var fontSize = 18;
if (txt == '1') {
txt = '▼';
_y = _y - 2;
} else if (txt == '2') {
txt = '◎';
_y = _y - 5;
fontSize = 26;
} else if (txt == '3') {
txt = '◆';
_y = _y - 6;
fontSize = 30;
} else if (txt == '4') {
txt = '■';
_y = _y - 7;
fontSize = 24;
} else if (txt == '5') {
txt = '★';
_y = _y - 5;
fontSize = 22;
}
var abcRect = new Konva.Text({
x: _x,
y: _y,
fontSize: fontSize,
text: txt,
name: id,
align: 'center',
fontFamily: 'Calibri',
fill: color,
});
var _self = this;
abcRect.on('mousedown', function (e) {
var id = e.target.attrs.name;
console.log('mousedown', e.evt);
if (e.evt.button == 0) {
//左键编辑
_self.UpdateFreqPointLable(id);
} else if (e.evt.button == 2) {
console.log('id', e.target.attrs);
//右键删除
_self.RemoveFreqPointLable(id);
}
});
//增益区域鼠标移入鼠标图标变化
abcRect.on('mouseover', (e) => {
this.stage.container().style.cursor = 'pointer';
_self._showInfo(
{
x: e.evt.offsetX - 30,
y: e.evt.offsetY - 70,
textcolor: this.fore_color,
bgcolor: this.bg_color,
text: '频点:' + textfre + '\r\n' + '标注信息:' + info,
},
true,
);
});
abcRect.on('mouseout', (e) => {
this.stage.container().style.cursor = 'default';
_self.hideInfo();
});
layer.add(abcRect);
};
//新增频点标注
waterfallwidget.prototype.AddFreqPointLable = function (freq) {
this.fire('freqPointLable-add-click', { freq });
};
//修改频点标注
waterfallwidget.prototype.UpdateFreqPointLable = function (id) {
this.fire('freqPointLable-update-click', { id });
};
//删除频点标注
waterfallwidget.prototype.RemoveFreqPointLable = function (id) {
if (this.wfFreqPointLableArray.length == 0) return;
this.fire('freqPointLable-remove-click', { id });
this.drawFreqPointLables();
};
//绘制所有频点标注
waterfallwidget.prototype.drawFreqPointLables = function () {
if (this.wfFreqPointLable == false || !this.wfFreqPointLableArray) return;
var layer = this.layer_freqpointlable;
layer.removeChildren();
for (let i = 0; i < this.wfFreqPointLableArray.length; i++) {
let item = this.wfFreqPointLableArray[i];
this.drawFreqPointLableItem(item);
}
layer.batchDraw();
};
//初始化频点标注
waterfallwidget.prototype.InitFreqPointLables = function () {
if (this.wfFreqPointLable == false) return;
if (this.wfFreqPointLableList && this.wfFreqPointLableList.length > 0) {
this.wfFreqPointLableArray = this.wfFreqPointLableList;
this.drawFreqPointLables();
}
};
//重新设置频点标注数据
waterfallwidget.prototype.SetFreqPointLablesData = function (list) {
if (this.wfFreqPointLable == false) return;
//console.log("SetFreqPointLablesData",list);
if (list) {
this.wfFreqPointLableArray = list;
}
this.drawFreqPointLables();
};
//黑名单
waterfallwidget.prototype.drawWhiteList = async function () {
var _self = this;
if (this.showWhitelist) {
var layer = this.layer_white;
var opaLine = 0.3;
var opaNormal = 0.5;
var opaSelected = 0.9;
var rowStart = this.spectrogram_y + 1;
layer.destroyChildren();
layer.removeChildren();
var ret = await $.post('/setting/GetWhiteList');
for (var i = 0; i < ret.data.length; i++) {
var data = ret.data[i];
var text = data.name;
if (data.end <= _self.min_freq || data.start >= _self.max_freq) {
continue;
}
var bw = data.end - data.start;
var fc = data.start;
if (fc <= 0 || bw <= 0) {
continue;
}
var text = new Konva.Text({
x: 2,
y: 2,
text: text,
fontSize: 10,
fill: '#B3BAC5',
});
var rect = new Konva.Rect({
x: 0,
y: 0,
fill: 'transparent',
width: text.width() > 0 ? text.width() + 4 : 0,
height: text.height() > 0 ? text.height() + 4 : 0,
cornerRadius: 0,
strokeWidth: 0,
name: 'rect',
});
var line = new Konva.Rect({
x: 0,
y: 0,
fill: '#f4f5f7',
width: _self.getWidthByBw(bw),
height: this.area_height,
cornerRadius: 0,
name: 'line',
opacity: opaLine,
});
var group = new Konva.Group({
x: _self.getPointByFreq(fc),
y: rowStart,
opacity: opaNormal,
});
group.add(line);
group.add(rect);
group.add(text);
layer.add(group);
}
layer.batchDraw();
}
};
waterfallwidget.prototype.init = function () {
if (!this.stage) return; //防止已经销毁但是仍然响应了大小变化事件
this.stage.setWidth(this.container.clientWidth);
this.stage.setHeight(this.container.clientHeight);
//确定位置和大小
this.area_x = this.margin_left;
this.area_y = this.margin_top;
this.area_width = this.stage.getWidth() - this.margin_left - this.margin_right - 2;
this.area_height = this.stage.getHeight() - this.margin_top - this.margin_bottom - 2;
this.spectrogram_y = this.margin_top;
this.spectrogram_x = this.margin_left + 1;
this.spectrogram_width = this.area_width;
this.spectrogram_height = Math.floor(this.area_height * this.spec_per) - 1; //分割线
this.waterfall_y = this.margin_top + this.spectrogram_height + 1;
this.waterfall_x = this.margin_left + 1;
this.waterfall_width = this.area_width;
this.waterfall_height = Math.floor(this.area_height * (1 - this.spec_per));
this.wf = document.createElement('canvas');
this.wf.height = this.waterfall_height;
this.wf.width = this.visual_MapLen;
this.ctx_wf = this.wf.getContext('2d');
this.ctx_wf.fillStyle = this.bg_color;
this.spec = document.createElement('canvas');
this.spec.height = this.spectrogram_height;
this.spec.width = this.visual_MapLen;
this.ctx_spec = this.spec.getContext('2d');
this.ctx_spec.fillStyle = this.bg_color;
this.ctx_spec.strokeStyle = this.wave_color;
this.ctx_spec.lineWidth = 1;
this.drawCoor();
this.setFreqZoom();
this.drawCoorFreq();
this.drawCoorFreqWheel();
this.drawBottomScroll();
this.drawMap();
this.drawRuler();
this.drawAdj();
//if (this.allowRunMode == 0) { this.drawAdj(); }
if (this.isUHF) {
this.drawGather();
this.drawGatherLocation();
}
this.split_draw();
this.darwLabel();
this.initCarryLine();
this.InitFreqPointLables(); //频点标注信息
this.drawWhiteList();
};
waterfallwidget.prototype.destroy = function () {
this._events = [];
this.container.oncontextmenu = null;
this.container = null;
this.stage.destroy();
this.stage = null;
this.color_map = null;
this.wf = null;
this.ctx_wf = null;
this.label_manager = null;
this.CompareCurLineBuff = [];
this.wfFreqPointLableArray = [];
this.layer_coor.destroy();
this.layer_coorFreq.destroy();
this.layer_coorFreqWeel.destroy();
this.layer_wf.destroy();
this.layer_map.destroy();
this.layer_mapRuler.destroy();
//20211228焦超 添加make功能
this.layer_info3.destroy();
this.layer_info4.destroy();
//this.layer_info6.destroy();
//this.layer_info5.destroy();
//this.layer_info6.destroy();
//this.layer_info7.destroy();
this.layer_adj.destroy();
this.layer_label.destroy();
this.layer_labelActive.destroy();
if (this.layer_split) {
this.layer_split.destroy(); //2021.05.07 西部需要拖动修改频谱图大小,李伟添加
}
this.layer_freqpointlable.destroy();
this.layer_instant.destroy();
this.layer_chanel.destroy();
this.layer_botscroll.destroy();
this.layer_cover.destroy();
this.layer_info.destroy();
this.layer_info2.destroy();
this.layer_white.destroy();
this.destroryContextMenu();
console.log('warterfall destory...............');
};
waterfallwidget.prototype.initResize = function () {
var _self = this;
$(this.container).resize(function () {
var target = this;
if (target.resizeFlag) {
clearTimeout(target.resizeFlag);
}
target.resizeFlag = setTimeout(function () {
_self.init();
target.resizeFlag = null;
}, 100);
});
};
function waterfallwidget(id, options) {
this.options = options;
this.SpectrogramBuff = [];
this.SpectrogramBuffCount = 10;
this.SpectrogramMinBuff = [];
this.SpectrogramMaxBuff = [];
this.CompareCurLineBuff = [];
this.wfFreqPointLableArray = []; //频点标注信息
this.MakeShow = []; //Make 存储用户选择的频点
this.MakeDb; //存储用户选择的频点的电平值
this.MakeDb1; //存储用户选择的频点的电平值
this.showScrollLocal = options && !options.showScrollLocal ? true : false;
this.showSpectrogramAvg =
options && (options.showSpectrogramAvg === false || options.showSpectrogramAvg === true)
? options.showSpectrogramAvg
: false;
this.showSpectrogramMin =
options && (options.showSpectrogramMin === false || options.showSpectrogramMin === true)
? options.showSpectrogramMin
: false;
this.showSpectrogramMax =
options && (options.showSpectrogramMax === false || options.showSpectrogramMax === true)
? options.showSpectrogramMax
: false;
this.showPeakMarker =
options && (options.showPeakMarker === false || options.showPeakMarker === true) ? options.showPeakMarker : false;
this._events = {};
var enentNames = [
'adj-change',
'pointer-change',
'band-change',
'pointer-type-change',
'zoom-change',
'label-change',
'context-click',
'context-ddc-click',
'gravity-ruler-change',
];
this.on = function (type, fn, scope) {
if (type + '' !== type) {
console && console.error && console.error('the first argument type is requird as string');
return this;
}
if (typeof fn != 'function') {
console && console.error && console.error('the second argument fn is requird as function');
return this;
}
type = type.toLowerCase();
if (!this._events[type]) {
this._events[type] = [];
}
this._events[type].push(scope ? [fn, scope] : [fn]);
return this;
};
this.fire = async function (type, data) {
type = type.toLowerCase();
var eventArr = this._events[type];
var fn,
scope,
event = Object.assign(
{
// 事件类型
type: type,
// 绑定的源
origin: this,
// scope 为 this 或用户指定的上下文,
// 是否取消
cancel: false,
},
data,
);
if (!eventArr) return event;
for (var i = 0, l = eventArr.length; i < l; ++i) {
fn = eventArr[i][0];
scope = eventArr[i][1];
if (scope) {
event.scope = scope;
fn.call(scope, event);
} else {
event.scope = this;
fn(event);
}
}
return event;
};
this.off = function (type, fn) {
type = type.toLowerCase();
var eventArr = this._events[type];
if (!eventArr || !eventArr.length) return this;
if (!fn) {
this._events[type] = eventArr = [];
} else {
for (var i = 0; i < eventArr.length; ++i) {
if (fn === eventArr[i][0]) {
eventArr.splice(i, 1);
// 1、找到后不能立即 break 可能存在一个事件一个函数绑定多次的情况
// 删除后数组改变,下一个仍然需要遍历处理!
--i;
}
}
}
return this;
};
this.one = function (type, fn, scope) {
var that = this;
function nfn() {
// 执行时 先取消绑定
that.off(type, nfn);
// 再执行函数
fn.apply(scope || that, arguments);
}
this.on(type, nfn, scope);
return this;
};
this.coorFreqType = options && options.coorFreqType ? options.coorFreqType : 0;
this.menuEnableHandle = options && options.menuEnableHandle ? options.menuEnableHandle : null;
this.menuDisableText = options && options.menuDisableText ? options.menuDisableText : '菜单禁止使用';
this.allowRunMode = options && options.allowRunMode != undefined ? options.allowRunMode : 0;
this.isADGather = options && options.isADGather != undefined ? options.isADGather : false; //是否开启AD采集
this.isHF = options && options.isHF != undefined ? options.isHF : false; //是否短波界面
this.isUHF = options && options.isUHF != undefined ? options.isUHF : false; //是否超短波界面
//this.allowCycleControl = (options && (options.allowCycleControl === false || options.allowCycleControl === true)) ? options.allowCycleControl : false;;//侦察控守
this.showCheckSignal = options && options.showCheckSignal != undefined ? options.showCheckSignal : false; //是否显示右键 识别选中信号
this.showHoppingDetect = options && options.showHoppingDetect != undefined ? options.showHoppingDetect : false; //是否显示超短 跳频检测
this.min_band = options && options.min_band ? options.min_band : 500;
this.max_band = options && options.max_band ? options.max_band : 200000;
//这是整体的频谱大小 hz
this.min_freq = options && options.min_freq ? options.min_freq : 0;
this.max_freq = options && options.max_freq ? options.max_freq : 40000;
//这是当前缩放尺度的大小
this.freq_start = 0;
this.freq_end = 0;
this.disableZoom = options && options.disableZoom ? options.disableZoom : false;
this.zoomOption = options && options.zoomOption ? options.zoomOption : 16;
this.zoomPer = (this.max_freq - this.min_freq) / this.zoomOption;
this.zoomQueue = [];
this.fucFFTBuff = options && options.fucFFTBuff ? options.fucFFTBuff : null;
this.unitBuffId = options && options.unitBuffId ? options.unitBuffId : 0;
this.fftModelId = options && options.fftModelId ? options.fftModelId : 0;
this.visual_MapLen = 2000;
// Handle options
this.min_db = options && options.min_db ? options.min_db : -200;
this.max_db = options && options.max_db ? options.max_db : 0;
this.db_counter = options && options.db_counter ? options.db_counter : 10;
this.onAutomaticAdjustment = options.onAutomaticAdjustment;
this.info_Position = options && options.info_Position ? options.info_Position : 0; //跟随鼠标 1右上角
this.freq_zoom = options && options.freq_zoom ? options.freq_zoom : -1;
this.show_msFreq =
options && (options.show_msFreq === false || options.show_msFreq === true) ? options.show_msFreq : true;
this.showFreqLable =
options && (options.showFreqLable === false || options.showFreqLable === true) ? options.showFreqLable : true;
this.wfFreqPointLable =
options && (options.wfFreqPointLable === false || options.wfFreqPointLable === true)
? options.wfFreqPointLable
: false; //频点标注
this.wfFreqPointLableList = options && options.wfFreqPointLable === true ? options.wfFreqPointLableList : []; //频点标注数据
//this.adj_Pointer = (options && options.adj_Pointer) ? options.adj_Pointer : (this.max_freq - this.min_freq) / 2;
//this.adj_Type = (options && options.adj_Type) ? options.adj_Type : 'center';
//this.adj_Band = (options && options.adj_Band) ? options.adj_Band : 3600;
//余晖图
//this.enableAfterglow = (options && (options.enableAfterglow === false || options.enableAfterglow === true)) ? options.enableAfterglow : false;
this.delayAfterglow = options && options.delayAfterglow ? options.delayAfterglow : 0; //3秒
this.isBwFc = options && (options.isBwFc === false || options.isBwFc === true) ? options.show_msFreq : false;
if (options.adj_show === false) {
this.adj_show = false;
} else if (options.adj_show === true) {
this.adj_show = true;
} else {
this.adj_show = this.allowRunMode == 1 ? true : false;
}
this.gather_show = this.allowRunMode == 0 ? true : false;
this.split_show = true; //2021.05.07 西部需求拖动更改频谱窗口大小,李伟添加;
this.adj_defaultbw = 1;
this.adj_maxbw = options && options.adj_maxbw ? options.adj_maxbw : 90000000;
this.adj_lineWidth = this.allowRunMode == 0 ? 1 : 2; //4 : 2
if (this.adj_lineType == undefined) {
this.adj_lineType = 0;
}
this.adj_color = options && options.adj_color ? options.adj_color : this.allowRunMode == 0 ? '#6CE26C' : '#F37570';
this.adjcenter_color =
options && options.adjcenter_color ? options.adjcenter_color : this.allowRunMode == 0 ? '#007ACC' : '#007ACC';
this.adj_start = options.adj_start;
this.adj_end = options.adj_end;
if (!this.adj_start) {
this.adj_start = this.min_freq + (this.max_freq - this.min_freq) / 2;
}
if (!this.adj_end) {
this.adj_end = this.adj_start + this.adj_defaultbw;
}
this.gather_fc = 0;
this.gather_bw = 0;
this.adj_step = options && options.adj_step ? options.adj_step : 0;
this.wf_size = options && options.wf_size ? options.wf_size : 1000;
this.wf_rows = options && options.wf_rows ? options.wf_rows : 1024;
this.timeQueue = [];
this.timeIndex = 0;
this.time_span = 20; //每20像素画一个时间
//this.time_out = (options && options.time_out) ? options.time_out : 100; //代表一提供数据的时间单位是 ms 废弃
this.showCurLine = options && options.showCurLine ? options.showCurLine : false;
//对比谱线
this.showCompareCurLine = options && options.showCompareCurLine ? options.showCompareCurLine : false;
this.time_rate = options && options.time_rate ? options.time_rate : 1; //代表速度(暂未实现) 比如0-1
//this.bg_color = (options && options.bg_color) ? options.bg_color : '#27293D';
this.bg_color = options && options.bg_color ? options.bg_color : '#37384B';
this.fore_color = options && options.bg_color ? options.bg_color : '#CCCCFF';
this.wave_color = options && options.wave_color ? options.wave_color : '#4BF3A7'; //'#296FF5';
this.wave_color_avg = options && options.wave_color_avg ? options.wave_color_avg : '#FC6945';
this.wave_color_max = options && options.wave_color_max ? options.wave_color_max : '#ffff00'; //'#296FF5';//'#00BF9A';
this.wave_color_min = options && options.wave_color_min ? options.wave_color_min : '#fff';
this.wave_color_compare = options && options.wave_color_compare ? options.wave_color_compare : '#f5365c';
this.waveAfterglow_color = options && options.waveAfterglow_color ? options.waveAfterglow_color : '#BCF90A'; //'#296FF5';
this.instant_color = options && options.instant_color ? options.instant_color : '#f8ffed';
this.instant_show =
options && (options.instant_show === false || options.instant_show === true) ? options.instant_show : true;
this.chanel_color = options && options.chanel_color ? options.chanel_color : '#ffffff';
this.chanel_show =
options && (options.chanel_show === false || options.chanel_show === true) ? options.chanel_show : true;
this.spec_per = options && (options.spec_per === 0 || options.spec_per) ? options.spec_per : 0.5;
this.labelMode = options && (options.labelMode === false || options.labelMode === true) ? options.labelMode : true;
this.showWhitelist = options && options.showWhitelist ? options.showWhitelist : false;
this.label_manager =
options && options.label_manager
? options.label_manager
: {
labels: [
{
name: 'FM',
id: 'id1',
bg_color: '#2bffc6',
fore_color: '#000',
location: 80000000,
},
{
name: 'AM',
id: 'id2',
bg_color: '#2bffc6',
fore_color: '#000',
location: 90000000,
},
{
name: 'USB',
id: 'id3',
bg_color: '#fd5d93',
fore_color: '#fff',
location: 100000000,
},
{
name: 'FSK',
id: 'id4',
bg_color: '#ff8d72',
fore_color: '#fff',
location: 110000000,
},
{
name: 'QPSK',
id: 'id5',
bg_color: '#5603ad',
fore_color: '#fff',
location: 120000000,
},
{
name: '4FSK',
id: 'id6',
bg_color: '#5603ad',
fore_color: '#fff',
location: 130000000,
},
{
name: 'USB',
id: 'id7',
bg_color: '#fd5d93',
fore_color: '#fff',
location: 140000000,
},
{
name: '2FSK',
id: 'id8',
bg_color: '#ff8d72',
fore_color: '#fff',
location: 150000000,
},
{
name: 'LSB',
id: 'id8',
bg_color: '#ff8d72',
fore_color: '#fff',
location: 160000000,
},
{
name: 'QPSK',
id: 'id9',
bg_color: '#5603ad',
fore_color: '#fff',
location: 170000000,
},
],
onclick: function (e) {},
load: function (start, end) {
return this.labels.filter((x) => x.location <= end && x.location >= start);
},
onRemove: function (id) {
console.log('label delete' + id);
},
};
//this.label_manager = null;
this.currentLabel = null;
this.margin_top = 20;
if (this.labelMode) {
this.margin_top = 140;
}
this.margin_bottom = 5;
this.margin_left = 60;
this.margin_right = 80; // Increased right margin to move content left
if (!this.options) {
this.options = {};
}
if (!this.options.wfOption) {
this.options.wfOption = {
wfRulerEnable: true,
wfTheme: 'default',
wfRulerGravity: true,
wfRulerLocation: -100,
};
}
this.gravity_location = this.options.wfOption.wfRulerLocation;
this.showRuler = this.options.wfOption.wfRulerEnable;
//console.log(`option gravity location=${this.gravity_location} gravity_value = ${this.getGravityPerByLocation()}`)
this.color_map = new colormapwidget({
name: this.options.wfOption.wfTheme,
gravity: this.options.wfOption.wfRulerGravity,
gravity_value: this.getGravityPerByLocation(),
count: this.max_db - this.min_db,
mapCount: this.max_db - this.min_db,
});
this.container = document.getElementById(id);
//屏蔽右键菜单
this.container.oncontextmenu = function () {
return false;
};
this.throttleSetFreqZoomUp = _.throttle((start, end, record) => {
this.setFreqZoomUp(start, end, record);
}, 100);
this.stage = new Konva.Stage({
container: id, // id of container <div>
width: this.container.clientWidth || 500,
height: this.container.clientHeight || 500,
});
this.layer_coor = new Konva.Layer();
this.layer_coor.hitGraphEnabled(false);
this.layer_coorFreq = new Konva.Layer();
this.layer_coorFreq.hitGraphEnabled(false);
this.layer_coorFreqWeel = new Konva.Layer();
this.layer_wf = new Konva.Layer();
this.layer_wf.hitGraphEnabled(false);
this.layer_map = new Konva.Layer();
this.layer_mapRuler = new Konva.Layer();
//绿色,在侦察模型下 能右键选中的区域。
this.layer_adj = new Konva.Layer();
//this.layer_split = new Konva.Layer();//2021.05.07 西部需要拖动修改频谱图大小,李伟添加
this.layer_label = new Konva.Layer();
this.layer_labelActive = new Konva.Layer();
this.layer_info = new Konva.Layer();
this.layer_info.hitGraphEnabled(false);
this.layer_info2 = new Konva.Layer();
this.layer_info2.hitGraphEnabled(false);
this.layer_instant = new Konva.Layer();
this.layer_instant.hitGraphEnabled(false);
this.layer_chanel = new Konva.Layer();
this.layer_chanel.hitGraphEnabled(false);
this.layer_cover = new Konva.Layer();
this.layer_cover.hitGraphEnabled(false);
this.layer_carryline = new Konva.Layer();
//this.layer_carryline.hitGraphEnabled(false);
this.layer_botscroll = new Konva.Layer();
//多点标记功能
this.layer_info3 = new Konva.Layer();
this.layer_info3.hitGraphEnabled(false);
this.layer_info4 = new Konva.Layer();
this.layer_info4.hitGraphEnabled(false);
this.layer_info5 = new Konva.Layer();
this.layer_info5.hitGraphEnabled(false);
//该层是砖红色的,在超短波模式下代表当前通道真实带宽。
this.layer_gather = new Konva.Layer();
this.layer_gather.hitGraphEnabled(false);
//this.layer_info6 = new Konva.Layer();
//this.layer_info6.hitGraphEnabled(false);
//this.layer_info7 = new Konva.Layer();
//this.layer_info7.hitGraphEnabled(false);
//频点标记 频率尺 标记 三角形 圆形 菱形 dhj 20241215
this.layer_freqpointlable = new Konva.Layer();
this.layer_freqpointlable.hitGraphEnabled(true);
this.layer_white = new Konva.Layer();
this.layer_white.hitGraphEnabled(true);
this.stage.add(this.layer_coor);
this.stage.add(this.layer_wf);
this.stage.add(this.layer_coorFreq);
this.stage.add(this.layer_labelActive);
this.stage.add(this.layer_coorFreqWeel);
this.stage.add(this.layer_label);
this.stage.add(this.layer_map);
this.stage.add(this.layer_mapRuler);
this.stage.add(this.layer_adj);
this.stage.add(this.layer_gather);
this.stage.add(this.layer_white);
//this.stage.add(this.layer_split);//2021.05.07 西部需要拖动修改频谱图大小,李伟添加
this.stage.add(this.layer_instant);
this.stage.add(this.layer_chanel);
this.stage.add(this.layer_botscroll);
this.stage.add(this.layer_cover);
this.stage.add(this.layer_carryline);
this.stage.add(this.layer_info);
this.stage.add(this.layer_info2);
//JC添加make功能
this.stage.add(this.layer_info3);
this.stage.add(this.layer_info4);
this.stage.add(this.layer_info5);
//this.stage.add(this.layer_info6);
this.stage.add(this.layer_freqpointlable);
//this.stage.add(this.layer_info7);
this.initContextMenu();
// this.initLabelsMenu();
this.init();
this.initResize();
}