实现方式一:

将数据(Point[])根据索引沿X轴使用虚拟画布进行绘制,每个数据绘制大小为1px * 1px;最终绘制出的宽度等于数据的总长度。标记并存储当前绘制的图为PreviousBitmap; 继续置顶绘制第二组数据,第二组数据绘制完后,将标记的PreviousBitmap作为Image在Y轴距离顶部距离为1px的地方用DrawingContext.DrawImage()方式绘制,以此类推。核心代码如下:

private void DoAddDataArray(Point[] arrPoints)
{
this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
double dPixelWidth = Pixel;
double dContainerWidth = this.VbxContainer.ActualWidth;
double dContainerHeight = this.VbxContainer.ActualHeight;
double dPixelHeight = Pixel/2d;
double dCellHeight = 1;
double dCellWidth = 1; DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawRectangle(new SolidColorBrush(Colors.Blue),
new Pen(), new Rect(0, 0, dPixelWidth, dCellHeight)); // 绘制新数据 for (int i = 0; i < arrPoints.Length; i++)
{
double dCellX = Math.Round(((arrPoints[i].X - MinAxisX) / (MaxAxisX - MinAxisX)) * Pixel);
double dY = arrPoints[i].Y;
Color oColor = this.GetColor(dY);
//drawingContext.DrawRectangle(new SolidColorBrush(oColor),
// new Pen(), new Rect(dCellX, 0, dCellWidth, dCellHeight));
LinearGradientBrush lineBrush = new LinearGradientBrush();
lineBrush.GradientStops.Add(new GradientStop(Colors.Transparent, 0));
lineBrush.GradientStops.Add(new GradientStop(oColor, 0.25));
lineBrush.GradientStops.Add(new GradientStop(oColor, 0.5));
lineBrush.GradientStops.Add(new GradientStop(oColor, 0.75));
lineBrush.GradientStops.Add(new GradientStop(Colors.Transparent, 1));
drawingContext.DrawRectangle(lineBrush, new Pen(), new Rect(dCellX-1, 0, dCellWidth + 2, dCellHeight));
} // 绘制历史数据
if (this.PreviousBitmap != null)
drawingContext.DrawImage(this.PreviousBitmap, new Rect(0, dCellHeight, dPixelWidth, dPixelHeight));
drawingContext.Close(); // 生成图像处理
RenderTargetBitmap rtbCurrent = new RenderTargetBitmap((int)dPixelWidth,
(int)dPixelHeight, 96, 96, PixelFormats.Pbgra32);
rtbCurrent.Render(drawingVisual); this.PreviousBitmap = rtbCurrent; // 当前绘制的存为历史,下次绘制时直接调用
this.ImgMain.Source = rtbCurrent; // 显示绘制的图像
}));
}

运行效果

实现方式二:

将数据(Point[])根据索引沿X轴使用虚拟画布进行绘制,每个数据绘制大小为1px * 1px;最终绘制出的宽度等于数据的总长度。创建一个Rectangle,将绘制的图赋值给Rectangle.Fill属性,将绘制过程中不断创建的Rectangle插入控件Stackpanel的首位。核心代码如下:

private void DoAddDataArray(Point[] arrPoints)
{
this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
double dPixelWidth = Pixel;
double dContainerWidth = this.VbxContainer.ActualWidth;
double dContainerHeight = this.VbxContainer.ActualHeight;
double dPixelHeight = Pixel / 2d; DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawRectangle(new SolidColorBrush(Colors.Blue),
new Pen(), new Rect(, , dPixelWidth, )); // 绘制新数据
double dCellHeight = ;
double dCellWidth = ;
for (int i = ; i < arrPoints.Length; i++)
{
double dCellX = Math.Round(((arrPoints[i].X - MinAxisX) / (MaxAxisX - MinAxisX)) * Pixel);
double dY = arrPoints[i].Y;
Color oColor = this.GetColor(dY);
//drawingContext.DrawRectangle(new SolidColorBrush(oColor),
// new Pen(), new Rect(dCellX, 0, dCellWidth, dCellHeight));
LinearGradientBrush lineBrush = new LinearGradientBrush();
lineBrush.GradientStops.Add(new GradientStop(Colors.Transparent, ));
lineBrush.GradientStops.Add(new GradientStop(oColor, 0.25));
lineBrush.GradientStops.Add(new GradientStop(oColor, 0.5));
lineBrush.GradientStops.Add(new GradientStop(oColor, 0.75));
lineBrush.GradientStops.Add(new GradientStop(Colors.Transparent, ));
drawingContext.DrawRectangle(lineBrush, new Pen(), new Rect(dCellX - 0.5, , dCellWidth + , dCellHeight));
}
drawingContext.Close(); // 生成图像处理
RenderTargetBitmap rtbCurrent = new RenderTargetBitmap((int)dPixelWidth, (int), , , PixelFormats.Pbgra32);
rtbCurrent.Render(drawingVisual); Rectangle rect = new Rectangle();
rect.Width = Pixel;
rect.Height = ;
rect.Fill = new ImageBrush(rtbCurrent);
// SpContainers ---- Stackpanel
this.SpContainers.Children.Insert(, rect);
if (this.SpContainers.Children.Count > )
this.SpContainers.Children.RemoveAt();
}));
}

运行效果:

