websocket+echarts+canvas实时分布式光纤振动系统的实时曲线图跟瀑布图

功能需求背景:

分布式光纤振动系统DVS,需要实现实时频谱曲线图跟瀑布图;DVS系统能够感知光纤上的振动,DVS底层系统把一根光缆分成N个点(可看成N个传感器),假设一根40KM的光缆,我们按5m一个点位,那么就可以采集到8000个点的数据信息。在一个周期内把这些点位的振动数值进行采集,就可以绘制出一个周期内的频谱图,频谱曲线图效果如下:

b10000.png

当我们定期把这8000个点位的数据值根据其振动数值的大小绘制成不同的颜色(值大就颜色深,值小就颜色浅)并显示出来,就形一副瀑布图。效果如下:

b10001.png

功能实现:

1、曲线图的实现. 曲线图,我们直接采用echarts进行绘制,option配置如下:

refreshData(data){
    var option = {
          animation: false,
          title: {
              text: '',
              left: 10
          },
          toolbox: {
              show: false,
              feature: {
                  dataZoom: {
                      yAxisIndex: false
                  },
                  saveAsImage: {
                      pixelRatio: 2
                  }
              }
          },
          tooltip: {
              trigger: 'axis',
              axisPointer: {
                  type: 'shadow'
              }
          },
          grid: {
              backgroundColor:'#ccc',
              show: true,
              top: 30,
              left: 40,
              right: 10,
              bottom: 60
          },
          dataZoom: [{
              type: 'inside'
          }, {
              type: 'slider',
              xAxisIndex: [0, 1]
          }],
          xAxis: [
          {

              data: data.categoryData,

              splitLine: {
                  show: false
              },
              splitArea: {
                  show: false
              }
          }
          ],
          yAxis: {
              show: true,
              max: 5000,
              min: 10,
              silent: false,
              splitArea: {
                  show: false
              }
          },
          series: [{
              type: 'bar',
              data: data.valueData,
              large: true
          }]
      }; 
      ...
}

绘制出来的效果如图:

2、瀑布图效果的实现

瀑布图可以考虑直接用echarts的热力图来实现,不过经过测试,热力图在快速刷新下效果不是很好,非常卡。所以只能采用canvas进行自己绘制了。canvas是一个画布,绘制算法是什么样的呢?

我们定期把这8000个点位的数据值根据其大小绘制成不同的颜色(值大就颜色深,值小就颜色浅)并显示出来。就形一副瀑布图。

怎么根据值(整形)获取不同样的颜色?我们这里用colormap这个现成的npm模块。 生成72个颜色。然后通过下标0,1,2...71我们就可以取到对应的颜色。每一个颜色是一个数组:[255,255,255,1] 代表红,绿,蓝的颜色值跟alpha值。

b10002.png

获取颜色值代码:

this.colormap = colormap({
          colormap: 'jet',
          nshades: 72,
          format: 'rba',
          alpha: 1
        })
映射振动值到具体颜色的下标。
squeeze (data, outMin, outMax) {
      if (!data) {
        return outMin
      }
      if (data <= this.minDb) {
        return outMin
      } else if (data >= this.maxDb) {
        return outMax
      } else {
        return Math.round((data - this.minDb) / (this.maxDb - this.minDb) * outMax)
      }
}

data为我们的振动值,outMin为colormap颜色其始下标,outMax为colormap颜色值的终止下标。minDb为data的范围,最小值,maxDb为data的最大值(可以设置比最大值大一些)。 好,下面我们为8000个点依次着色,并绘制到canvas画布上。代码如下。

var n = 8000;
const imgData = _this.waterFallCtx.createImageData(n, 1);//创建一个宽8000,高1像素的图。
for (let i = 0; i < imgData.data.length; i += 4) {
    const cindex = _this.squeeze(data['valueData'][i / 4], 0, 71)//获取颜色下标
    const color = _this.colormap[cindex]//获取颜色
    imgData.data[i + 0] = color[0]
    imgData.data[i + 1] = color[1]
    imgData.data[i + 2] = color[2]
    imgData.data[i + 3] = 255
}
_this.waterFallCtx.drawImage(_this.waterFallCtx.canvas, 0, 0, n, 199,  0, 1, n, 199)//把画布往下移一行,留出顶部空白。
_this.waterFallCtx.putImageData(imgData, 0, 0)//把顶部留出的一行画上刚刚生成的图片
_this.ctx.drawImage(_this.waterFallCtx.canvas, 0, 0, n, 200);//显示到界面上。

通过websocket实时接收数据,并设置到曲线图跟 瀑布图上。

var _this = this
var ws = new WebSocket('ws://xxxx:8082/dvs/xxx/ui');
// Web Socket 已连接上,使用 send() 方法发送数据
// 这里接受服务器端发过来的消息
ws.onmessage = function(e) {
    _this.parseBlob(e.data, function (e) {
        _this.$refs.waterFall.addData(e);
    })
}

这里的数据我们采用二进制输出,所以获取到的数据是二进制,需要解析一下才能拿到8000个点的数据。

parseBlob(blob, callback) {
      var _this = this
      var reader = {
        readAs: function(type,blob,cb){
        var r = new FileReader();
        r.onloadend = function(){
            if(typeof(cb) === 'function') {
              cb.call(r,r.result);
            }
          }
          try{
            r['readAs'+type](blob);
          }catch(e){}
        }
      }

      var shortVar, intVar, stringVar;

      reader.readAs('ArrayBuffer',blob.slice(6, blob.size-2),function(result){
        shortVar = new Int16Array(result);
        var list = [], val = [];
        for(var i=0; i<shortVar.length; i ++) {
          list.push(i)
          val.push(shortVar[i])
        }
        var obj = {
          'categoryData': list,
          'valueData': val
        }
        _this.refreshData(obj)//绘制曲线图
        callback(obj)
      });
    },

最终效果:

b10003.png

点击查看效果视频

分类: 分布式光纤振动DVS   标签: canvas瀑布图, dvs实时曲线, dvs瀑布图, 瀑布图, 频谱曲线图    更新日期: Jun 24, 2021


联系电话 13427781756