[原译]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绘制圆角多边形的更多相关文章
- MFC 用gdi绘制填充多边形区域
MFC 用gdi绘制填充多边形区域 这里的代码是实现一个三角形的绘制,并用刷子填充颜色 在OnPaint()函数里面 运用的是给定的三角形的三个点,很多个点可以绘制多边形 CBrush br(RGB( ...
- 在Microsoft Expression Blend 2 中绘制圆角矩形按钮
原文:在Microsoft Expression Blend 2 中绘制圆角矩形按钮 /* 声明:转载请保留此信息:http://www.BrawDraw.com, http://www.ZPXP.c ...
- WPF绘制自定义窗口
原文:WPF绘制自定义窗口 WPF是制作界面的一大利器,下面就用WPF模拟一下360的软件管理界面,360软件管理界面如下: 界面不难,主要有如下几个要素: 窗体的圆角 自定义标题栏及按钮 自定义状态 ...
- WPF绘制深度不同颜色的3D模型填充图和线框图
原文:WPF绘制深度不同颜色的3D模型填充图和线框图 在机械测量过程中,测量的数据需要进行软件处理.通常测量一个零件之后,需要重建零件的3D模型,便于观察测量结果是否与所测工件一致. 重建的3D模型需 ...
- IOS 中openGL使用教程2(openGL ES 入门篇 | 绘制一个多边形)
在上一篇我们学习了如何搭建IOS下openGL的开发环境,接下来我们来学习如何绘制一个多边形. 在2.0之前,es的渲染采用的是固定管线,何为固定管线,就是一套固定的模板流程,局部坐标变换 -> ...
- WPF绘制党徽(立体效果,Cool)
原文:WPF绘制党徽(立体效果,Cool) 前面用WPF方式绘制了党旗(WPF制作的党旗) ,去年3月份利用C# 及GDI+绘制过党徽,这次使用WPF来绘制党徽. ------------------ ...
- 利用百度API(JavaScript 版)实现在地图上绘制任一多边形,并判断给定经纬度是否在多边形范围内。以及两点间的测距功能
权声明:本文为博主原创文章,未经博主允许不得转载. 利用百度API(JavaScript 版)实现在地图上绘制任一多边形,并判断给定经纬度是否在多边形范围内.以及两点间的测距功能. 绘制多边形(蓝色) ...
- WPF 关于圆角的制作
原文:WPF 关于圆角的制作 1.使用Boder(一般情况): 设置CornerRadius属性 <Border x:Name="border" CornerRadius=& ...
- 封装:WPF绘制曲线视图
原文:封装:WPF绘制曲线视图 一.目的:绘制简单轻量级的曲线视图 二.实现: 1.动画加载曲线 2.点击图例显示隐藏对应曲线 3.绘制标准基准线 4.绘制蒙板显示标准区域 曲线图示例: 心电图示例: ...
随机推荐
- POJ 3252 Round Numbers(数位dp&记忆化搜索)
题目链接:[kuangbin带你飞]专题十五 数位DP E - Round Numbers 题意 给定区间.求转化为二进制后当中0比1多或相等的数字的个数. 思路 将数字转化为二进制进行数位dp,由于 ...
- 微信小程序从零开始开发步骤(一)
从零到有写一个小程序系列专题,很早以前就想写来分享,但由于项目一直在进展,没有过多的时间研究技术,现在可以继续分享了.1:注册用没有注册过微信公众平台的邮箱注册一个微信公众号, 申请帐号 ,点击 ht ...
- 第六章:任务执行——Java并发编程实战
任务:通常是一些抽象的且离散的工作单元.大多数并发应用程序都是围绕"任务执行"来构造的,把程序的工作分给多个任务,可以简化程序的组织结构便于维护 一.在线程中执行任务 任务的独立性 ...
- 小强的HTML5移动开发之路(40)——jqMobi中实践header定义的几种方式
一.定义全局的header 这个header是所有panel默认的header,需要在<div id="afui">内部,也就是和<div id="co ...
- ActivityManagerService的启动过程
AMS对象随系统进程启动而构建,随着系统进程退出而消亡,可以说,AMS与系统进程共存亡. 先上一张总的启动时序图: 上图分为三个步骤: 初始化系统进程的运行环境; 初始化AMS对象; AMS对象启动的 ...
- 【codeforces 791C】Bear and Different Names
[题目链接]:http://codeforces.com/contest/791/problem/C [题意] 给你n-k+1个限制 要求 a[i]..a[i]+k-1里面有相同的元素,或全都不同; ...
- redis举例调用两种方式方式
在以下的代码演示样例中.将给出两种最为经常使用的Redis命令操作方式,既普通调用方式和基于管线的调用方式. 注:在阅读代码时请留意凝视. 1 #include <stdio.h> ...
- C#委托之个人理解
C#委托之个人理解 什么是委托 首先要知道什么是委托,用最通俗易懂的话来讲,你就可以把委托看成是用来执行方法(函数)的一个东西. 如何使用委托 在使用委托的时候,你可以像对待一个类一样对待它.即先 ...
- 单核、多线程与时间片,以Node.js为例
去年写了篇文章<线程与进程的理解>,当时认为线程和CPU的单核多核无关,操作系统可以有很多个线程.但今天看<深入浅出Node.js>一书时,多次提到单线程无法利用多核CPU一类 ...
- 一个2013届毕业生(踏上IT行业)的迷茫(2)
初中的时光是一段艰辛,但幸福的时光,在这一段时光中同样我遇到了我人生中第二个贵人.记得在小学毕业的那个暑假里,我知道上了初中会开一门叫做英语的课程,那时候在我们那里有好多上过初中.高中的在我们小学开英 ...