1,绘制标准基准线
2,可拖动
1,Canvas
2,Ellipse
<Canvas Background="#232323" Grid.Row="1" x:Name="MainCanvas" SizeChanged="LiveChar\_SizeChanged"
Width="600" Height="300" MouseMove="MainCanvas_MouseMove"
ClipToBounds="True" MouseLeftButtonDown="MainCanvas_MouseLeftButtonDown"
MouseLeftButtonUp="MainCanvas_MouseLeftButtonUp"/>
1,定义变量
///
public double BoardWidth { get; set; }
///
public double BoardHeight { get; set; }
///
public double HorizontalMargin { get; set; }
///
public double VerticalMargin { get; set; }
///
public double horizontalBetween { get; set; }
///
public double verticalBetween { get; set; }
///
public double ChartWidth;
///
public double ChartHeight;
///
public PointCollection DataSourse;
///
public Point StartPostion;
///
public Point EndPostion;
///
public double MaxX { get; set; }
///
public double MaxY { get; set; }
///
public double MinX { get; set; }
///
public double MinY { get; set; }
double MapLocationX = 0;
double MapLocationY = 0;
TextBox moushPonit;
Point pBefore = new Point();//鼠标点击前坐标
Point eBefore = new Point();//圆移动前坐标
bool isMove = false;//是否需要移
Path path2 = null;
2,定义类型
public enum DrawType
{
//Line
L,
//Horizontal line
H,
//Vertical line
V,
//Cubic Bezier curve
C,
//Quadratic Bezier curve
Q,
//Smooth cubic Bezier curve
S,
//smooth quadratic Bezier curve
T
}
public class SpeedOrPower
{
public double SpeedNum { get; set; }
public double PowerNum { get; set; }
}
3,方法
private PointCollection GetCollection()
{
PointCollection myPointCollection = new PointCollection()
{
new Point(0,50),
new Point(10,50),
new Point(20,50),
new Point(100,100)
};
return myPointCollection;
}
private void LiveChar_SizeChanged(object sender, SizeChangedEventArgs e)
{
Refresh();
}
private void Refresh()
{
InitCanvas();
//获取y最大值
if (MaxY < 0.0001)
{
MaxY = 100;
}
//MinY = DataSourse.Min(m => m.Y);
if (MaxX < 0.0001)
{
MaxX = 100;
}
//MinX = DataSourse.Min(m => m.X);
if (Math.Abs(MaxX) < 0.000001 || Math.Abs(MaxY) < 0.000001)
{
return;
}
DrawAxis();
DrawXAxisScale();
DrawYAxisScale();
DrawPolyLine();
}
List<Point> Points = new List<Point>();
/// <summary>
/// 初始化计算点的相对坐标
/// </summary>
private void DrawPolyLine()
{
foreach (var item in DataSourse)
{
Point point = GetRealPoint(item);
Points.Add(point);
}
PaintLine(Points);
PaintEllipse(Points);
}
/// <summary>
/// 绘制控制点
/// </summary>
/// <param name="points"></param>
private void PaintEllipse(List<Point> points)
{
int i = 0;
foreach (var item in points)
{
Ellipse ellipse = new Ellipse();
ellipse.Fill = Brushes.Yellow;
ellipse.Width = 5;
ellipse.Height = 5;
ellipse.Tag = i;
MainCanvas.Children.Add(ellipse);
Canvas.SetTop(ellipse, item.Y-(ellipse.Width/2));
Canvas.SetLeft(ellipse, item.X - (ellipse.Height / 2));
i++;
}
}
/// <summary>
/// h绘制曲线
/// </summary>
/// <param name="points"></param>
private void PaintLine(List<Point> points, DrawType drawType = DrawType.C)
{
StringBuilder data = new StringBuilder("M");
switch (drawType)
{
case DrawType.L:
data.AppendFormat("{0},{1} L", points\[0\].X, points\[0\].Y);
break;
case DrawType.H:
data.AppendFormat("{0},{1} H", points\[0\].X, points\[0\].Y);
break;
case DrawType.V:
data.AppendFormat("{0},{1} V", points\[0\].X, points\[0\].Y);
break;
case DrawType.C:
data.AppendFormat("{0},{1} C", points\[0\].X, points\[0\].Y);
break;
case DrawType.Q:
data.AppendFormat("{0},{1} Q", points\[0\].X, points\[0\].Y);
break;
case DrawType.S:
data.AppendFormat("{0},{1} S", points\[0\].X, points\[0\].Y);
break;
case DrawType.T:
data.AppendFormat("{0},{1} T", points\[0\].X, points\[0\].Y);
break;
default:
break;
}
if (path2 != null)
{
for (int i = 1; i < points.Count; i++)
{
Point pre;
Point next;
if (i == 1)
{
var CurrentPoint = GetSpeedOrPower(points\[i\]);
var GetCurrentPoint= GetSpeedOrPower(points\[i - 1\]);
if (CurrentPoint.SpeedNum- GetCurrentPoint.SpeedNum < 10)
{
pre = new Point((points\[i - 1\].X + points\[i\].X) / 2, points\[i \].Y); //控制点
next = new Point(points\[i\].X, points\[i\].Y); //控制点
}
else
{
pre = new Point((points\[i - 1\].X + points\[i\].X) / 2, points\[i-1\].Y); //控制点
next = new Point((points\[i - 1\].X + points\[i\].X) / 2, points\[i-1\].Y); //控制点
}
}
else
{
pre = new Point((points\[i - 1\].X + points\[i\].X) / 2, points\[i - 1\].Y); //控制点
next = new Point((points\[i - 1\].X + points\[i\].X) / 2, points\[i\].Y); //控制点
}
//Point pre = new Point((points\[i - 1\].X + points\[i\].X) / 2, points\[i - 1\].Y); //控制点
//Point next = new Point((points\[i - 1\].X + points\[i\].X) / 2, points\[i - 1\].Y); //控制点
data.AppendFormat(" {0},{1} {2},{3} {4},{5}", pre.X, pre.Y, next.X, next.Y, points\[i\].X, points\[i\].Y);
}
path2.Data = Geometry.Parse(data.ToString());
}
else
{
// data.AppendFormat("{0},{1} C", points\[0\].X, points\[0\].Y);
for (int i = 1; i < points.Count; i++)
{
Point pre = new Point((points\[i - 1\].X + points\[i\].X) / 2, points\[i - 1\].Y); //控制点
Point next = new Point((points\[i - 1\].X + points\[i\].X) / 2, points\[i\].Y); //控制点
data.AppendFormat(" {0},{1} {2},{3} {4},{5}", pre.X, pre.Y, next.X, next.Y, points\[i\].X, points\[i\].Y);
}
path2 = new Path { Stroke = Brushes.White, StrokeThickness = 2, Data = Geometry.Parse(data.ToString()) };
this.MainCanvas.Children.Add(path2);
}
}
/// <summary>
/// 查询相对坐标
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
private Point GetRealPoint(Point point)
{
var realX = StartPostion.X + (point.X - MinX) \* ChartWidth / (MaxX - MinX) + MapLocationX;
var realY = StartPostion.Y + (MaxY - point.Y) \* ChartHeight / (MaxY - MinY) + MapLocationY;
return new Point(realX, realY);
}
/// <summary>
/// 绘制Y刻度
/// </summary>
private void DrawYAxisScale()
{
if (MinY > MaxY) return;
if (verticalBetween < 0.0001)
verticalBetween = (MaxY - MinY) / 10;
for (var i = MinY; i <= MaxY + 0.01; i += verticalBetween)
{
var y = EndPostion.Y - i \* ChartHeight / (MaxY - MinY) + MapLocationY;
var marker = new Line
{
X1 = StartPostion.X - 5,
Y1 = y,
X2 = StartPostion.X,
Y2 = y,
Stroke = Brushes.Red
};
MainCanvas.Children.Add(marker);
//绘制Y轴网格
var gridLine = new Line
{
X1 = StartPostion.X,
Y1 = y,
X2 = EndPostion.X,
Y2 = y,
StrokeThickness = 0.5,
Stroke = new SolidColorBrush(Colors.AliceBlue)
};
MainCanvas.Children.Add(gridLine);
string text = i.ToString(CultureInfo.InvariantCulture);
var MarkerText = new TextBlock
{
Text = text,
Width = 30,
Foreground = Brushes.Yellow,
FontSize = 10,
HorizontalAlignment = HorizontalAlignment.Right,
TextAlignment = TextAlignment.Right
};
MainCanvas.Children.Add(MarkerText);
Canvas.SetTop(MarkerText, y - 10);
Canvas.SetLeft(MarkerText, 00);
}
}
/// <summary>
/// 绘制X刻度
/// </summary>
private void DrawXAxisScale()
{
if (MinX >= MaxX) return;
if (horizontalBetween < 0.0001)
horizontalBetween = (MaxX - MinX) / 10;
for (var i = MinX; i <= MaxX + 0.01; i += horizontalBetween)
{
var x = StartPostion.X + i \* ChartWidth / (MaxX - MinX) + MapLocationX;
///绘制X轴刻度
var marker = new Line
{
X1 = x,
Y1 = EndPostion.Y,
X2 = x,
Y2 = EndPostion.Y + 4,
Stroke = Brushes.Red
};
MainCanvas.Children.Add(marker);
//绘制X轴网格
var gridLine = new Line
{
X1 = x,
Y1 = StartPostion.Y,
X2 = x,
Y2 = EndPostion.Y,
StrokeThickness = 0.5,
Stroke = new SolidColorBrush(Colors.AliceBlue)
};
MainCanvas.Children.Add(gridLine);
//绘制X轴字符
var text = i.ToString(CultureInfo.InvariantCulture);
var markText = new TextBlock
{
Text = text,
Width = 130,
Foreground = Brushes.Yellow,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Stretch,
TextAlignment = TextAlignment.Left,
FontSize = 10
};
MainCanvas.Children.Add(markText);
Canvas.SetTop(markText, EndPostion.Y + 5);
Canvas.SetLeft(markText, x - 5);
}
}
/// <summary>
/// 绘制线条
/// </summary>
private void DrawAxis()
{
var xaxis = new Line
{
X1 = StartPostion.X,
Y1 = EndPostion.Y,
X2 = EndPostion.X,
Y2 = EndPostion.Y,
Stroke = new SolidColorBrush(Colors.Black)
};
MainCanvas.Children.Add(xaxis);
var XaxisTop = new Line
{
X1 = StartPostion.Y,
Y1 = StartPostion.Y,
X2 = EndPostion.X,
Y2 = StartPostion.Y,
Stroke = new SolidColorBrush(Colors.Black)
};
MainCanvas.Children.Add(XaxisTop);
var yaxis = new Line
{
X1 = StartPostion.X,
Y1 = StartPostion.Y,
X2 = StartPostion.X,
Y2 = EndPostion.Y,
Stroke = new SolidColorBrush(Colors.Black)
};
MainCanvas.Children.Add(yaxis);
var YaxisBottom = new Line
{
X1 = EndPostion.X,
Y1 = EndPostion.Y,
X2 = EndPostion.X,
Y2 = StartPostion.Y,
Stroke = new SolidColorBrush(Colors.Black)
};
MainCanvas.Children.Add(YaxisBottom);
}
/// <summary>
/// 初始化
/// </summary>
private void InitCanvas()
{
MainCanvas.Children.Clear();
BoardWidth = MainCanvas.ActualWidth - SystemParameters.VerticalScrollBarWidth;
BoardHeight = MainCanvas.ActualHeight - SystemParameters.HorizontalScrollBarHeight;
HorizontalMargin = 40;
VerticalMargin = 40;
ChartWidth = BoardWidth - 2 \* HorizontalMargin;//画图区域宽度
ChartHeight = BoardHeight - 2 \* VerticalMargin; //画图区域高度
StartPostion = new Point(HorizontalMargin, VerticalMargin);
EndPostion = new Point(BoardWidth - HorizontalMargin, BoardHeight - VerticalMargin);
moushPonit = new TextBox
{
Background = new SolidColorBrush(Colors.Transparent),
Height = 20,
Width = 200,
Foreground = Brushes.White,
BorderThickness = new Thickness(0),
VerticalAlignment = VerticalAlignment.Top
};
MainCanvas.Children.Add(moushPonit);
Canvas.SetTop(moushPonit, 0);
Canvas.SetLeft(moushPonit, 0);
}
/// <summary>
/// 查询当前速度与功率的值
/// </summary>
/// <param name="Point"></param>
/// <returns></returns>
public SpeedOrPower GetSpeedOrPower(Point Point)
{
double num2 = 100 - (Point.Y - VerticalMargin) / (EndPostion.Y - VerticalMargin) \* 100;
double num3 = (Point.X - HorizontalMargin) / (EndPostion.X - HorizontalMargin) \* 100;
double SpeedNum = Math.Round(num3, 1);
double PowerNum = Math.Round(num2, 1);
return new SpeedOrPower() { SpeedNum=SpeedNum,PowerNum=PowerNum};
}
/// <summary>
/// 鼠标移动时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MainCanvas\_MouseMove(object sender, MouseEventArgs e)
{
Point currentMousePosition = e.GetPosition((UIElement)sender);
var CurrentPoint = GetSpeedOrPower(currentMousePosition);
if (e.OriginalSource != null && e.OriginalSource.GetType() == typeof(Ellipse) && isMove)
{
Ellipse el = (Ellipse)e.OriginalSource;
Point p = e.GetPosition(null);//获取鼠标移动中的坐标
int index = Convert.ToInt32(el.Tag);
if (CurrentPoint.SpeedNum < 0 || CurrentPoint.PowerNum < 0)
isMove = false;
if (currentMousePosition.X > EndPostion.X || currentMousePosition.X < StartPostion.X)
isMove = false;
if (eBefore.Y + (p.Y - pBefore.Y) > EndPostion.Y || eBefore.Y + (p.Y - pBefore.Y) < StartPostion.Y)
isMove = false;
if (index == 0)
{
var Getobj = GetSpeedOrPower(Points\[index + 1\]);
if(CurrentPoint.PowerNum>Getobj.PowerNum)
{
isMove = false; return;
}
Canvas.SetLeft(el, Points\[index\].X - (el.Width / 2));
Canvas.SetTop(el, eBefore.Y + (p.Y - pBefore.Y));
Points\[index\] = new Point(Points\[index\].X, currentMousePosition.Y);
PaintLine(Points);
}
else if (index == Points.Count() - 1)
{
var Getobj = GetSpeedOrPower(Points\[index -1\]);
if (CurrentPoint.PowerNum < Getobj.PowerNum)
{
isMove = false; return;
}
Canvas.SetLeft(el, Points\[index\].X - (el.Width / 2));
Canvas.SetTop(el, eBefore.Y + (p.Y - pBefore.Y));
Points\[index\] = new Point(Points\[index\].X, currentMousePosition.Y);
PaintLine(Points);
}
else
{
if (currentMousePosition.X > Points\[index + 1\].X) { isMove = false; return; }
if (currentMousePosition.Y < Points\[index + 1\].Y) { isMove = false; return; }
if (currentMousePosition.X < Points\[index - 1\].X) { isMove = false; return; }
if (currentMousePosition.Y > Points\[index - 1\].Y) { isMove = false; return; }
Canvas.SetLeft(el, currentMousePosition.X-(el.Width/2));
Canvas.SetTop(el, currentMousePosition.Y - (el.Height / 2));
Points\[index\] = currentMousePosition;
PaintLine(Points);
}
}
if (CurrentPoint.SpeedNum < 0)
{
moushPonit.Visibility = Visibility.Collapsed;
CurrentPoint.SpeedNum = 0;
return;
}
if (CurrentPoint.SpeedNum > 100)
{
moushPonit.Visibility = Visibility.Collapsed;
return;
}
if (CurrentPoint.PowerNum < 0)
{
moushPonit.Visibility = Visibility.Collapsed;
CurrentPoint.PowerNum = 0;
return;
}
if (CurrentPoint.PowerNum > 100)
{
moushPonit.Visibility = Visibility.Collapsed;
return;
}
moushPonit.Visibility = Visibility.Visible;
moushPonit.Text = $"(Speed={CurrentPoint.SpeedNum}%:Power={CurrentPoint.PowerNum}%)";
Canvas.SetTop(moushPonit, currentMousePosition.Y - 20);
Canvas.SetLeft(moushPonit, currentMousePosition.X);
}
/// <summary>
/// 鼠标按下时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MainCanvas\_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(Ellipse))
{
this.pBefore = e.GetPosition(null);//获取点击前鼠标坐标
Ellipse el = (Ellipse)e.OriginalSource;
el.Width = el.Width + 5;
el.Height = el.Height + 5;
this.eBefore = new Point(Canvas.GetLeft(el), Canvas.GetTop(el));//获取点击前圆的坐标
isMove = true;//开始移动了
el.CaptureMouse();//鼠标捕获此圆
}
}
/// <summary>
/// 鼠标释放时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MainCanvas\_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(Ellipse))
{
Ellipse el = (Ellipse)e.OriginalSource;
int index = Convert.ToInt32(el.Tag);
if (el.Width >= 10)
{
el.Width = el.Width - 5;
el.Height = el.Height - 5;
}
Canvas.SetLeft(el, Points\[index\].X - (el.Width / 2));
Canvas.SetTop(el, Points\[index\].Y - (el.Height / 2));
isMove = false;//结束移动了
el.ReleaseMouseCapture();//鼠标释放此圆
}
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章