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

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

效果图

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

标签:c#,绘制,波浪线
0
投稿

猜你喜欢

  • JAVA求两直线交点和三角形内外心的方法

    2023-07-30 02:46:35
  • 关于C# 5.0 CallerMemberName CallerFilePath CallerLineNumber 在.NET4中的使用介绍方法

    2022-03-27 22:05:56
  • springboot FeignClient注解及参数

    2021-07-09 21:59:07
  • SpringBoot动态修改日志级别的操作

    2022-10-31 05:00:30
  • 基于Spring@Autowired注解与自动装配详谈

    2022-01-14 09:38:49
  • SpringBean依赖和三级缓存的案例讲解

    2023-06-25 09:33:22
  • java实现图片滑动验证(包含前端代码)

    2022-03-21 12:13:52
  • SpringBoot全局异常处理与定制404页面的方法

    2021-08-07 18:54:56
  • C#简单读写txt文件的方法

    2023-01-17 06:30:27
  • 深入浅析Spring 的aop实现原理

    2023-01-10 00:00:10
  • 关于mybatis使用${}时sql注入的问题

    2023-04-18 03:29:40
  • Java基于ArrayList实现群主发红包功能

    2022-04-06 20:34:09
  • C#使用LINQ查询表达式的基本子句总结

    2022-08-05 05:09:41
  • C++封装静态链接库和使用的详细步骤

    2021-08-28 00:54:13
  • Android开发Retrofit源码分析

    2022-06-11 18:19:07
  • jvm细节探索之synchronized及实现问题分析

    2023-08-24 02:13:29
  • maven工程中jar包瘦身的五种方法

    2023-11-04 05:01:54
  • java UDP实现一个聊天工具的示例代码

    2021-09-19 18:41:47
  • JavaWeb Servlet实现文件上传与下载功能实例

    2023-06-16 16:41:27
  • c#正反序列化XML文件示例(xml序列化)

    2023-01-06 02:49:57
  • asp之家 软件编程 m.aspxhome.com