C# 波浪线绘制
Posted kybs0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 波浪线绘制相关的知识,希望对你有一定的参考价值。
波浪线效果如上
界面绘制操作
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
以上是关于C# 波浪线绘制的主要内容,如果未能解决你的问题,请参考以下文章
一起Talk Android吧(第五百一十七回:绘制波浪效果)