前言
以曲线图的方式展示数据,是一个永远都躲不开的事。
之前做过一些曲线图、柱状图、饼图、地图等,都是用的第三方控件或者 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 更胜一筹。