WPF数据可视化-瀑布图
实现方式一:
将数据(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数据可视化-瀑布图的更多相关文章
- WPF数据可视化-趋势图
环境: 系统: Window 7以上: 工具:VS2013及以上. 研发语言及工程: C# WPF 应用程序 效果: 简介: 不需要调用第三方Dll, 仅仅在WPF中使用贝塞尔曲线,不到500 ...
- 手把手教你做一个python+matplotlib的炫酷的数据可视化动图
1.效果图 2.注意: 上述资料是虚拟的,为了学习制作动图,构建的. 仅供学习, 不是真实数据,请别误传. 当自己需要对真实数据进行可视化时,可进行适当修改. 3.代码: #第1步:导出模块,固定 i ...
- 基于matplotlib的数据可视化 - 热图imshow
热图: Display an image on the axes. 可以用来比较两个矩阵的相似程度 mp.imshow(z, cmap=颜色映射,origin=垂直轴向) imshow( X, cma ...
- g2蚂蚁数据可视化折线图,点位坐标label 图形文本设置
应用g2可视化插件画了个粉丝分析图 要求显示如图所见的节点参数,查看文档蚂蚁图形文本设置,得知需要引入如下代码: chart.point().position('update*praises').la ...
- flask+sqlite3+echarts2+ajax数据可视化--静态图
结构: /www | |-- /static | | | |-- echarts.js(当然还有echarts原dist目录下的文件(夹)) | |-- /templates | | | |-- in ...
- 气象netCDF数据可视化分析
气象netCDF数据可视化分析 2019-09-19 15:34:22 自走棋 阅读数 162更多 分类专栏: web前端 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载 ...
- 用Python的Plotly画出炫酷的数据可视化(含各类图介绍,附代码)
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 我被狗咬了 在谈及数据可视化的时候,我们通常都会使用到matplo ...
- Webstorm+Webpack+echarts构建个性化定制的数据可视化图表&&两个echarts详细教程(柱状图,南丁格尔图)
Webstorm+Webpack+echarts ECharts 特性介绍 ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(I ...
- [原创.数据可视化系列之五]韩国"萨德"系统防御图
自从7月8日美国和韩国共同宣布将在韩国部署萨德反导系统后,韩国国内对此事的巨大争议以及本地区一些国家的强烈不满情绪在持续发酵.“萨德”(THAAD)全称“末段高空区域防御系统”,是美国导弹防御局和美国 ...
随机推荐
- Good Bye 2017 A B C
Good Bye 2017 A New Year and Counting Cards 题目链接: http://codeforces.com/contest/908/problem/A 思路: 如果 ...
- gulp+webpack+angular1的一点小经验(第一部分gulp与webpack的整合)
时间匆匆如流水继上周熟悉了gulp的初步安装与环境配置以后,我的项目又进入了新的阶段! 这篇文章将把我这一周遇到的一些问题,以及解决的方式做一个小小的总结,不一定记的完整,但都是个人的一点经验,分享给 ...
- 关于非阻塞I/O、多路复用、epoll的杂谈
本文主要是想解答一下这样几个问题: - 什么是非阻塞I/O - 非阻塞I/O和异步I/O的区别 - epoll的工作原理 文件描述符 文件描述符在本文有多次出现,难免有的朋友不太熟悉,有必要简单说明一 ...
- iOS 网络基本剖析
一.网络通信的本质 数据传输,数据交换 Client <======> 服务器 二.HTTP.TCP,IP.UDP.Socket关系刨析 Socket:套接字,是一个用于网络传输 ...
- python笔记02
day02笔记记录 一.今日摘要 循环.字符串格式化.运算符.编码.博客. 二.内容回顾 (一)计算机基础 计算机由硬件和软件组成.传统计算机的硬件一般有输入单元.输出单元,算数逻辑单元.控制单元及记 ...
- 【解决】http: server gave HTTP response to HTTPS client
[问题]上传镜像到私有仓库时报错 $ docker push xxx.xxx.xxx.xxx:5000/java-8 The push refers to repository [xxx.xxx.xx ...
- nitacm第十六届浙江大学宁波理工学院程序设计大赛总结
校赛时间:2019.11.30周六下午12:00-16:00 重现赛链接:https://ac.nowcoder.com/acm/contest/2995#question 体验: 11点多到达石鳞大 ...
- CoderForces999F-Cards and Joy
F. Cards and Joy time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- TypeScript - 泛型
什么是泛型 官方是这样介绍的: 软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性. 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵 ...
- js原生实现链式动画效果
// 1. css样式 div { width: 100px; height: 100px; background: olivedrab; position: absolute; left: 0px; ...