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吧(第五百一十七回:绘制波浪效果)

如何利用百度地图JSAPI画带箭头的线

请教C#中如何在 WinForm中画曲线图

由于 cookie,Wavesurfer 不会使用 CROS 错误绘制波浪

怎样为最后一段文字添加下划线,而且下划线的线型为双波浪线?

在 iOS 7 上的 UITableViewCell 之间绘制自定义分隔线