原文:WPF 曲线图表控件(自制)(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/koloumi/article/details/77521872

    如果还有不懂的请去资源区下载控件包含所有源码

http://download.csdn.net/download/koloumi/9947692

接下来将代码上的。

界面调整部分的代码函数

    还有一个重要的函数就是控件的MyChart_SizeChanged事件。
/// <summary>
/// 尺寸改变
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MyChart_SizeChanged(object sender, SizeChangedEventArgs e)
{
Size newsize = e.NewSize;
if(!e.WidthChanged)
{
this.Width = newsize.Width;
}
if(!e.HeightChanged)
{
this.Height = newsize.Height;
}
AdjustSize();
AdjustScale();
AdjustLines();
AdjustLinesAndPoints();
}
    接下来是先看下定义的属性:
/// <summary>
/// 数据集
/// </summary>
private Dictionary<string, DrawData> _data = new Dictionary<string, DrawData>();
/// <summary>
/// 坐标原点
/// </summary>
private Point _origPoint = new Point();
/// <summary>
/// X轴上的文字
/// </summary>
private List<TextBlock> _xTip = new List<TextBlock>();
/// <summary>
/// Y轴上的文字
/// </summary>
private List<TextBlock> _yTip = new List<TextBlock>();
/// <summary>
/// X轴的区间
/// </summary>
private VectorChart2 _xLimt = new VectorChart2(double.MaxValue, double.MinValue);
/// <summary>
/// Y轴的区间
/// </summary>
private VectorChart2 _yLimt = new VectorChart2(double.MaxValue, double.MinValue);
/// <summary>
/// 每个像素映射为多少距离
/// </summary>
private VectorChart2 _everyDisForPiexl = new VectorChart2();
/// <summary>
/// 缩放中心点的偏移
/// </summary>
private VectorChart2 _centerOffect = new VectorChart2(0, 0);
/// <summary>
/// 当前线的缩放比例
/// </summary>
private Vector4 _currentLinesScale = new Vector4(1, 1, 1, 1);
/// <summary>
/// 每个刻度之间的间隔
/// </summary>
private static double _everyDis = 30;
    在这个控件上我们将每个刻度的间隔直接定死,这样有需要的时候直接修改刻度上的数值,而不用去移动刻度。如果尺寸变大只要增加刻度线,减少反之。
在控件中用到的数据结构
/// <summary>
/// 向量
/// </summary>
public struct VectorChart2
{
public double Vec1; public double Vec2; public VectorChart2(double v1, double v2)
{
this.Vec1 = v1;
this.Vec2 = v2;
}
/// <summary>
/// Point 转换VectorChart2
/// </summary>
/// <param name="p"></param>
public static implicit operator VectorChart2(Point p)
{
return new VectorChart2(p.X, p.Y);
}
/// <summary>
/// 乘法
/// </summary>
/// <param name="v1"></param>
/// <param name="ratio"></param>
/// <returns></returns>
public static VectorChart2 operator * (VectorChart2 v1, double ratio)
{
return new VectorChart2(v1.Vec1 * ratio, v1.Vec2 * ratio);
}
}
/// <summary>
/// 4维向量
/// </summary>
public struct Vector4
{
/// <summary>
/// 空
/// </summary>
public static Vector4 Empty = new Vector4() { _isEmpty = true }; public double Vec1; public double Vec2; public double Vec3; public double Vec4;
/// <summary>
/// 是否为空数据
/// </summary>
private bool _isEmpty; public Vector4(double Vec1, double Vec2, double Vec3, double Vec4)
{
this.Vec1 = Vec1;
this.Vec2 = Vec2;
this.Vec3 = Vec3;
this.Vec4 = Vec4;
_isEmpty = false;
} /// <summary>
/// 重载等号运算符
/// </summary>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
public static bool operator ==(Vector4 v1, Vector4 v2)
{
if (v1.Vec1 == v2.Vec1 && v1.Vec2 == v2.Vec2 && v1.Vec3 == v2.Vec3 && v1.Vec4 == v2.Vec4 && v1._isEmpty == v2._isEmpty)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 重载
/// </summary>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
public static bool operator !=(Vector4 v1, Vector4 v2)
{
return !(v1 == v2);
} public override bool Equals(object obj)
{
return base.Equals(obj);
} public override int GetHashCode()
{
return base.GetHashCode();
}
}
/// <summary>
/// 绘图数据
/// </summary>
public class DrawData : IDisposable
{
/// <summary>
/// 线
/// </summary>
public Polyline Line;
/// <summary>
/// 线的标记点
/// </summary>
public List<Ellipse> Points = new List<Ellipse>();
/// <summary>
/// 源数据集合
/// </summary>
public ObservableCollection<Point> Ps = null;
/// <summary>
/// 极值
/// </summary>
public Vector4 Vec4 = Vector4.Empty;
/// <summary>
/// 提示
/// </summary>
public LineTitle LineTitle = new LineTitle(); public DrawData()
{ } ~DrawData()
{
this.Dispose();
}
#region IDisposable Support
private bool disposedValue = false; // 要检测冗余调用 protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)。
Line = null;
Ps = null;
Points = null;
LineTitle = null;
} // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
// TODO: 将大型字段设置为 null。 disposedValue = true;
}
} // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
// ~DrawData() {
// // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
// Dispose(false);
// } // 添加此代码以正确实现可处置模式。
public void Dispose()
{
// 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
Dispose(true);
// TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
GC.SuppressFinalize(this);
}
#endregion
}
调整曲线 刻度(直接修改)部分:

