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

介绍

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

下载的Demo包括两部分

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

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

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


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

XAML方式

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

C#方式

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

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

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

XAML方式

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

C#方式

var cnv = new Canvas();
var roundedPolygon = new RoundedCornersPolygon
{
Stroke = Brushes.Black, StrokeThickness = ,
ArcRoundness = , UseAnglePercentage = false, IsClosed = true
};
roundedPolygon.Points.Add(new Point(, ));
roundedPolygon.Points.Add(new Point(, ));
roundedPolygon.Points.Add(new Point(, ));
roundedPolygon.Points.Add(new Point(, ));
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 - ;
//设置第一条线段的终点.
((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), ) +
Math.Pow((p2.Y - p1.Y), ));
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 / : ( - distancePercent) / ;
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 翻译,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!

[原译]WPF绘制圆角多边形的更多相关文章

  1. MFC 用gdi绘制填充多边形区域

    MFC 用gdi绘制填充多边形区域 这里的代码是实现一个三角形的绘制,并用刷子填充颜色 在OnPaint()函数里面 运用的是给定的三角形的三个点,很多个点可以绘制多边形 CBrush br(RGB( ...

  2. 在Microsoft Expression Blend 2 中绘制圆角矩形按钮

    原文:在Microsoft Expression Blend 2 中绘制圆角矩形按钮 /* 声明:转载请保留此信息:http://www.BrawDraw.com, http://www.ZPXP.c ...

  3. WPF绘制自定义窗口

    原文:WPF绘制自定义窗口 WPF是制作界面的一大利器,下面就用WPF模拟一下360的软件管理界面,360软件管理界面如下: 界面不难,主要有如下几个要素: 窗体的圆角 自定义标题栏及按钮 自定义状态 ...

  4. WPF绘制深度不同颜色的3D模型填充图和线框图

    原文:WPF绘制深度不同颜色的3D模型填充图和线框图 在机械测量过程中,测量的数据需要进行软件处理.通常测量一个零件之后,需要重建零件的3D模型,便于观察测量结果是否与所测工件一致. 重建的3D模型需 ...

  5. IOS 中openGL使用教程2(openGL ES 入门篇 | 绘制一个多边形)

    在上一篇我们学习了如何搭建IOS下openGL的开发环境,接下来我们来学习如何绘制一个多边形. 在2.0之前,es的渲染采用的是固定管线,何为固定管线,就是一套固定的模板流程,局部坐标变换 -> ...

  6. WPF绘制党徽(立体效果,Cool)

    原文:WPF绘制党徽(立体效果,Cool) 前面用WPF方式绘制了党旗(WPF制作的党旗) ,去年3月份利用C# 及GDI+绘制过党徽,这次使用WPF来绘制党徽. ------------------ ...

  7. 利用百度API(JavaScript 版)实现在地图上绘制任一多边形,并判断给定经纬度是否在多边形范围内。以及两点间的测距功能

    权声明:本文为博主原创文章,未经博主允许不得转载. 利用百度API(JavaScript 版)实现在地图上绘制任一多边形,并判断给定经纬度是否在多边形范围内.以及两点间的测距功能. 绘制多边形(蓝色) ...

  8. WPF 关于圆角的制作

    原文:WPF 关于圆角的制作 1.使用Boder(一般情况): 设置CornerRadius属性 <Border x:Name="border" CornerRadius=& ...

  9. 封装:WPF绘制曲线视图

    原文:封装:WPF绘制曲线视图 一.目的:绘制简单轻量级的曲线视图 二.实现: 1.动画加载曲线 2.点击图例显示隐藏对应曲线 3.绘制标准基准线 4.绘制蒙板显示标准区域 曲线图示例: 心电图示例: ...

随机推荐

  1. HDOJ 5001 Walk

    概率DP dp[j][d] 表示不经过i点走d步到j的概率, dp[j][d]=sigma ( dp[k][d-1] * Probability ) ans = sigma ( dp[j][D] ) ...

  2. [Angular Unit Testing] Testing Component methods

    import {ComponentFixture, TestBed} from '@angular/core/testing'; import {BrowserDynamicTestingModule ...

  3. php实现字符串的排列(交换)(递归考虑所有情况)

    php实现字符串的排列(交换)(递归考虑所有情况) 一.总结 交换: 当有abc的时候,分别拿第一位和其它位交换,第一位固定,余下的位做递归,这样有考虑到所有情况,因为第一位只可能是所有的字母,那第一 ...

  4. Android组件——使用DrawerLayout仿网易新闻v4.4侧滑菜单

    摘要: 转载请注明出处:http://blog.csdn.net/allen315410/article/details/42914501 概述        今天这篇博客将记录一些关于DrawerL ...

  5. [React Native] Writing Platform-Specific Components for iOS and Android in React Native

    Learn to write components that render differently on iOS and Android, but present the same API. Firs ...

  6. HDU 5044 Tree(树链剖分)

    HDU 5044 Tree field=problem&key=2014+ACM%2FICPC+Asia+Regional+Shanghai+Online&source=1&s ...

  7. 【codeforces 546C】Soldier and Cards

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  8. eclipse配置本地服务

    1.下载安装eclipse 2.下载tomcat文件,并解压 3.下载tomcat插件 com.sysdeo.eclipse.tomcat_3.3.0 将com.sysdeo.eclipse.tomc ...

  9. 在 Oracle 中新建 SDE 用户

    --1.创建用户(SDE)和密码(SDE) CREATE USER SDE IDENTIFIED BY SDE --2.创建表空间(SDE) CREATE TABLESPACE SDE DATAFIL ...

  10. PHP设计模式——迭代模式

    声明:这一系列的博客引用<大话设计模式>.程洁作者. 迭代器模式:迭代器模式是遍历集合的成熟模式.迭代器模式的关键是将遍历集合的任务交给一个叫做迭代器的对象,它的工作时遍历并选择序列中的对 ...