服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - c# 实例——绘制波浪线(附源码)

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

2022-09-26 14:04唐宋元明清2188 C#

这篇文章主要介绍了c#如何绘制波浪线,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下

效果图

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

界面绘制操作

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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;
    }
  }

波浪线控件及绘制

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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

以上就是c# 实例——绘制波浪线(附源码)的详细内容,更多关于c# 绘制波浪线的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/kybs0/p/11141190.html

延伸 · 阅读

精彩推荐
  • C#C#利用GDI绘制常见图形和文字

    C#利用GDI绘制常见图形和文字

    本文主要介绍了C#中利用GDI来绘制图形和文字的方法,并提供的简单的示例供大家参考学习,希望能够对大家有所帮助。...

    Kimisme4132021-11-17
  • C#轻松学习C#的装箱与拆箱

    轻松学习C#的装箱与拆箱

    轻松学习C#的装箱与拆箱,在之前的文章简单的提到了轻松学习C#的装箱与拆箱,本文带着大家更加详细的介绍轻松学习C#的装箱与拆箱,感兴趣的小伙伴们...

    丿木呈广予口贝5782021-11-03
  • C#ListView用法中与滚动相关的需求实现

    ListView用法中与滚动相关的需求实现

    这篇文章主要介绍了ListView用法中与滚动相关的需求实现,获取并设置ListView的滚动位置,以及获取滚动位置处的项目,具有一定的参考价值,感兴趣的小伙...

    WPInfo8042022-01-10
  • C#C#实现字符串倒序的写法

    C#实现字符串倒序的写法

    这篇文章主要为大家详细介绍了C#实现字符串倒序的多种写法,以LINQ写法最为简洁,感兴趣的朋友可以参考一下...

    zhangbaochong6672021-11-22
  • C#Unity实现倒计时功能

    Unity实现倒计时功能

    这篇文章主要为大家详细介绍了Unity实现倒计时功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    SakuraJI11842022-09-08
  • C#Unity3D实现飞机大战游戏(2)

    Unity3D实现飞机大战游戏(2)

    这篇文章主要为大家详细介绍了Unity3D实现飞机大战游戏的第二部分,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    阿浪啊4872022-09-16
  • C#C#遍历文件夹获取指定后缀名文件

    C#遍历文件夹获取指定后缀名文件

    这篇文章主要为大家详细介绍了C#遍历文件夹获取指定后缀名文件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    cell0065652022-07-14
  • C#Unity中C#和Java的相互调用实例代码

    Unity中C#和Java的相互调用实例代码

    在unity中接入sdk或者定制一些功能时,需要调用系统接口。安卓手机实际操作中,也就是Unity与android相互调用。我们在Unity中使用c#,android中使用java。...

    Unique_8499975634772022-02-19