然后是调整所有绘图区的尺寸:

极值的调整 这里乘以0.15 是为了扩大上限 让初始曲线能够包括在视图中。

还有曲线刻度的添加式修改:(因为增加删除速度比较慢,所以只在有必要的时候调用这个,比如尺寸改变的时候,平时直接修改刻度即可)
/// <summary>
/// 调整刻度\网格线(删除重新添加)
/// </summary>
protected void AdjustScale()
{
//if (!IsHaveLine) return;
if (X_Axis.Width == 0 || X_Axis.Height == 0 || X_Axis.Width == double.NaN || X_Axis.Height == double.NaN) return;
//if (GridLines.Width == 0 || GridLines.Height == 0 || GridLines.Width == double.NaN || double.IsNaN(GridLines.Height)) return;
///清除X轴的刻度
if (X_Axis.Children.Count > 1)
{
X_Axis.Children.RemoveRange(1, X_Axis.Children.Count - 1);
}
///清除Y轴的刻度
if (Y_Axis.Children.Count > 1)
{
Y_Axis.Children.RemoveRange(1, Y_Axis.Children.Count - 1);
}
///清除网格线
GridLines.Children.Clear();
///清除刻度线的提示文字
_xTip.Clear();
_yTip.Clear(); ///添加X轴的
for (double i = _origPoint.X; i < X_Axis.Width; i += _everyDis)
{
Line x_scale = new Line();
x_scale.StrokeThickness = 2;
x_scale.Stroke = new SolidColorBrush(Colors.Black);
x_scale.StrokeStartLineCap = PenLineCap.Round;
x_scale.StrokeEndLineCap = PenLineCap.Round;
x_scale.Width = 4;
x_scale.Height = 20;
x_scale.X1 = 2;
x_scale.Y1 = 4;
x_scale.X2 = 2;
x_scale.Y2 = x_scale.Height;
Canvas.SetLeft(x_scale, i);
Canvas.SetTop(x_scale, 0);
X_Axis.Children.Add(x_scale);
///网格线
GridLines.Children.Add(GetGridLine(new Point(i - 2, 0), false, GridLinesArea.Vec2));
//double.IsNaN(GridLines.Height) ? GridLines.ActualHeight : GridLines.Height
///添加提示文字
TextBlock block = new TextBlock();
block.FontSize = 10;
block.Text = i.ToString();
Canvas.SetLeft(block, i);
Canvas.SetTop(block, 25);
_xTip.Add(block);
X_Axis.Children.Add(block);
}
///添加Y轴的
for (double i = _origPoint.Y; i < Y_Axis.Height; i += _everyDis)
{
Line y_scale = new Line();
y_scale.StrokeThickness = 2;
y_scale.Stroke = new SolidColorBrush(Colors.Black);
y_scale.StrokeStartLineCap = PenLineCap.Round;
y_scale.StrokeEndLineCap = PenLineCap.Round;
y_scale.Width = 20;
y_scale.Height = 4;
y_scale.X1 = 4;
y_scale.Y1 = 2;
y_scale.X2 = y_scale.Width;
y_scale.Y2 = 2;
Canvas.SetBottom(y_scale, i + 1);
Canvas.SetRight(y_scale, 2);
Y_Axis.Children.Add(y_scale);
///网格线
GridLines.Children.Add(GetGridLine(new Point(i - 2, 0), true, GridLinesArea.Vec1));
//double.IsNaN(GridLines.Width) ? GridLines.ActualWidth : GridLines.Width)
///添加提示文字
TextBlock block = new TextBlock();
block.FontSize = 10;
block.Text = i.ToString();
Canvas.SetBottom(block, i);
Canvas.SetRight(block, 10);
_yTip.Add(block);
Y_Axis.Children.Add(block);
} }
调整线和点:(主要是,缩放和拖动)