相对而言,方式二由于不断插入新的Rectangle。下移效果为控件位置变化所呈现,不像方式一是一张完整图,故画质欠缺。

性能和测试: 

采用Timer生成随机数据进行测试。10毫秒1组,每组1000个数据点。 相当于每秒绘制10万个点。

测试时在Release模式下,开启多个子模块,性能勉强能接受。

环境:

语言: C#

工程:WPF

工具:Visual Studio 2017

系统:Windows

第三方插件:无

            微信扫码下载源代码:

WPF数据可视化-瀑布图的更多相关文章

  1. WPF数据可视化-趋势图

    环境: 系统: Window 7以上: 工具:VS2013及以上. 研发语言及工程: C# WPF 应用程序 效果: ​ ​ 简介: 不需要调用第三方Dll, 仅仅在WPF中使用贝塞尔曲线,不到500 ...

  2. 手把手教你做一个python+matplotlib的炫酷的数据可视化动图

    1.效果图 2.注意: 上述资料是虚拟的,为了学习制作动图,构建的. 仅供学习, 不是真实数据,请别误传. 当自己需要对真实数据进行可视化时,可进行适当修改. 3.代码: #第1步:导出模块,固定 i ...

  3. 基于matplotlib的数据可视化 - 热图imshow

    热图: Display an image on the axes. 可以用来比较两个矩阵的相似程度 mp.imshow(z, cmap=颜色映射,origin=垂直轴向) imshow( X, cma ...

  4. g2蚂蚁数据可视化折线图,点位坐标label 图形文本设置

    应用g2可视化插件画了个粉丝分析图 要求显示如图所见的节点参数,查看文档蚂蚁图形文本设置,得知需要引入如下代码: chart.point().position('update*praises').la ...

  5. flask+sqlite3+echarts2+ajax数据可视化--静态图

    结构: /www | |-- /static | | | |-- echarts.js(当然还有echarts原dist目录下的文件(夹)) | |-- /templates | | | |-- in ...

  6. 气象netCDF数据可视化分析

    气象netCDF数据可视化分析 2019-09-19 15:34:22 自走棋 阅读数 162更多 分类专栏: web前端   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载 ...

  7. 用Python的Plotly画出炫酷的数据可视化(含各类图介绍,附代码)

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 我被狗咬了 在谈及数据可视化的时候,我们通常都会使用到matplo ...

  8. Webstorm+Webpack+echarts构建个性化定制的数据可视化图表&&两个echarts详细教程(柱状图,南丁格尔图)

    Webstorm+Webpack+echarts   ECharts 特性介绍 ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(I ...

  9. [原创.数据可视化系列之五]韩国"萨德"系统防御图

    自从7月8日美国和韩国共同宣布将在韩国部署萨德反导系统后,韩国国内对此事的巨大争议以及本地区一些国家的强烈不满情绪在持续发酵.“萨德”(THAAD)全称“末段高空区域防御系统”,是美国导弹防御局和美国 ...

随机推荐

  1. 《Windows内核安全与驱动开发》 3.1 字符串操作

    <Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 3.1 字符串操作 一.字符串的初始化 1. 判断下列代码为什么会蓝屏? U ...

  2. 动态规划--最长上升子序列(LIS)的长度

    l例如:对于[3,1,4,2,5],最长上升子序列的长度是3 arr = [3,1,4,5,9,2,6,5,0] def lis(arr): #dp[i]表示第i个位置的值为尾的数组的最长递增子序列的 ...

  3. 在phpstudy集成环境下的nginx服务器下配置url重写

    直接在对应的vhosts.conf配置文件的location / {}中添加以下内容: location / { index index.html index.htm index.php; #auto ...

  4. MongoDB的第二天(更新,删除,查询,索引)

    Mongodb的更新方式有三种 update函数,操作符更新,save函数 update: 语法格式:db.COLLECTION_NAME.update({查询条件},{更新内容},{更新参数(可选) ...

  5. [TimLinux] Python 类型与运算

    1. 内建(built-in)数据类型种类 数字类型:int(), float() 顺序(sequence): 字符串:str() 元祖:tuple() 列表:list() 字典:dict() 集合: ...

  6. HDU3896 Greatest TC(双联通分量+倍增)

    Problem Description TC (Tian Chao) is magical place, as you all know...The railways and the rail-sta ...

  7. 2018HDU多校训练-3-Problem G. Interstellar Travel

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6325                                   Interstellar Tra ...

  8. Linux中Postfix反病毒和垃圾邮件(十)

    amavisd-new amavisd-new呼叫器是一个连接MTA和内容检测工具(诸如病毒扫描工具和SpamAssassin)的高性能接口程序,使用perl语言写成.它一般通过SMTP.ESMTP或 ...

  9. UWP 中的全局异常处理

    问题 在开发一款应用的过程中,我们开发者很难考虑到所有问题,往往会忘记处理一些可能发生的异常.随之而来的结果就是用户使用过程中接连不断的崩溃.所以,我们有必要处理所有未被我们处理的异常. 本文介绍了 ...

  10. 轻松构建基于 Serverless 架构的弹性高可用音视频处理系统

    前言 随着计算机技术和 Internet 的日新月异,视频点播技术因其良好的人机交互性和流媒体传输技术倍受教育.娱乐等行业青睐,而在当前, 云计算平台厂商的产品线不断成熟完善, 如果想要搭建视频点播类 ...