大量数据 折线图

前言

以曲线图的方式展示数据,是一个永远都躲不开的事。

之前做过一些曲线图、柱状图、饼图、地图等,都是用的第三方控件或者 API,也试过用 GDI+ 自己绘制。

第三方控件功能丰富、美观,开发周期短,但是性能跟不上。GDI+ 绘制性能极高,可以在极短的时间绘制十万级的图,但是所有功能都要自己代码实现,开发周期很长。

第三方控件比较常见的有 MSChart、DevExpress、TreeChart、ZedGraph、DotNetCharting,数据量一大就开始卡顿。

现在使用 echarts 比较好的解决了大量数据卡顿的问题。

由于 .net 自带的 webBrowser 控件使用 ie 浏览器解析页面,在兼容、性能方面都太欠缺,所以使用 cefSharp 加载 Chrome 解析页面。

参考:https://www.runner.ink/2020/05/03/winform-use-cefsharp-chrome/

Html

方便观察我把html和js放在一起:

<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <title>ECharts</title>
	<!-- 引入 echarts.js -->
    <script src="echarts.js"></script>
</head>
<body>
    <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
    <div id="main" style="width: 700px;height:190px;"></div>
    <script type="text/javascript">
	
    var myChart = echarts.init(document.getElementById('main'));	
    var data= [];//空数组
	
    var option = 
    {
	  grid: {  
		  left: '3%',  
		  right: '7%',   
		  containLabel: true  
	        },
	  tooltip: 
                {
		   trigger: 'axis'
                },
	  title: 
                {
		   text: 'Pitch'
		},
	  xAxis: 
		{
		     name: '时间',
		     type: 'category'
		},
		yAxis: 
		{
		     name: '值',
		     type: 'value',
		     min: -30,
                     max: 30,
		     minorSplitLine: 
		     {
			  show: true,
			  lineStyle: 
			  {
				color: '#ddd'
			  }
		     }
		},
		series: [{
		    name: 'Pitch',
			data: data,
			type: 'line',
			showSymbol: false
		}],
		toolbox: 
		{
			feature: 
			{
				restore: {}
			}
		},
		dataZoom: [{
			show: true,
			type: 'inside',
			filterMode: 'none',
			xAxisIndex: [0]
		}, 
		{
			show: true,
			type: 'inside',
			filterMode: 'none',
			yAxisIndex: [0]
		}]
	};

        myChart.setOption(option);
	
        //实时调用,实现动态效果
	function AddPoint(x,y1,y2,y3,y4,y5)
	{
	    data.push([x,y1]);
	    data.push([x + 1,y2]);
	    data.push([x + 2,y3]);
	    data.push([x + 3,y4]);
	    data.push([x + 4,y5]);

	    myChart.setOption({series: [{ data: data}]});
	};
	
        //更新Echart大小适应应用缩放
	function changeWH(width, height)
	{
	   var div = document.getElementById('main');
	   
	   div.style.width = width + "px";
	   div.style.height = height + "px";
	   myChart.resize();
	};
	
        //一次性绘制大量数据点
	function ShowImage(strT,strV)
	{	
	    var arrT = JSON.parse(strT);
	    var arrV = JSON.parse(strV);
	    data.length = 0; //清空历史数据
	    for(var i = 0; i< arrT.length; i++)
	    {
	       data.push([arrT[i],arrV[i]]);
            }	
	    myChart.setOption({series: [{ data: data}]});
	};
	</script>
</body>
</html>

C#

一次性绘图:

//声明数组
List<string> timeList = new List<string>();
//添加数据
timeList.Add("2020-05-04 00:00:00:0000");
timeList.Add("2020-05-04 00:00:00:0001");
timeList.Add("2020-05-04 00:00:00:0002");
//序列化成Json
string strTime = JsonConvert.SerializeObject(timeList);
//传递给页面脚本
chromeBrowser.ExecuteScriptAsync("ShowTime('" + strTime + "')");

上图像,大概是 2w 个点,缩放毫无压力:

动态绘图:

就不贴代码了,原理就是定时调用 js 里 AddPoint(x,y1,y2,y3,y4,y5) 函数,把新的数据点添加到曲线里。

这里注意两点:1,可以在 js 里判断数据点的个数,大于多少个就 shift() 第一个点,曲线就波动起来了。2,这里我一次性传递5个点进去绘图,是因为数据采样频率达到了100HZ,如果一次传一个点,那么每 10 毫秒就要渲染一下图像,cpu 的压力非常巨大,当数据量达到 2000 个点的时候就开始出现卡顿,3000 个点的时候,一旦缩放就会出现明显的卡顿。

粗略算了一下,以 50 毫秒的速度渲染,数据量达到 14000 个点的时候,才开始出现卡顿。

上才艺,哦不,上图:

可以看到 1w 个数据点实时刷新带缩放仍然不卡顿,这放在主流的第三方 winform 图表控件上是不敢想的。

 

最后

也试了下 HighChart,和 Echarts 一样,也是纯 Javascript 图表库,个人感觉在静态数据的展示上优于 Echarts,更加美观,种类也更多。

官方甚至直接放了一个 5w 个数据点带缩放的样例:

https://www.highcharts.com.cn/demo/highcharts/line-boost

但是据我实测,在动态数据的渲染上, Echarts 更胜一筹。

发表评论