[原译]WPF绘制圆角多边形

简介: 原文:[原译]WPF绘制圆角多边形介绍 最近,我发现我需要个圆角多边形。而且是需要在运行时从用户界面来绘制。WPF有多边形。但是不支持圆角。我搜索了一下。也没找到可行的现成例子。于是就自己做吧。本文描述了圆角多边形的实现,也包括如何用在你的项目里。
原文: [原译]WPF绘制圆角多边形

介绍

最近,我发现我需要个圆角多边形。而且是需要在运行时从用户界面来绘制。WPF有多边形。但是不支持圆角。我搜索了一下。也没找到可行的现成例子。于是就自己做吧。本文描述了圆角多边形的实现,也包括如何用在你的项目里。在Demo里面的RoundedCornersPolygon 类是完整的实现。

下载的Demo包括两部分

1. 通过XAML绘制圆角多边形

2. 运行时创建圆角多边形

背景
多边形可以被认为是沿着一个给定半径的圆的边缘和一些指定点/边。所构成的点的集合。


在WPF中。你可以给Polygon对象的Points属性添加一系列的点来制作多边形。

XAML方式

<Canvas>
    <Polygon Points="10,50 180,50 180,150 10,150" 
       StrokeThickness="1" Stroke="Black" />
</Canvas>

 

C#方式

var cnv = new Canvas(); 
var polygon = new Polygon {StrokeThickness = 1, Fill = Brushes.Black};
polygon.Points.Add(new Point(10, 50)); 
polygon.Points.Add(new Point(180, 50));
polygon.Points.Add(new Point(180, 150));
polygon.Points.Add(new Point(10, 150));
cnv.Children.Add(polygon);
this.Content = cnv;

 

上面两个例子会输出下面的矩形

使用代码
我写的RoundedCornersPolygon 类和普通的多边形类很相似。但是有更多的属性来控制圆角。首先。看一个例子。展示一下圆角矩形类的使用

XAML方式

<Canvas>
    <CustomRoundedCornersPolygon:RoundedCornersPolygon Points="10,50 180,50 180,150 10,150" 
               StrokeThickness="1" Stroke="Black" ArcRoundness="25" 
               UseAnglePercentage="False" IsClosed="True"/>
<Canvas>

 

C#方式

var cnv = new Canvas();  
var roundedPolygon = new RoundedCornersPolygon
{
    Stroke = Brushes.Black, StrokeThickness = 1, 
    ArcRoundness = 25, UseAnglePercentage = false, IsClosed = true
};
roundedPolygon.Points.Add(new Point(10, 50));
roundedPolygon.Points.Add(new Point(180, 50));
roundedPolygon.Points.Add(new Point(180, 150));
roundedPolygon.Points.Add(new Point(10, 150));
cnv.Children.Add(roundedPolygon);
this.Content = cnv;

 

输出如下:

多边形有四个主要属性
ArcRoundness 属性指定了从距离LineSegment终点多远的距离开始弯曲,通常和UseRoundnessPercentage 一起使用。UseRoundnessPercentage属性指定了ArcRoundness 值是百分比还是一个固定的值。

举个例子。ArcRoundness 被设置成10,而且UseRoundnessPercentage 被设置成false,那么弯曲将会在距离线段终点10的地方开始。而如果UseRoundnessPercentage 被设置成ture。则会是从线段终点10%的地方开始弯曲。

/// <summary> 
/// Gets or sets a value that specifies the arc roundness.
/// </summary>
public double ArcRoundness { get; set; }

/// <summary>  
/// Gets or sets a value that specifies if the ArcRoundness property
/// value will be used as a percentage of the connecting segment or not.
/// </summary>
public bool UseRoundnessPercentage { get; set; }

 

IsClosed 指定多边形的最后一个点是否和第一个点闭合。为了成为一个多边形。一般应该被设置为true

/// <summary> 
/// Gets or sets a value that specifies if the polygon will be closed or not.
/// </summary> 
public bool IsClosed { get; set; }
 

 

