背景
【问题描述】我想绘制一个折线图,包含多条折线,每条的数据量大概在1w~10w之间,要求1.可以流畅拖动 2.某些位置可以显示数值 3.放大缩小不会严重卡顿 4.不要收费。
【工具调研】(没记录出处,一般来自用户手册或博客)
- Drawing Visual:不提供布局/事件处理,适合绘制背景或剪贴画
- Live-charts:数据量>2k可能会卡顿
- Scicharts:基本可以满足我的需求,但是收费
解决方案
InteractiveDataDisplay.WPF-v1.0
安装的话直接NuGet安装即可,如果提示缺什么包,就继续装上。
前端:
<Window x:Class="SnapDemo.WavePainter"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d3="clr-namespace:InteractiveDataDisplay.WPF;assembly=InteractiveDataDisplay.WPF"
xmlns:local="clr-namespace:SnapDemo"
mc:Ignorable="d"
Title="WavePainter" Height="400" Width="800">
<Grid Margin="20,30,20,20" x:Name="myGrid">
<d3:Chart BottomTitle="Argument" LeftTitle="Function" PlotHeight="5000" PlotWidth="100">
<Grid>
<d3:LineGraph x:Name="linegraphA" Stroke="Blue" StrokeThickness="1" />
<d3:LineGraph x:Name="linegraphC" Stroke="Green" StrokeThickness="1" />
<d3:LineGraph x:Name="linegraphG" Stroke="Orange" StrokeThickness="1" />
<d3:LineGraph x:Name="linegraphT" Stroke="Red" StrokeThickness="1" />
</Grid>
</d3:Chart>
</Grid>
</Window>
后台:
List<double> xx = new List<double>();
List<double> ya = new List<double>();
List<double> yc = new List<double>();
List<double> yg = new List<double>();
List<double> yt = new List<double>();
...填充数据
this.linegraphA.Plot(xx, ya);
this.linegraphC.Plot(xx, yc);
this.linegraphG.Plot(xx, yg);
this.linegraphT.Plot(xx, yt);
结果
当前可以支持鼠标拖动、滚轮放大和缩小,但是不顺畅,会有一点卡顿。
其他代码存档
这里是没有用到的代码,食之无味弃之不忍。。。所以放在这里。
Drawing Visual
Bitmap b = new Bitmap(1000, 800);
Graphics bg = Graphics.FromImage(b);
bg.Clear(System.Drawing.Color.LightGray);
List<System.Drawing.Point> points = new List<System.Drawing.Point>();
// xx和yc是两个List<double>, 是我的测试数据
for (int i = 0; i < xx.Count; i++) {
points.Add(new System.Drawing.Point((int)xx[i], (int)yc[i]));
}
bg.DrawLines(new System.Drawing.Pen(System.Drawing.Color.Red), points.ToArray());
foreach (var item in points)
{
item.Offset(-10, -10);
bg.FillEllipse(new SolidBrush(System.Drawing.Color.Yellow),
new System.Drawing.Rectangle(item,
new System.Drawing.Size(15, 15)));
item.Offset(5, 5);
bg.DrawString(item.Y.ToString(),new Font("Arial", 6),
new SolidBrush(System.Drawing.Color.Blue),item);
}
bg.Dispose();
b.Save("demo.bmp");