C# 波浪线绘制_github

波浪线效果如上

界面绘制操作

1     private Point? _startPoint = null;
2 private void ContainerCanvas_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
3 {
4 var position = e.GetPosition(ContainerCanvas);
5 if (_startPoint == null)
6 {
7 _startPoint = position;
8 }
9 else
10 {
11 //删除预览
12 if (_previewLineElement != null)
13 {
14 ContainerCanvas.Children.Remove(_previewLineElement);
15 _previewLineElement = null;
16 _lastMovedPoint = null;
17 }
18 //确定结束点,绘制波浪线
19 var myLineElement = new MyLineElement();
20 myLineElement.DrawLine((Point)_startPoint, position);
21 ContainerCanvas.Children.Add(myLineElement);
22 _startPoint = null;
23 }
24 }
25
26 private MyLineElement _previewLineElement = null;
27 private Point? _lastMovedPoint = null;
28
29 /// <summary>
30 /// 波浪线绘制预览
31 /// </summary>
32 /// <param name="sender"></param>
33 /// <param name="e"></param>
34 private void ContainerCanvas_OnMouseMove(object sender, MouseEventArgs e)
35 {
36 var position = e.GetPosition(ContainerCanvas);
37 if (_startPoint != null && (_lastMovedPoint == null || _lastMovedPoint != null & (position - (Point)_lastMovedPoint).Length >= 2))
38 {
39 _lastMovedPoint = position;
40 if (_previewLineElement != null)
41 {
42 ContainerCanvas.Children.Remove(_previewLineElement);
43 }
44 var myLineElement = new MyLineElement();
45 myLineElement.DrawLine((Point)_startPoint, position);
46 ContainerCanvas.Children.Add(myLineElement);
47 _previewLineElement = myLineElement;
48 }
49

波浪线控件及绘制

1     class MyLineElement : FrameworkElement
2 {
3 public MyLineElement()
4 {
5 _visualShape = new VisualCollection(this);
6 }
7 internal void DrawLine(Point startPoint, Point endPoint)
8 {
9 List<Point> points = ForgePoints(startPoint, endPoint);
10 DrawLine(points);
11 }
12 private const int SeparatorPiexl = 4;
13 private const int AbundancePiexl = 3;
14 private List<Point> ForgePoints(Point startPoint, Point endPoint)
15 {
16 var points = new List<Point>();
17
18 var lineVector = endPoint - startPoint;
19 var lineDistance = lineVector.Length;
20 var lineAngle = Math.Atan2(-(endPoint.Y - startPoint.Y), endPoint.X - startPoint.X);
21
22 points.Add(startPoint);
23 int index = 0;
24 bool isAbundanceUpward = true;
25 while (index * SeparatorPiexl < lineDistance)
26 {
27 index++;
28 //计算出间隔长度(模拟点到起始点)
29 var separatorDistance = index * SeparatorPiexl;
30 var abundancePiexl = AbundancePiexl;
31 var distanceToStartPoint = Math.Sqrt(Math.Pow(separatorDistance, 2) + Math.Pow(abundancePiexl, 2));
32 //计算出模拟点、起始点,与直线的角度
33 var separatorAngle = Math.Atan2(AbundancePiexl, separatorDistance);
34 separatorAngle = isAbundanceUpward ? separatorAngle : -separatorAngle;
35 isAbundanceUpward = !isAbundanceUpward;
36 //得到模拟点的水平角度
37 var mockPointAngle = lineAngle + separatorAngle;
38 //计算出模拟点坐标
39 var verticalDistance = distanceToStartPoint * Math.Sin(mockPointAngle);
40 var horizontalDistance = distanceToStartPoint * Math.Cos(mockPointAngle);
41 var mockPoint = new Point(startPoint.X + horizontalDistance, startPoint.Y - verticalDistance);
42 points.Add(mockPoint);
43 }
44 points.Add(endPoint);
45 return points;
46 }
47
48 private void DrawLine(List<Point> points)
49 {
50 _visualShape.Clear();
51
52 var geometryTest = new StreamGeometry();
53 using (var ctx = geometryTest.Open())
54 {
55 ctx.BeginFigure(points[0], true, false);
56 if (points.Count % 2 == 0)
57 {
58 //绘制二阶贝塞尔函数,需要保证为偶数点
59 ctx.PolyQuadraticBezierTo(points, true, true);
60 }
61 else
62 {
63 //绘制二阶贝塞尔函数,需要保证为偶数点
64 points.Insert(0, points[0]);
65 ctx.PolyQuadraticBezierTo(points, true, true);
66 }
67
68 ctx.Close();
69 }
70
71 var visual = new DrawingVisual();
72 using (var context = visual.RenderOpen())
73 {
74 context.DrawGeometry(FillBrush, StrokePen, geometryTest);
75 }
76 _visualShape.Add(visual);
77 }
78
79 #region 内部方法
80
81 [Obsolete]
82 protected override void OnRender(DrawingContext drawingContext)
83 {
84 //弃用,改为_visualShape填充实现
85 //drawingContext.DrawGeometry(FillBrush, StrokePen, BaseGeometry);
86 }
87
88 protected override int VisualChildrenCount => _visualShape.Count;
89
90 protected override Visual GetVisualChild(int index)
91 {
92 if (index < 0 || index >= _visualShape.Count)
93 {
94 throw new ArgumentOutOfRangeException();
95 }
96
97 return _visualShape[index];
98 }
99
100 #endregion
101
102 #region 曲线属性
103
104 private readonly VisualCollection _visualShape;
105 protected Brush FillBrush { get; set; } = Brushes.Transparent;
106 public Brush LineBrush { get; set; } = Brushes.DarkSeaGreen;
107 protected double BorderThickness { get; set; } = 1.0;
108 private Pen _defaultPen = null;
109 protected Pen StrokePen
110 {
111 get
112 {
113 if (_defaultPen == null)
114 {
115 _defaultPen = new Pen(LineBrush, BorderThickness);
116 }
117 return _defaultPen;
118 }
119 set => _defaultPen = value;
120 }
121
122 #endregion
123

 

Github地址:​​https://github.com/Kybs0/WaveLineTextDemo​


作者:唐宋元明清2188

本文版权归作者所有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。