实现方式一:

将数据(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. python中random的基本用法

    那么怎么使 a 随机生成一个数值呢,来研究一下random的部分程序:python中random模块的几个函数可以随机生成数值,下面咱们看一下random的几个函数的使用方法. random()是不能 ...

  2. 《Windows内核安全与驱动开发》 5.1&5.2 内核与应用方面的编程

    <Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发>  5.1&5.2 内核与应用方面的编程 一.生成控制设备 如果一个驱 ...

  3. APP 框架搭建

    在开发一款app前必须先把框架搭建好,这样能避免代码混乱,多人开发时遇到bug难以解决. 构建MVC整体框架的缺点是会导致VC代码量过大,也存在一些不足.借鉴了网上牛人的思路后,https://www ...

  4. keychain 的学习

    keychain 的使用    http://www.cnblogs.com/ios8/archive/2012/06/25/iOS-keychain.html

  5. ESP8266调试(UDP调试)

    1.设置STA模式 AT+CWMODE=1 2.加入热点 AT+CWJAP="Admin_name","password" 3.开启单路连接 AT+CIPMUX ...

  6. linux google protobuf

    说明: protobuf已经全面迁移到github,地址:https://github.com/google/protobuf 直接下载2.6.1版本:https://github.com/googl ...

  7. 基于iCamera测试模拟摄像头-TVP5150模块小结

    基于iCamera测试模拟摄像头-TVP5150模块小结 首先先认识下模拟摄像头,相信大家都不陌生, CCD模拟摄像头 CMOS模拟摄像头 可以看到,ccd摄像头电路较复杂,接口少,而cmos摄像头, ...

  8. Python3 类与对象之王者荣耀对战小游戏

    王者荣耀对战小游戏 # 定义英雄: 亚瑟 class Arthur: hero_type = 'Tank' def __init__(self, attack_value=164, armor=98, ...

  9. Vmware Workstation虚拟机

    目录 一.虚拟机是什么? 二.虚拟机的作用: 三.虚拟机创建流程 四.新的虚拟机上安装系统 五.虚拟机里添加硬盘 六.磁盘分区 一.虚拟机是什么? 虚拟机指通过软件模拟的具有完整硬件系统功能的.运行在 ...

  10. JS内置对象-Array之splice-删插替

    splice-删除 var arr = [1, 2, 3, 4, 5, 6]; //删除 var delArr = arr.splice(1, 2) console.log(arr); // => ...