软件编程
位置:首页>> 软件编程>> C#编程>> c# 实例——绘制波浪线(附源码)

c# 实例——绘制波浪线(附源码)

作者:唐宋元明清2188  发布时间:2023-03-02 12:53:54 

标签:c#,绘制,波浪线

效果图

c# 实例——绘制波浪线(附源码)

界面绘制操作


private Point? _startPoint = null;
 private void ContainerCanvas_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 {
   var position = e.GetPosition(ContainerCanvas);
   if (_startPoint == null)
   {
     _startPoint = position;
   }
   else
   {
     //删除预览
     if (_previewLineElement != null)
     {
       ContainerCanvas.Children.Remove(_previewLineElement);
       _previewLineElement = null;
       _lastMovedPoint = null;
     }
     //确定结束点,绘制波浪线
     var myLineElement = new MyLineElement();
     myLineElement.DrawLine((Point)_startPoint, position);
     ContainerCanvas.Children.Add(myLineElement);
     _startPoint = null;
   }
 }

private MyLineElement _previewLineElement = null;
 private Point? _lastMovedPoint = null;

/// <summary>
 /// 波浪线绘制预览
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void ContainerCanvas_OnMouseMove(object sender, MouseEventArgs e)
 {
   var position = e.GetPosition(ContainerCanvas);
   if (_startPoint != null && (_lastMovedPoint == null || _lastMovedPoint != null & (position - (Point)_lastMovedPoint).Length >= 2))
   {
     _lastMovedPoint = position;
     if (_previewLineElement != null)
     {
       ContainerCanvas.Children.Remove(_previewLineElement);
     }
     var myLineElement = new MyLineElement();
     myLineElement.DrawLine((Point)_startPoint, position);
     ContainerCanvas.Children.Add(myLineElement);
     _previewLineElement = myLineElement;
   }
 }

波浪线控件及绘制


class MyLineElement : FrameworkElement
 {
   public MyLineElement()
   {
     _visualShape = new VisualCollection(this);
   }
   internal void DrawLine(Point startPoint, Point endPoint)
   {
     List<Point> points = ForgePoints(startPoint, endPoint);
     DrawLine(points);
   }
   private const int SeparatorPiexl = 4;
   private const int AbundancePiexl = 3;
   private List<Point> ForgePoints(Point startPoint, Point endPoint)
   {
     var points = new List<Point>();

var lineVector = endPoint - startPoint;
     var lineDistance = lineVector.Length;
     var lineAngle = Math.Atan2(-(endPoint.Y - startPoint.Y), endPoint.X - startPoint.X);

points.Add(startPoint);
     int index = 0;
     bool isAbundanceUpward = true;
     while (index * SeparatorPiexl < lineDistance)
     {
       index++;
       //计算出间隔长度(模拟点到起始点)
       var separatorDistance = index * SeparatorPiexl;
       var abundancePiexl = AbundancePiexl;
       var distanceToStartPoint = Math.Sqrt(Math.Pow(separatorDistance, 2) + Math.Pow(abundancePiexl, 2));
       //计算出模拟点、起始点,与直线的角度
       var separatorAngle = Math.Atan2(AbundancePiexl, separatorDistance);
       separatorAngle = isAbundanceUpward ? separatorAngle : -separatorAngle;
       isAbundanceUpward = !isAbundanceUpward;
       //得到模拟点的水平角度
       var mockPointAngle = lineAngle + separatorAngle;
       //计算出模拟点坐标
       var verticalDistance = distanceToStartPoint * Math.Sin(mockPointAngle);
       var horizontalDistance = distanceToStartPoint * Math.Cos(mockPointAngle);
       var mockPoint = new Point(startPoint.X + horizontalDistance, startPoint.Y - verticalDistance);
       points.Add(mockPoint);
     }
     points.Add(endPoint);
     return points;
   }

private void DrawLine(List<Point> points)
   {
     _visualShape.Clear();

var geometryTest = new StreamGeometry();
     using (var ctx = geometryTest.Open())
     {
       ctx.BeginFigure(points[0], true, false);
       if (points.Count % 2 == 0)
       {
         //绘制二阶贝塞尔函数,需要保证为偶数点
         ctx.PolyQuadraticBezierTo(points, true, true);
       }
       else
       {
         //绘制二阶贝塞尔函数,需要保证为偶数点
         points.Insert(0, points[0]);
         ctx.PolyQuadraticBezierTo(points, true, true);
       }

ctx.Close();
     }

var visual = new DrawingVisual();
     using (var context = visual.RenderOpen())
     {
       context.DrawGeometry(FillBrush, StrokePen, geometryTest);
     }
     _visualShape.Add(visual);
   }

#region 内部方法

[Obsolete]
   protected override void OnRender(DrawingContext drawingContext)
   {
     //弃用,改为_visualShape填充实现
     //drawingContext.DrawGeometry(FillBrush, StrokePen, BaseGeometry);
   }

protected override int VisualChildrenCount => _visualShape.Count;

protected override Visual GetVisualChild(int index)
   {
     if (index < 0 || index >= _visualShape.Count)
     {
       throw new ArgumentOutOfRangeException();
     }

return _visualShape[index];
   }

#endregion

#region 曲线属性

private readonly VisualCollection _visualShape;
   protected Brush FillBrush { get; set; } = Brushes.Transparent;
   public Brush LineBrush { get; set; } = Brushes.DarkSeaGreen;
   protected double BorderThickness { get; set; } = 1.0;
   private Pen _defaultPen = null;
   protected Pen StrokePen
   {
     get
     {
       if (_defaultPen == null)
       {
         _defaultPen = new Pen(LineBrush, BorderThickness);
       }
       return _defaultPen;
     }
     set => _defaultPen = value;
   }

#endregion
 }

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

来源:https://www.cnblogs.com/kybs0/p/11141190.html

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com