调整线和点的大小比例AdjustLinesAndPointsSize 这个函数可以删掉,后来发现没有用。

鼠标滚轮事件:
/// <summary>
/// 鼠标滚轮事件
/// </summary>
/// <param name="e"></param>
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
base.OnMouseWheel(e);
VectorChart2 curPDraw = (VectorChart2)e.GetPosition(Draw);
VectorChart2 curPLinesAndPoint = (VectorChart2)e.GetPosition(DrawLineAndPoint); double delta = 1;
if(e.Delta >= 120)
{
delta = 1.2;
}
else if(e.Delta <= -120)
{
delta = (double)5 / (double)6;
}
if (IsXZoom)
{
DrawLineAndPoint.Width *= delta;
curPDraw.Vec1 *= delta;
curPLinesAndPoint.Vec1 *= delta;
}
if (IsYZoom)
{
DrawLineAndPoint.Height *= delta;
curPDraw.Vec2 *= delta;
curPLinesAndPoint.Vec2 *= delta;
} _currentLinesScale.Vec4 *= delta;
//Canvas.SetLeft(DrawLineAndPoint, curPDraw.Vec1 - curPLinesAndPoint.Vec1);
//Canvas.SetBottom(DrawLineAndPoint, -(DrawArea.Vec2 - (curPLinesAndPoint.Vec2 - curPDraw.Vec2))); ///调整刻度
AdjustLines(); AdjustLinesAndPoints();
}
重置按钮:



鼠标移动的时候计算移动的差值然后调用该函数:



获取偏移量函数:

/// <summary>
/// 获取偏移量
/// </summary>
/// <returns></returns>
protected VectorChart2 GetOffectValue(VectorChart2 offectValue)
{
return new VectorChart2( -offectValue.Vec1 * _everyDisForPiexl.Vec1, offectValue.Vec2 * _everyDisForPiexl.Vec2);
}
至此全部结束 如果还有不懂的请去资源区下载控件包含所有源码

http://download.csdn.net/download/koloumi/9947692