Points属性则代表了多边形点的集合。

/// <summary> 
/// Gets or sets a collection that contains the points of the polygon.
/// </summary>
public PointCollection Points{ get; set; } 

如何实现
控件实现了Shape 类,被用来画多边形的形状是一个Path对象。我们会往Path对象里添加LineSegment 和QuadraticBezierSegment 对象。QuadraticBezierSegment 对象表示一个贝塞尔曲线。由三个点定义。更多的信息请查看

对于一个普通的多边形,只有LineSegment是必须的,但是为了设计圆角多边形。就需要贝塞尔曲线了。每一次一个点被添加/一个属性被修改。形状会重绘。做圆角的关键方式就是ConnectLinePoints 方法。

/// <summary>
/// 使用公共点连接两条线段,
/// 通过3个点的指定来绘制弯曲部分
/// </summary>
/// <param name="pathFigure"></param>
/// <param name="p1">第一条线段的第一个点</param>
/// <param name="p2">第二个点,也是公共点</param>
/// <param name="p3">第二条线段的第二个点</param>
/// <param name="roundness">角的弧度</param>
/// <param name="usePercentage">标志值(百分比还是真值) </param>
private static void ConnectLinePoints(PathFigure pathFigure, Point p1, 
                                      Point p2, Point p3,
                                      double roundness, bool usePercentage)
{
      //第一条线段上弯曲部分开始的位置点.
      Point backPoint;
      //第二条线段上弯曲部分结束的位置点
      Point nextPoint;
      if (usePercentage)
      {
          backPoint = GetPointAtDistancePercent(p1, p2, roundness, false);
          nextPoint = GetPointAtDistancePercent(p2, p3, roundness, true);
      }
      else
      {
          backPoint = GetPointAtDistance(p1, p2, roundness, false);
          nextPoint = GetPointAtDistance(p2, p3, roundness, true);
      }            

      int lastSegmentIndex = pathFigure.Segments.Count - 1;
      //设置第一条线段的终点.
      ((LineSegment)(pathFigure.Segments[lastSegmentIndex])).Point = backPoint;

      //创建并添加弯曲部分
      var curve = new QuadraticBezierSegment { Point1 = p2, Point2 = nextPoint };
      pathFigure.Segments.Add(curve);

      /创建并添加新线段。
      var line = new LineSegment { Point = p3 };
      pathFigure.Segments.Add(line);
}

 

还有两个方法计算弯曲部分开始的点GetPointAtDistance 和GetPointAtDistancePercent,第一个是以值计算,第二个是以百分比计算。

/// <summary>
///得到由两个点定义的线段上,给定距离的点
/// </summary>
/// <param name="p1">第一条线段的第一个点</param>
/// <param name="p2">第一条线段的第二个点</param>
/// <param name="distance">点的距离</param>
/// <param name="firstPoint">标志值(百分比还是真值)</param>
/// <returns>计算结果点</returns>
private static Point GetPointAtDistance(Point p1, Point p2, 
                     double distance, bool firstPoint)
{
     double totalDistance = Math.Sqrt(Math.Pow((p2.X - p1.X), 2) + 
                            Math.Pow((p2.Y - p1.Y), 2));
     double rap = firstPoint ? distance / totalDistance : 
                   (totalDistance - distance) / totalDistance;
     return new Point(p1.X + (rap * (p2.X - p1.X)), p1.Y + (rap * (p2.Y - p1.Y)));
}

private static Point GetPointAtDistancePercent(Point p1, Point p2, 
                     double distancePercent, bool firstPoint)
{
     double rap = firstPoint ? distancePercent / 100 : (100 - distancePercent) / 100;
     return new Point(p1.X + (rap * (p2.X - p1.X)), p1.Y + (rap * (p2.Y - p1.Y)));
}
 

 

结论
依然有很多细节应该完善的。但这仅仅是圆角多边形的一个尝试。比如。在其他情况。每个角应该有不同晚景的圆角,WPF使得一切皆有可能。本文的目的是创建一个大家可以用的圆角多边形,他们可以扩展来满足他们的需求。

