zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    移动 App 接入 QQ 登录/分享 图文教程
    Word 最后一页无法删除-解决办法
    Java快速入门-04-Java.util包简单总结
    Java快速入门-03-小知识汇总篇(全)
    SSM 框架-06-详细整合教程(IDEA版)(Spring+SpringMVC+MyBatis)
    二叉树的镜像
    浅析I/O模型及其设计模式
    远程方法调用(RMI)原理与示例
    树的子结构
    合并两个排序的链表
  • 原文地址:https://www.cnblogs.com/kybs0/p/11141190.html
Copyright © 2011-2022 走看看