WPF 曲线图表控件(自制)(二)的更多相关文章

  1. WPF 曲线图表控件(自制)(一)

    原文:WPF 曲线图表控件(自制)(一) 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/koloumi/article/details/775092 ...

  2. WPF Visifire 图表控件

    Visifire WPF 图表控件 破解 可能用WPF生成过图表的开发人员都知道,WPF虽然本身的绘图能力强大,但如果每种图表都自己去实现一次的话可能工作量就大了, 尤其是在开发时间比较紧的情况下.这 ...

  3. C# WPF DevExpress 图表控件之柱状图

    说明:DevExpress版本是17.1.VS是2015. XAML: <!--#region 图表控件--> <dxc:ChartControl x:Name="char ...

  4. 【WPF】 OxyPlot图表控件学习

    最近在学习OxyPlot图表控件,一些基本的学习心得,在这里记录一下,方便以后进行查找.   一.引用 OxyPlot控件可以直接在VS的 " Nuget " 里面下载   选择: ...

  5. Visifire For WPF 图表控件 如何免费

    可能用WPF生成过图表的开发人员都知道,WPF虽然本身的绘图能力强大,但如果每种图表都自己去实现一次的话可能工作量就大了, 尤其是在开发时间比较紧的情况下.这时候有必要借助一种专业的图表工具. Vis ...

  6. 二十六、【开源框架】EFW框架Winform前端开发之Grid++Report报表、条形码、Excel导出、图表控件

    回<[开源]EFW框架系列文章索引>        EFW框架源代码下载V1.2:http://pan.baidu.com/s/1hcnuA EFW框架实例源代码下载:http://pan ...

  7. echart图表控件配置入门(二)常用图表数据动态绑定

    上一节 <echart图表控件配置入门(一)>介绍了echarts图表控件的入门配置,使开发人员可以快速搭建出一个静态的图表.但是在实际开发过程这还是不够的,不可能所有的图表控件都是静态数 ...

  8. 深入理解MVC C#+HtmlAgilityPack+Dapper走一波爬虫 StackExchange.Redis 二次封装 C# WPF 用MediaElement控件实现视频循环播放 net 异步与同步

    深入理解MVC   MVC无人不知,可很多程序员对MVC的概念的理解似乎有误,换言之他们一直在错用MVC,尽管即使如此软件也能被写出来,然而软件内部代码的组织方式却是不科学的,这会影响到软件的可维护性 ...

  9. WPF 4 DataGrid 控件(进阶篇二)

    原文:WPF 4 DataGrid 控件(进阶篇二)      上一篇<WPF 4 DataGrid 控件(进阶篇一)>中我们通过DataGridTemplateColumn 类自定义编辑 ...

随机推荐

  1. 【例题5-6 UVA 540 】Team Queue

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 用两个队列模拟就好. 记录某个队在不在队列里面. 模拟 [错的次数] 在这里输入错的次数 [反思] 在这里输入反思 [代码] #in ...

  2. swift项目第二天:初始化项目

    初始化项目 项目的部署版本 之后项目会运行在哪些系统中 横竖屏的支持 iPhone应用一般只支持横屏 iPhone游戏一般支持竖屏 iPad横竖屏都支持 设置项目的图标和启动图片 项目的图标(美工做好 ...

  3. Declarative Widgets is a QML plugin that adds Qt Widgets support to QML

     05.04.2018  Nathan Collins  8 comments FacebookTwitterGoogle+LinkedInEmail Declarative Widgets is a ...

  4. 【Redis学习】:Windows环境下的Redis安装与配置

    Redis简介 REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统. Redis是一个开源的使用ANSI C ...

  5. 使用openoffice转换ms_office to pdf

    java源代码: package com.jeecms.common.office2pdf; import java.io.File; import java.io.FileInputStream; ...

  6. ios开发swift学习第三天:逻辑分支

    一. 分支的介绍 分支即if/switch/三目运算符等判断语句 通过分支语句可以控制程序的执行流程 二. if分支语句 和OC中if语句有一定的区别 判断句可以不加() 在Swift的判断句中必须有 ...

  7. 使用truss、strace或ltrace诊断软件的"疑难杂症"

    原文链接 简介 进程无法启动,软件运行速度突然变慢,程序的"Segment Fault"等等都是让每个Unix系统用户头痛的问题,本文通过三个实际案例演示如何使用truss.str ...

  8. [Angular Directive] 1. Write an Angular Directive

    Angular 2 Directives allow you manipulate elements by adding custom behaviors through attributes. Th ...

  9. css3-1 css3游戏介绍、css3样式和优先级

    css3-1 css3游戏介绍.css3样式和优先级 一.总结 一句话总结:我们写外部css表的时候可以用class,那样使用的人用id修改的话优先级就比我们高,达到目的. 1.html嵌套css样式 ...

  10. PEM_密钥对生成与读取方法

    PS:欢迎转载,但请注明出处,谢谢配合. 前言: PEM是OpenSSL和许多其他SSL工具的标准格式,OpenSSL 使用PEM 文件格式存储证书和密钥.这种格式被设计用来安全的包含在ascii甚至 ...