Demo下载

圆角多边形

许可
本文包括源代码和文件在CPOL下授权。

原文地址:WPF-rounded-corners-polygon

著作权声明:本文由http://leaver.me 翻译,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!

目录
相关文章
|
9月前
|
C#
WPF空心圆角combox
WPF空心圆角combox
104 0
|
前端开发 C#
WPF 自定义的图表(适用大量数据绘制)下
原文:WPF 自定义的图表(适用大量数据绘制)下 上一篇文章中讲了WPF中自定义绘制大量数据的图标,思路是先将其绘制在内存,然后一次性加载到界面,在后续的调试过程中,发现当数据量到达10W时,移动鼠标显示数据有明显的延迟。
1395 0
|
前端开发 C#
WPF使用Canvas绘制可变矩形
原文:WPF使用Canvas绘制可变矩形 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WANGYAN9110/article/details/38130661 1、问题以及解决办法 最近因为项目需要,需要实现一个位置校对的功能,大致的需求如下:有一个图片,有一些位置信息,但是位置信息可能和实际有些偏差,需要做简单调整,后面会对这张图片进行切割等,做些处理。
1640 0
|
C#
WPF 创建无边框的圆角窗口
原文:WPF 创建无边框的圆角窗口 如题所述,在WPF中要创建一个没有边框且为圆角的窗体,有如下几步工作要进行: 第一步:去掉窗体默认样式的边框 首先将窗体的背景设为透明,将允许透明的属性设置为True,...
2567 0
|
C# 前端开发 JavaScript
WPF绘制自定义窗口
原文:WPF绘制自定义窗口 WPF是制作界面的一大利器,下面就用WPF模拟一下360的软件管理界面,360软件管理界面如下:   界面不难,主要有如下几个要素: 窗体的圆角 自定义标题栏及按钮 自定义状态栏 窗体的半透明效果 窗体4周有一圈半透明阴影(抓的图上看不出来) 实现思路很简单,首先隐藏默认窗口的标题栏和边框,然后用WPF的Border或Canvas等元素模拟定义窗体的标题栏、内容区和状态栏。
1474 0
|
C#
WPF 关于圆角的制作
原文:WPF 关于圆角的制作 1、使用Boder(一般情况): 设置CornerRadius属性   ...   2、创建ClippingBorder类: View Code using System; using System.
1317 0
|
C#
WPF 圆角textbox
原文:WPF 圆角textbox 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a771948524/article/details/9245965 ...
1209 0
|
前端开发 Windows
C#WPF 如何绘制几何图形 图示教程 绘制sin曲线 正弦 绘制2D坐标系 有图有代码
原文:C#WPF 如何绘制几何图形 图示教程 绘制sin曲线 正弦 绘制2D坐标系 有图有代码 C#WPF 如何绘制几何图形? 怎么绘制坐标系?绘制sin曲线(正弦曲线)? 这离不开Path(System.Windows.Shapes)和StreamGeometry(System.Windows.Media)类。
2114 0
|
算法 C# 图形学
WPF绘制深度不同颜色的3D模型填充图和线框图
原文:WPF绘制深度不同颜色的3D模型填充图和线框图 在机械测量过程中,测量的数据需要进行软件处理。通常测量一个零件之后,需要重建零件的3D模型,便于观察测量结果是否与所测工件一致。
2859 0
|
C# 前端开发
WPF 自定义的图表(适用大量数据绘制)
原文:WPF 自定义的图表(适用大量数据绘制) 在WPF中绘制图表比较简单,有很多的第三方控件,但是在绘制大量数据的时候,就显得有些吃力,即便是自己用StreamGeometry画也达不到理想的效果,要达到绘制大量数据而不会顿卡现象,只有一个途径,就是首先在内存中绘制好所有的图形,再一次性加载(或者说绘制)到界面控件Canvas或Grid中。
1147 0