ChartDate.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WpfApp5
{
/// <summary>
/// 画图的基本数据项
/// </summary>
public class ChartDate
{
private double yMarginTop;//顶部留空
private double yMarginLeft;//Y轴左侧,用来显示刻度文字的空白间距
private double xMarginBottom;//X轴下侧,用来显示刻度文字的空白间距
private int yNumInt;//刻度个数
private double yInterval;//Y轴刻度间隔量
private int xNumInt;//x轴的刻度个数
private double xInterval;//x轴间隔量
private double xIntervalLineHeight;//X轴刻度线的高度
private double minY;//Y轴最小值
private double maxY;//Y轴最大值
private DateTime minX;//X轴最小值
private DateTime maxX;//X轴最大值
private double xMove;//x位移量
private double yMove;//y位移量
public ChartDate(double yMarginTop, double yMarginLeft, double xMarginBottom, int yNumInt, double yInterval, int xNumInt, double xIntervalLineHeight, double minY, double maxY, DateTime minX, DateTime maxX, double xInterval, double xMove = 0, double yMove = 0)
{
this.yMarginTop = yMarginTop;
this.yMarginLeft = yMarginLeft;
this.xMarginBottom = xMarginBottom;
this.yNumInt = yNumInt;
this.yInterval = yInterval;
this.xNumInt = xNumInt;
this.xIntervalLineHeight = xIntervalLineHeight;
this.minY = minY;
this.maxY = maxY;
this.minX = minX;
this.maxX = maxX;
this.XInterval = xInterval;
this.xMove = xMove;
this.yMove = yMove;
}
public double YMarginLeft { get => yMarginLeft; set => yMarginLeft = value; }
public double XMarginBottom { get => xMarginBottom; set => xMarginBottom = value; }
public int YNumInt { get => yNumInt; set => yNumInt = value; }
public double YInterval { get => yInterval; set => yInterval = value; }
public int XNumInt { get => xNumInt; set => xNumInt = value; }
public double XIntervalLineHeight { get => xIntervalLineHeight; set => xIntervalLineHeight = value; }
public double MinY { get => minY; set => minY = value; }
public double MaxY { get => maxY; set => maxY = value; }
public DateTime MinX { get => minX; set => minX = value; }
public DateTime MaxX { get => maxX; set => maxX = value; }
public double YMarginTop { get => yMarginTop; set => yMarginTop = value; }
public double XInterval { get => xInterval; set => xInterval = value; }
public double XMove { get => xMove; set => xMove = value; }
public double YMove { get => yMove; set => yMove = value; }
/// <summary>
/// X轴线
/// </summary>
public Rectangle Xaxis()
{
//x轴线
Rectangle rx = new Rectangle();//矩形
rx.Height = 1;
rx.Stroke = new SolidColorBrush(Color.FromRgb(128, 128, 142));//Stroke 边框
rx.HorizontalAlignment = HorizontalAlignment.Stretch;//拉伸填充
rx.VerticalAlignment = VerticalAlignment.Bottom;
return rx;
}
/// <summary>
/// Y轴线
/// </summary>
public Rectangle Yaxis()
{
Rectangle ry = new Rectangle();
ry.Width = 1;
ry.Stroke = new SolidColorBrush(Color.FromRgb(128, 128, 142));
ry.HorizontalAlignment = HorizontalAlignment.Left;
ry.VerticalAlignment = VerticalAlignment.Stretch;
return ry;
}
/// <summary>
/// Y轴虚线
/// </summary>
public Line YImaginaryLine(double ActualHeight, double ActualWidth, int i)
{
//y轴虚线
Line line = new Line();
line.X1 = 0;
line.Y1 = (ActualHeight - YMarginTop) / YInterval * i + YMarginTop;
//Debug.WriteLine($"Data3 :{line.Y1.ToString()+"虚"+ ActualHeight+"高"+ YMarginTop+"顶"+ Convert.ToDouble(XNumInt)+"最后"+ YMove}");
//MessageBox.Show($"Data3 :{line.Y1.ToString() + "Y轴位置"+ YInterval +"间距"+ ActualHeight + "高" + YMarginTop + "顶" + Convert.ToDouble(XNumInt) + "个数" + YMove+"移动量"}");
line.X2 = ActualWidth;
line.Y2 = line.Y1;
line.Stroke = new SolidColorBrush(Color.FromRgb(73, 73, 91));
line.StrokeThickness = 1;
line.StrokeDashArray = new DoubleCollection() { 10, 15 };//虚线,实线的长度和间距
return line;
}
/// <summary>
///Y轴图标
/// </summary>
public TextBlock YIco(double ActualHeight, int i)
{
//Y轴
//y轴图标
TextBlock tb = new TextBlock();
tb.FontSize = 12;
tb.Foreground = new SolidColorBrush(Color.FromRgb(128, 128, 142));
tb.Text = (maxY - (maxY - minY) / yInterval * i).ToString();
tb.VerticalAlignment = VerticalAlignment.Top;
tb.HorizontalAlignment = HorizontalAlignment.Left;
tb.Margin = new Thickness(YMarginLeft-10, (ActualHeight - YMarginTop) / YInterval * i + YMarginTop - (GetFontSizeByTextBlock(tb).Height / 2D), 0, 0);//GetFontSizeByTextBlock 文体尺寸
// MessageBox.Show($"Data4 :{ "Y轴位置" + YInterval + "间距" + ActualHeight + "高" + YMarginTop + "顶" + Convert.ToDouble(XNumInt) + "个数" + YMove + "移动量"}");
return tb;
}
/// <summary>
/// //X轴刻度线
/// </summary>
public Line XImaginaryLine(double ActualHeight, double ActualWidth, int i)
{
//x刻度线
Line line = new Line();//小短线
//xInterval = (maxX.ToOADate() - minX.ToOADate())/Convert.ToDouble(xNumInt);
// Debug.WriteLine("间距:"+xInterval.ToString());
line.X1 =xInterval * i+xMove;
line.Y1 = 0;//顶部
line.X2 = line.X1;
line.Y2 = -XIntervalLineHeight;
if (i % 2 == 0)
{
line.Y2 -= 5D;
}
line.Stroke = new SolidColorBrush(Color.FromRgb(128, 128, 142));
line.StrokeThickness = 1;
return line;
}
//x轴图标
public TextBlock XIco(double ActualWidth, int i)
{
//x轴图标
//两个刻度显示一次文字,并且图标加长
//Min
Debug.WriteLine("_+_++++++++++++++++++++++++++++++++++++" + minX.ToString());
string strMin = minX.ToString();
string[] strArrayMin = strMin.Split(new char[] { '/', ' ', ':' });
//foreach (string s in strArrayMin)
//{
// Debug.WriteLine("_+_:" + s);
int[] dataNumMin = new int[6];
int countMin = 0;
foreach (string j in strArrayMin)
{
dataNumMin[countMin++] = Convert.ToInt32(j);
// Debug.WriteLine("====:" + dataNumMin[countMin - 1]);
}
string strMax = maxX.ToString();
string[] strArrayMax = strMax.Split(new char[] { '/', ' ', ':' });
int[] dataNumMax = new int[6];
int countMax = 0;
foreach (string j in strArrayMin)
{
dataNumMax[countMax++] = Convert.ToInt32(j);
// Debug.WriteLine("====:" + dataNumMax[countMax - 1]);
}
//坐标轴位置输出
TextBlock tb = new TextBlock();
tb.FontSize = 12;
tb.Foreground = new SolidColorBrush(Color.FromRgb(128, 128, 142));
//i++;
// dataNumMin[1] += i;
// Debug.WriteLine("临时点:++:" + dataNumMin[1]);
//if (dataNumMin[1] > 12)
//{
// dataNumMin[1] = i % 12;
// dataNumMin[0]++;
//}
//if (dataNumMin[1] < 1)
//{
// dataNumMin[1] = 12 + dataNumMin[1] % 12;
// dataNumMin[0]--;
//}
//for (int j = 0; j < 3; j++)
//{
// tb.Text += dataNumMin[j].ToString();
// if (j < 2)
// tb.Text += "/";
//}
//tb.Text += "\n";
//for (int j = 3; j < 6; j++)
//{
// tb.Text += dataNumMin[j].ToString();
// if (j < 5)
// tb.Text += ":";
//}
//算出第一个坐标大个格子
double data = (maxX.ToOADate() - minX.ToOADate()) /ActualWidth;
double iData = minX.ToOADate()+data * i * (ActualWidth/xNumInt);
DateTime iDataTime = DateTime.FromOADate(iData);
Debug.WriteLine(" iDataTime 转换检测:======================" + iDataTime+" "+i);
tb.Text = iDataTime.ToString();
tb.VerticalAlignment = VerticalAlignment.Bottom;
tb.HorizontalAlignment = HorizontalAlignment.Left;
tb.Margin = new Thickness(xInterval * i - (GetFontSizeByTextBlock(tb).Width / 2D) + xMove, 0, 0, XMarginBottom);
return tb;
//TextBlock tb = new TextBlock();
//tb.FontSize = 12;
//tb.Foreground = new SolidColorBrush(Color.FromRgb(128, 128, 142));
//if (i < 10)//个位数补零
//{
// tb.Text = "0" + i.ToString() + ":00";
//}
//else
//{
// tb.Text = i.ToString() + ":00";
//}
//tb.VerticalAlignment = VerticalAlignment.Bottom;
//tb.HorizontalAlignment = HorizontalAlignment.Left;
//tb.Margin = new Thickness(xInterval * i + (GetFontSizeByTextBlock(tb).Width / 2D)-xInterval/2D +xMove, 0, 0, XMarginBottom);
//return tb;
}
//画折线图
public Polyline DrawChart(SortedDictionary<DateTime, int> source, double actualWidth,double actualHeight)
{
//第二条数据折线
Polyline plPeople = new Polyline();
plPeople.Stroke = new SolidColorBrush(Color.FromRgb(27, 221, 58));
plPeople.StrokeThickness = 1;
plPeople.StrokeLineJoin = PenLineJoin.Round;
plPeople.IsHitTestVisible = false;
plPeople.Fill= new SolidColorBrush(Color.FromRgb(27, 221, 58));
plPeople.Fill.Opacity = 0.1;
//SortedDictionary<DateTime, int> temp = new SortedDictionary<DateTime, int>();
//将第一个值为初始值
DateTime preMinX= Convert.ToDateTime("2021-01-01 00:00:00");//最小值的前一个节点
foreach (var t in source)
{
preMinX= t.Key;//最小值的前一个节点
break;
}
DateTime dateMaxX=Convert.ToDateTime("2021-01-01 00:00:00");//最后一个节点
bool bPreMinx = false;//用于判断是否需要输出preMinx
foreach (var t in source)
{
//在minX 和max之外的不显示
DateTime k = t.Key;
dateMaxX = k;
//多显示图像的前一个和后一个保证图形的连续性
if (k.ToOADate() <minX.ToOADate() )
{
//Debug.WriteLine("全显示:key:" + k.ToString() + " value:" + source[k]);
//Debug.WriteLine("minx:key:" + minX.ToString());
//Debug.WriteLine("max:key:" + maxX.ToString());
//Debug.WriteLine("k的double:" + k.ToOADate() + " min的double" + minX.ToOADate() + " max的double" + maxX.ToOADate());
preMinX = k;
continue;
}
//输入前一个
if (!bPreMinx)
{
//连接0点
Point pStart1 = new Point();
pStart1.X = (actualWidth / xNumInt * ((preMinX.ToOADate() - minX.ToOADate()) / ((maxX.ToOADate() - minX.ToOADate()) / xNumInt))) + xMove;
pStart1.Y = actualHeight;
plPeople.Points.Add(pStart1);
Point p1 = new Point();
p1.X = (actualWidth / xNumInt * ((preMinX.ToOADate() - minX.ToOADate()) / ((maxX.ToOADate() - minX.ToOADate()) / xNumInt))) + xMove;
p1.Y = ((actualHeight - yMarginTop) / (maxY - minY) * (maxY - source[preMinX])) + yMarginTop;
plPeople.Points.Add(p1);
bPreMinx = true;
}
Point p = new Point();
p.X = (actualWidth / xNumInt * ((k.ToOADate() - minX.ToOADate()) / ((maxX.ToOADate() - minX.ToOADate()) / xNumInt))) + xMove;
//超出y的界限怎么计算?????????
p.Y = ((actualHeight - yMarginTop) / (maxY - minY) * (maxY - source[k])) + yMarginTop;
plPeople.Points.Add(p);
//最后一个值的后一个
//这值要是存在就输出,不存在就将最后一个值连接0点
if (k.ToOADate() > maxX.ToOADate())
{
Point pEnd1 = new Point();
pEnd1.X = (actualWidth / xNumInt * ((dateMaxX.ToOADate() - minX.ToOADate()) / ((maxX.ToOADate() - minX.ToOADate()) / xNumInt))) + xMove;
pEnd1.Y = actualHeight;
plPeople.Points.Add(pEnd1);
return plPeople;
}
//Ellipse ep = new Ellipse();
//ep.Width = 10;
//ep.Height = 10;
//ep.Stroke = new SolidColorBrush(Color.FromRgb(230, 230, 236));
//ep.StrokeThickness = 0;
//ep.Fill = new SolidColorBrush(Color.FromRgb(27, 221, 58));
//ep.HorizontalAlignment = HorizontalAlignment.Left;
//ep.VerticalAlignment = VerticalAlignment.Top;
//ep.Margin = new Thickness(p.X - 5, p.Y - 5, 0, -5);//底部设置-5(圆球宽高的一半),当Y等于0的时候,可以让圆球全部显示
}
//当容器第一个数据出现,第一个最底边
Point pStart = new Point();
pStart.X = (actualWidth / xNumInt * ((preMinX.ToOADate() - minX.ToOADate()) / ((maxX.ToOADate() - minX.ToOADate()) / xNumInt))) + xMove;
//Debug.WriteLine("二号折线图数据:"+ "MAX-MIN:"+((cd.MaxX.ToOADate() - cd.MinX.ToOADate()) / cd.YNumInt)+ "K-MIN"+ (k.ToOADate() - cd.MinX.ToOADate()));
pStart.Y = actualHeight;
plPeople.Points.Add(pStart);
//当容器最后一个数据出现时,连接最后一个最底边
Point pEnd = new Point();
pEnd.X = (actualWidth / xNumInt * ((dateMaxX.ToOADate() - minX.ToOADate()) / ((maxX.ToOADate() - minX.ToOADate()) / xNumInt))) + xMove;
//Debug.WriteLine("二号折线图数据:"+ "MAX-MIN:"+((cd.MaxX.ToOADate() - cd.MinX.ToOADate()) / cd.YNumInt)+ "K-MIN"+ (k.ToOADate() - cd.MinX.ToOADate()));
pEnd.Y = actualHeight;
plPeople.Points.Add(pEnd);
return plPeople;
}
//测量文本框的尺寸
public Size GetFontSizeByTextBlock(TextBlock tb)
{
var formattedText = new FormattedText(
tb.Text,
CultureInfo.CurrentUICulture,
FlowDirection.LeftToRight,
new Typeface(tb.FontFamily, tb.FontStyle, tb.FontWeight, tb.FontStretch),
tb.FontSize,
tb.Foreground
);
Size size = new Size(formattedText.Width, formattedText.Height);
return size;
}
}
}
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace WpfApp5
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// //Y轴上方的空白间距
/// </summary>
//double maxYMarginTop = 20;//Y轴上方的空白间距
//double yMarginLeft = 30D;//Y轴左侧,用来显示刻度文字的空白间距
//double yNum = 10D;//Y轴的刻度个数
//int yNumInt = 10;
//double minY = 10D;//Y轴最小值
//double maxY = 110D;//Y轴最大值
//double yInterval = 10D;//Y轴刻度
//double xMarginBottom = 20D;//X轴下侧,用来显示刻度文字的空白间距
//double xNum = 100D;//x轴的刻度个数
//int xNumInt = 100;//x轴的刻度个数
//double xIntervalLineHeight = 10D;//X轴刻度线的高度
//DateTime minX = Convert.ToDateTime("2022-06-27 00:00:00");//X轴最小值
//DateTime maxX = Convert.ToDateTime("2022-06-27 00:00:00");//X轴最大值
//提前计算最小最大,坐标刻度间隔度
ChartDate cd;
SortedDictionary<DateTime, int> bsource;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
cd = new ChartDate(20D, 30D, 20D, 10, 10D, 12, 10D, 0D, 100D, Convert.ToDateTime("2021-01-01 00:00:00"), Convert.ToDateTime("2022-02-01 00:00:00"), Bgrid.ActualWidth / 12D);
try
{
Stopwatch watch = new Stopwatch();
Agrid.Children.Clear();//清除全部
//double timeInterval = (maxX.ToOADate() - minX.ToOADate()) / (xNum - 1);
watch.Start();
//折线1数据
SortedDictionary<DateTime, int> csource = new SortedDictionary<DateTime, int>();
Random random = new Random(DateTime.Now.Millisecond);
for (int i = 0; i < 50; i++)
{
DateTime time = DateTime.Now.AddHours(random.Next(-2400, 0));
int x = random.Next(1, 100);
if (csource.Count == 0 || csource.Keys.ToList().FindIndex(cur => $"{cur:yyyy-MM-dd HH:mm:ss}" == $"{time:yyyy-MM-dd HH:mm:ss}") == -1)
{
csource.Add(time, x);
// Debug.WriteLine("数据1 :" + time.ToString() + " " + x.ToString());
}
}
watch.Stop();
Console.WriteLine($"Data1 : {watch.ElapsedMilliseconds}ms");
watch.Restart();
///折线2数据
bsource = new SortedDictionary<DateTime, int>();
for (int i = 0; i < 10000; i++)
{
var time = DateTime.Now.AddDays(random.Next(-24000, 24000));
int x = random.Next(1, 100);
bool bl = true;
foreach (DateTime dt in bsource.Keys)
{
if (dt.ToOADate() == time.ToOADate())
{
bl = false;
break;
}
}
if (!bl)
continue;
bsource.Add(time, x);
}
foreach (var t in bsource)
{
// Debug.WriteLine("数据2 :" + t.ToString());
}
watch.Stop();
Debug.WriteLine($"Data2 : {watch.ElapsedMilliseconds}ms");
watch.Restart();
//x轴线
Bgrid.Children.Add(cd.Xaxis());
//y轴线
Bgrid.Children.Add(cd.Yaxis());
//y图标
Ychart();
//x轴
Xchart();
//第一条数据折线
Polyline plView = new Polyline();//互连直线
plView.Stroke = new SolidColorBrush(Color.FromRgb(66, 120, 255));
plView.StrokeThickness = 1;
plView.StrokeLineJoin = PenLineJoin.Round;//联接形状
plView.IsHitTestVisible = true;
foreach (DateTime k in csource.Keys)
{
Point p = new Point();
// p.X = (Agrid.ActualWidth / Convert.ToDouble(cd.XNumInt) * ((k.ToOADate() - cd.MaxX.ToOADate()) / cd.)) + ((Agrid.ActualWidth / xNum) / 2D);
//p.Y = ((Agrid.ActualHeight - maxYMarginTop) / (maxY - minY) * (maxY - csource[k])) + maxYMarginTop;
plView.Points.Add(p);
Ellipse ep = new Ellipse();//椭圆形
ep.Width = 10;
ep.Height = 10;
//在点击节点时候出现
ep.Stroke = new SolidColorBrush(Color.FromRgb(230, 230, 236));//透明色,边框
ep.StrokeThickness = 0;
ep.Fill = new SolidColorBrush(Color.FromRgb(66, 120, 255));//内部上色
ep.HorizontalAlignment = HorizontalAlignment.Left;
ep.VerticalAlignment = VerticalAlignment.Top;
ep.Margin = new Thickness(p.X - 5, p.Y - 5, 0, -5);//底部设置-5(圆球宽高的一半),当Y等于0的时候,可以让圆球全部显示
}
Agrid.Children.Add(plView);
//第二条数据折线
Draw(bsource);
watch.Stop();
Console.WriteLine($"Drawing : {watch.ElapsedMilliseconds}ms");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//X轴
public void Xchart()
{
if (cd.XMove <= 0)
{
int countX = cd.XNumInt;
//x轴
for (int i = 0; i <= countX; i++)
{
Debug.WriteLine("dad+:" + (cd.XInterval * i + cd.XMove));
if (cd.XInterval * i + cd.XMove < 0)
countX++;
else
{
//虚线
a4.Children.Add(cd.XImaginaryLine(Bgrid.ActualWidth, Bgrid.ActualHeight, i));
//图标
if (i % 2 == 0)
a4.Children.Add(cd.XIco(Bgrid.ActualWidth, i));
//超出界限的不算数
Debug.WriteLine("判断x轴移动的越界情况:间隔量" + cd.XInterval + " 移动量:" + cd.XMove);
}
}
}
else if (cd.XMove > 0)
{
int countX = 0;
//x轴
for (int i = cd.XNumInt; i >countX; i--)
{
if (cd.XInterval * i + cd.XMove > Bgrid.ActualWidth)
countX--;
else
{
//虚线
a4.Children.Add(cd.XImaginaryLine(Bgrid.ActualWidth, Bgrid.ActualHeight, i));
//图标
if (i % 2 == 0)
a4.Children.Add(cd.XIco(Bgrid.ActualWidth, i));
//超出界限的不算数
Debug.WriteLine("判断x轴移动的越界情况:间隔量" + cd.XInterval + " 移动量:" + cd.XMove);
}
}
}
}
//Y轴
public void Ychart()
{
//Y轴
//for (int i = 0; i < cd.YNumInt; i++)
//{
// //虚线
// Agrid.Children.Add(cd.YImaginaryLine(Agrid.ActualHeight, Agrid.ActualWidth, i));
// //图标
// a1.Children.Add(cd.YIco(Agrid.ActualHeight, i));
// Debug.WriteLine("YY." + Agrid.ActualHeight.ToString() + " " + i);
//}
if (cd.YMove <= 0)
{
int countY = cd.YNumInt;
//x轴
for (int i = 0; i <= countY; i++)
{
Debug.WriteLine("dad+:" + (cd.XInterval * i + cd.XMove));
if (cd.YInterval * i + cd.YMove < 0)
countY++;
else
{
//虚线
Agrid.Children.Add(cd.YImaginaryLine(Agrid.ActualHeight, Agrid.ActualWidth, i));
//图标
a1.Children.Add(cd.YIco(Agrid.ActualHeight, i));
//超出界限的不算数
Debug.WriteLine("判断x轴移动的越界情况:间隔量" + cd.YInterval + " 移动量:" + cd.YMove);
}
}
}
else if (cd.YMove > 0)
{
int countY = 0;
//x轴
for (int i = cd.YNumInt; i >= countY; i--)
{
if (cd.XInterval * i + cd.XMove > Bgrid.ActualWidth)
countY--;
else
{
//虚线
Agrid.Children.Add(cd.YImaginaryLine(Agrid.ActualHeight, Agrid.ActualWidth, i));
//图标
a1.Children.Add(cd.YIco(Agrid.ActualHeight, i));
//超出界限的不算数
Debug.WriteLine("判断x轴移动的越界情况:间隔量" + cd.YInterval + " 移动量:" + cd.YMove);
}
}
}
}
//画图
public void Draw(SortedDictionary<DateTime, int> source)
{
Polyline plPeople = new Polyline();
plPeople = cd.DrawChart(source, Bgrid.ActualWidth, Bgrid.ActualHeight);
Agrid.Children.Add(plPeople);
}
private bool mouseDown;
private Point mouseXY;
//sender
//事件处理程序附加到的对象
//事件数据
//鼠标按下时的事件,启用捕获鼠标位置并把坐标赋值给mouseXY
private void ContentControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var img = sender as ContentControl;
if (img == null)
{
return;
}
img.CaptureMouse(); //强制获得鼠标元素
mouseDown = true; //点击左键,赋值ture
mouseXY = e.GetPosition(img); //返回指针坐标
}
//鼠标松开时的事件,停止捕获鼠标位置
private void ContentControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var img = sender as ContentControl;
if (img == null)
{
return;
}
img.ReleaseMouseCapture();//释放
mouseDown = false;
}
//鼠标移动时的事件
//当鼠标按下并移动时发生Domousemove(img, e);函数
private void ContentControl_MouseMove(object sender, MouseEventArgs e)
{
var img = sender as ContentControl;
if (img == null)
{
return;
}
if (mouseDown)
{
Domousemove(img, e);
}
}
//它根据X.Y的值来移动。并把当前鼠标位置赋值给mouseXY
//group.Children中的第二个是移动的函数
//改:鼠标移动周不变
private void Domousemove(ContentControl img, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed)//LeftButton 获得鼠标的状态 判断左键是不是被按下
{
return;
}
var group = View.FindResource("Trans") as TransformGroup;
//var transform = group.Children[1] as TranslateTransform; //平移
var position = e.GetPosition(img);
// transform.X -= mouseXY.X - position.X;
// transform.Y -= mouseXY.Y - position.Y;
//这一块有问题??????解决了!!!
// cd.XMove = transform.X*100;
//x移动量
cd.XMove = (mouseXY.X - position.X) * -1/10;
//根据移动获取x最大最小值:
double totalDateX = cd.MaxX.ToOADate() - cd.MinX.ToOADate();
double wideDays = totalDateX / Agrid.ActualWidth;
double rightDataX = cd.XMove * wideDays + cd.MinX.ToOADate();
DateTime rightMinX = DateTime.FromOADate(rightDataX);
double leftDataX = cd.XMove * wideDays + cd.MaxX.ToOADate();
DateTime leftMaxX = DateTime.FromOADate(leftDataX);
Debug.WriteLine(" 左边 转换检测:" + rightMinX + " 右边 转换检测:" + leftMaxX);
//传值
cd.MinX = rightMinX;
cd.MaxX = leftMaxX;
//y移动量
cd.YMove = (mouseXY.Y - position.Y) * -1/10;
//根据移动获取y最大最小值
double totalDateY = cd.MaxY - cd.MinY;
double heighDays = totalDateY / (Agrid.ActualHeight-cd.YMarginTop);
double topDataY = cd.YMove * heighDays + cd.MaxY;
double botDataY = cd.YMove * heighDays + cd.MinY;
Debug.WriteLine(" 左边 转换检测:" + topDataY + " 右边 转换检测:" + botDataY + "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
//传值
cd.MinY = botDataY;
cd.MaxY = topDataY;
a1.Children.Clear();
a4.Children.Clear();
Agrid.Children.Clear();
//cd.YMove = -transform.Y;
Xchart();
Ychart();
Draw(bsource);
// mouseXY = position;
//移动的坐标横坐标计算有问题????????????????
}
//鼠标滑轮事件,得到坐标,放缩函数和滑轮指数,由于滑轮值变化较大所以*0.001.
private void ContentControl_MouseWheel(object sender, MouseWheelEventArgs e)
{
var img = sender as ContentControl;
if (img == null)
{
return;
}
var point = e.GetPosition(Agrid);
var group = View.FindResource("Trans") as TransformGroup;
var delta = e.Delta * 0.001;
DowheelZoom(group, point, delta,e);
}
// Group.Children中的第一个是放缩函数。
//如果ScaleX+滑轮指数小于0.1时就返回。
//var pointToContent = group.Inverse.Transform(point);
// 获取此变换的逆变换的值
//使图片放缩后,放缩原点也随之变化。
private void DowheelZoom(TransformGroup group, Point point, double delta, MouseWheelEventArgs e)
{
var pointToContent = group.Inverse.Transform(point);
var transform = group.Children[0] as ScaleTransform;
if (transform.ScaleX + delta < 1) return;
//实现放缩
transform.ScaleX += delta;
transform.ScaleY += delta;
//找到放缩基点
TranslateTransform translateTransform = group.Children[1] as TranslateTransform;
Debug.WriteLine("原来的x:" + e.GetPosition(Agrid));
translateTransform.X -= point.X * delta;
translateTransform.Y -= point.Y * delta;
Debug.WriteLine("旋转的x"+transform.ScaleX.ToString());
Debug.WriteLine("移动的x:" + translateTransform.X+" 原来位置点 "+point.X+" 放缩倍数点 "+delta);
a4.Children.Clear();
Agrid.Children.Clear();
a1.Children.Clear();
// cd.XInterval *= transform.ScaleX + delta;
// Debug.WriteLine("改变的间距:" + cd.XInterval);
// cd.MinX.AddHours(1);
// cd.MaxX.AddHours(-1);
//cd.XMove = point.X-point.X/(1-delta);
//Debug.WriteLine("移动的轴:" + cd.XMove);
//这里改变最小最大值吧???先只算x的,y先不动
DateTime k = Convert.ToDateTime("2022-02-01 01:00:00");
//宽800 鼠标点击点的时间
double width = Agrid.ActualWidth;
double height = Agrid.Height;
//鼠标点x的位置
double preDoubleX = point.X * ((cd.MaxX.ToOADate() - cd.MinX.ToOADate()) / width) + cd.MinX.ToOADate();
// DateTime PointX = DateTime.FromOADate(preDoubleX);
// Debug.WriteLine("鼠标点位x:" + PointX);
double totalDateX;//x轴最小最大距
double totalDateY;//y轴最小最大距
if (delta > 0)
{
//transNum++;
//在放大
totalDateX = (cd.MaxX.ToOADate() - cd.MinX.ToOADate()) / 2;
totalDateY = (cd.MaxY - cd.MinY) / 2;
}
else
{
totalDateX = (cd.MaxX.ToOADate() - cd.MinX.ToOADate()) * 2;
totalDateY = (cd.MaxY - cd.MinY) * 2;
}
//根据鼠标点击x轴点求最大值和最小值
double wideDays = totalDateX / width;
double rightDataX = preDoubleX-point.X * wideDays;
DateTime rightMinX = DateTime.FromOADate(rightDataX);
double leftDataX = preDoubleX+(width - point.X) * wideDays;
DateTime leftMaxX = DateTime.FromOADate(leftDataX);
Debug.WriteLine( " 左边 转换检测:" + rightMinX+" 右边 转换检测:"+leftMaxX);
//根据鼠标点击y轴点求最大值和最小值
double heightDays = totalDateY / (height - cd.YMarginTop);
double topDataY =cd.MaxY - (point.Y-cd.YMarginTop) * heightDays;
double botDataY = cd.MinY + (height-point.Y) * heightDays;
Debug.WriteLine(" 上边 转换检测:" + topDataY + " 下边 转换检测:" + botDataY + "********************************************");
//传值
cd.MinX = rightMinX;
cd.MaxX = leftMaxX;
cd.MinY = botDataY;
cd.MaxY = topDataY;
Xchart();
Ychart();
//画图
Draw(bsource);
//DateTime l1 = Convert.ToDateTime("2022-06-02 00:00:00");
//double kkk = l1.ToOADate();
//Debug.WriteLine("测测试数据1:" + kkk);
//DateTime dateMinX = DateTime.FromOADate(kkk);
//Debug.WriteLine("原数据:"+l1.ToString()+" 转换检测:"+ dateMinX);
根据点位计算x的变化后的min和max
指定的点代表那一天
//double cha=cd.MaxX.ToOADate() - cd.MinX.ToOADate();
//double ge= cha/ Agrid.ActualWidth;
坐标位置:
//double data1 = ge * point.X;
宽是700
//Debug.WriteLine("X坐标:" + point.X+" max: "+ cd.MaxX.ToOADate() + " minx: "+ cd.MinX.ToOADate() + " ge: "+ cha / Agrid.ActualWidth + " data1: "+ ge * point.X);
//cd.MinX=Convert.ToDateTime("2022-06-01 00:00:00");
//cd.MaxX = Convert.ToDateTime("2022-06-10 00:00:00");
//Draw(bsource);
//DateTime l1 = Convert.ToDateTime("2022-06-02 00:00:00") ;
//DateTime l2 = Convert.ToDateTime("2022-06-01 00:00:00");
//Debug.WriteLine("测测试数据1:" + (l1.ToOADate() - l2.ToOADate()));
//DateTime l3 = Convert.ToDateTime("2021-08-01 00:00:00");
//DateTime l4 = Convert.ToDateTime("2022-08-01 00:00:00");
//Debug.WriteLine("测测试数据2:" + (l3.ToOADate() - l4.ToOADate()));
}
}
}