1、路径和集合图形。
之前介绍过继承Shape类的有Rectangle、Ellipse、PolyGon和Polyline。但还有一个继承自Shape类的Path类,Path类是处理强大的形状类,Path类提供了Data属性,该属性接受一个Geometry(几何)对象,不能直接创建一个Geometry对象,因为Geometry是抽象类,需要用以下派生类中的一个类进行创建。
|
Geometry(集合图形类) |
|
|
名称 |
说明 |
|
LineGeometry |
代表直线,该集合图形相当于Line形状。 |
|
RectangleGeometry |
代表矩形(可以具有圆形拐角),该集合形状相当于Rectangle形状。 |
|
EllipseGeometry |
代表椭圆,该图形相当于Ellipse形状。 |
|
GeometryGroup |
为单个路径添加任意多个Geometry对象,使用EvenOdd或NonZero填充规则来确定要填充的区域。 |
|
CombinedGeometry |
将两个矩形形状合并为一个形状,可使用CombineMode属性选择如何组合两个集合图形。 |
|
PathGeometry |
表更复杂的由弧线、曲线以及直线构成的图形,并且既可以是闭合的,也可以不是闭合的。 |
|
StreamGeometry |
相当于PathGeometry的只读的轻量级类。 |
2、直线、矩形、椭圆图形和GeometryGroup。
2.1)、直线。
<Path Stroke="Red" StrokeThickness="10">
<Path.Data>
<LineGeometry StartPoint="0,0" EndPoint="50,150"></LineGeometry>
</Path.Data>
</Path>
2.2)、矩形。
<Path Fill="Red" Stroke="Blue">
<Path.Data>
<RectangleGeometry Rect="0,0,200,100" RadiusX="10" RadiusY="10"></RectangleGeometry>
</Path.Data>
</Path>
2.3)、椭圆。
<Path Stroke="Gainsboro" Fill="Gainsboro">
<Path.Data>
<EllipseGeometry Center="150,10" RadiusX="100" RadiusY="100">
</EllipseGeometry>
</Path.Data>
</Path>
2.4)、GeometryGroup。
<Path Fill="Yellow" Stroke="Blue" Margin="5">
<Path.Data>
<GeometryGroup>
<RectangleGeometry Rect="0,0, 100,100"></RectangleGeometry>
<EllipseGeometry Center="150,50" RadiusX="35" RadiusY="25"></EllipseGeometry>
</GeometryGroup>
</Path.Data>
</Path>
</StackPanel>
效果图:
通过以上的代码,不能直接为元素设置鼠标事件,只能为Path元素设置鼠标事件。 使用GeometryGroup时,不能为不同的形状执行事件处理,几何图形的另一个优点是可在几个独立的Path元素中重用相同的集合图形,只需要在资源集合中定义即可。
在资源集合中定义资源:
<Window.Resources>
<!--定义一个GeometryGroup类型的资源-->
<GeometryGroup x:Key="gGroup">
<RectangleGeometry Rect="0,0,300,150"></RectangleGeometry>
<EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50"></EllipseGeometry>
</GeometryGroup>
</Window.Resources>
<Grid>
<!--引用-->
<Path Fill="Yellow" Stroke="Yellow" Data="{StaticResource gGroup}">
</Path>
</Grid>
效果图:
2.5)、使用CombinedGeometry融合集合图形。
CombinedGeometry类专门用于组合重叠到一起并且不相互包含的形状,与GemometryGroup类不同,CombindGeometry类只使用两个几何图形,通过Geometry1和Geometry2属性提供这两个集合图形,CombineGeometry类没有包含FillRule属性,反而具有功能更强大的GermotryCombineMode属性。
|
GeometryCombineMode枚举值 |
|
|
名称 |
说明 |
|
Union |
创建包含两个集合图形所有区域的形状。 |
| Intersect | 创建包含两个集合图形共有区域的形状。 |
|
Xor |
创建包含两个集合图形非共有区域的形状,话句话说,就像先合并图形(使用Union),再移除共有的部分(使用Intersect)那样。 |
|
Exclude |
创建的形状包含第一个几何图形的所有区域,但不包含第二个图形的区域。 |
Xaml代码:
<Window x:Class="GeometryCombineMode测试.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:GeometryCombineMode测试"
mc:Ignorable="d"
Title="MainWindow" Height="500" Width="400">
<Grid >
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<!--Union模式-->
<Path Stroke="Red" Fill="Red" Grid.Row="0">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Union">
<CombinedGeometry.Geometry1>
<RectangleGeometry Rect="0,0,100,100"></RectangleGeometry>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="85,50" RadiusX="65" RadiusY="35"></EllipseGeometry>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<Label Grid.Column="1" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center">Union模式</Label>
<!--Intersect模式-->
<Path Stroke="Red" Fill="Red" Grid.Row="1">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Intersect">
<CombinedGeometry.Geometry1>
<RectangleGeometry Rect="0,0,100,100"></RectangleGeometry>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="85,50" RadiusX="65" RadiusY="35"></EllipseGeometry>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<Label Grid.Row="1" Grid.Column="1" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center">Intersect模式</Label>
<!--Xor模式-->
<Path Stroke="Red" Fill="Red" Grid.Row="2">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Xor">
<CombinedGeometry.Geometry1>
<RectangleGeometry Rect="0,0,100,100"></RectangleGeometry>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="85,50" RadiusX="65" RadiusY="35"></EllipseGeometry>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<Label Grid.Row="2" Grid.Column="1" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center">Xor模式</Label>
<!--Exclude模式-->
<Path Stroke="Red" Fill="Red" Grid.Row="3">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Exclude">
<CombinedGeometry.Geometry1>
<RectangleGeometry Rect="0,0,100,100"></RectangleGeometry>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="85,50" RadiusX="65" RadiusY="35"></EllipseGeometry>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<Label Grid.Row="3" Grid.Column="1" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center">Exclude模式</Label>
</Grid>
</Window>
效果图:
构建一个稍微复杂一点的形状。
Xmal代码:
<Grid>
<Path Fill="Yellow" Stroke="Blue">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Exclude">
<CombinedGeometry.Geometry1>
<EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50"></EllipseGeometry>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="50,50" RadiusX="40" RadiusY="40"></EllipseGeometry>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
<Path Fill="Red" Stroke="Blue">
<Path.Data>
<RectangleGeometry Rect="45,10,10,80">
<RectangleGeometry.Transform>
<RotateTransform Angle="45" CenterX="50" CenterY="50"></RotateTransform>
</RectangleGeometry.Transform>
</RectangleGeometry>
</Path.Data>
</Path>
<!--也可写成嵌套模式(Geometry1中嵌套CombinedGeometry)-->
<Path Fill="Yellow" Stroke="Blue" Margin="20">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Union">
<CombinedGeometry.Geometry1>
<CombinedGeometry GeometryCombineMode="Exclude">
<CombinedGeometry.Geometry1>
<EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50"></EllipseGeometry>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="50,50" RadiusX="40" RadiusY="40"></EllipseGeometry>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<RectangleGeometry Rect="45,10,10,80">
<RectangleGeometry.Transform>
<RotateTransform Angle="45" CenterX="50" CenterY="50"></RotateTransform>
</RectangleGeometry.Transform>
</RectangleGeometry>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
</Grid>
效果图:
为集合图形应用变换时,使用的是Transform属性,而不是RenderTransform或者LayoutTransform。这是因为几何图形定义了形状,而且所有变换总在布局中使用路径之前被应用。
3、PathGeomery绘制曲线和直线。
PathGeomery是功能超级强大的图形,她能绘制其他所有几何图形能够绘制的内容,也能绘制其他几何图形不能绘制的内容,每个PathGeomery对象都是由一个或多个PathFigure对象构建的,每个PathFigure对象是一系列相互连接的直线和曲线,可闭合也可不闭合,如果图形中最后一条直线的终点连接到了第一条直线的起点,那么图形就是闭合的。
|
PathFigure常用属性 |
|
|
名称 |
说明 |
| StartPoint | 指示从何处开始绘制图形线条的Point对象。 |
|
Segments |
用于绘制几何的PathSegment对象的集合。 |
|
IsClosed |
如果为true,WPF添加直线来连接起点和终点(假设他们不是同一个点) |
|
IsFilled |
如果为true,就使用Path.Fill画刷填充图形内部的区域。 |
PathFIgure对象是由包含大量线段的不间断线条绘制的形状,然而技巧是有几种类型的线段,它们都继承自PathSegment类,可以通过绘制直线的类和绘制曲线的类来进行绘制。
|
PathSegment类 |
|
| 名称 | 说明 |
| LineSegment |
在两点之间创建直线。 |
|
ArcSegment |
在两点之间创建椭圆形弧线。 |
|
BezierSegment |
在两点之间创建贝塞尔曲线。 |
|
QuadraticBezierSegment |
创建形式更简单的白塞尔曲线,只有一个控制点,而不是两个控制点,并且计算速度更快。 |
|
PloyLineSegment |
创建一系列直线,可使用多个LineSegment对象得到相同的效果。 |
|
PolyBezierSegment |
创建一些列贝塞尔曲线。 |
|
PolyQuadraticBezierSegment |
创建一系列更简单的二次贝塞尔曲线。 |
3.1)、直线。
下面的标记是从点(50,50)开始,绘制一条到点(50,200)的直线,接着再绘制一条点(200,200)的直线,最后仔绘制一条点(50,50)的直线。
<Path Stroke="Blue">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="50,50" IsClosed="True">
<LineSegment Point="50,200"></LineSegment>
<LineSegment Point="200,200"></LineSegment>
<LineSegment Point="200,50"></LineSegment>
<LineSegment Point="50,50"></LineSegment>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
效果图:
3.2)、弧线。
通过使用ArcSegment.Point属性指定弧线段终点,PathFigure从起点向弧线的终点绘制一条曲线,这条弯曲的连接线实际是椭圆边缘的一部分。为了绘制弧线,只有终点是不够的,还需要指定用于绘制弧线的假想椭圆的尺寸(有的椭圆弯曲程度更大),需要使用ArcSegment.Size属性完成该工作,该属性提供了椭圆的X半径和Y半径,假想的椭圆越大,边缘曲线也就越缓和。对于任意两点,实际上存在最大尺寸和最小尺寸的椭圆。当创建的椭圆足够大时,以至于绘制的线段看起来像直线时,这是椭圆的尺寸就有最大尺寸,再增大尺寸就没有效果了,当椭圆足够小时,以至于使用整个半圆链接两点,这时椭圆的尺寸就最小,再缩小尺寸也没有效果。
Xaml代码:
<Path Stroke="Navy">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="10,100">
<ArcSegment Point="300,150" Size="150,150"></ArcSegment>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
效果图:
另外,可用ArcSegment.IsLargeArc属性设置弧线的方向,可将该属性设置为True或false,默认值是false,这意味着使用两条弧线中较短的一条。即使设置了方向,还有一点需要明确椭圆位于何处,使用ArcSegment.SweepDirection属性,该属性可设置向上拉伸和向下拉伸(顺时针或逆时针)。
3.3)、贝塞尔曲线。
贝塞尔曲线使用更复杂的数学公式连接两条线段,该公式包含的两个控制点决定了曲线的形状。这两个控制是问题的关键,它们以两种方式影响着曲线。
方式一:在起点,贝塞尔曲线和从第一个控制点到起点之间的直线相切,在终点,贝塞尔曲线和连接终点与最后一个点的直线相切(在中间是曲线)。
方式二:弯曲程度由两个控制点的距离决定,如果一个控制点更远,该控制点会更强地拉贝塞尔曲线。
为在标记中定义贝塞尔曲线,需要提供三个点:前两个点(BezierSegment.Point1和BezierSegment.Point2)是控制点,第三个点(BezierSegment.Point3)是曲线的终点,同样,起点是路径的起点或前一条线段的终点。
Xaml代码:
<Canvas>
<Path Stroke="Blue" StrokeThickness="5" Canvas.Top="20">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="10,10">
<BezierSegment Point1="130,30" Point2="40,140" Point3="150,150"></BezierSegment>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Green" StrokeThickness="2" StrokeDashArray="5 2" Canvas.Top="20">
<Path.Data>
<GeometryGroup>
<LineGeometry StartPoint="10,10" EndPoint="130,30"></LineGeometry>
<LineGeometry StartPoint="40,140" EndPoint="150,150"></LineGeometry>
</GeometryGroup>
</Path.Data>
</Path>
<Path Stroke="Red" Fill="Red" StrokeThickness="8" Canvas.Top="20">
<Path.Data>
<GeometryGroup>
<EllipseGeometry Center="130,30"></EllipseGeometry>
<EllipseGeometry Center="40,140"></EllipseGeometry>
</GeometryGroup>
</Path.Data>
</Path>
</Canvas>
效果图:
更多贝塞尔内容参考此链接:https://en.wikipedia.org/wiki/B%C3%A9zier_curve
4、微语言集合图形。
微语言本质上是包含一系列命令的长字符串,这些命令由类型转换器读取,然后创建相应的几何图形,每个命令都是单独的字母,后面可选地跟随一些由空格分隔的数字信息(如X和Y坐标),每个命令也使用空格与前面的命令隔开。
|
微语言图形命令 |
|
|
名称 |
说明 |
|
F value |
设置Geometry.FillRute属性。0表示EvenOdd,1表示NonZero,如果决定使用该命令就必须将该命令放在字符串的开头。 |
|
M x,y |
为集合图形创建新的PathFilgure对象,并设置其起点。该命令必须在其他命令之前使用,F命令除外,然而,也可在绘制序列期间使用该命令移动坐标系统的原点(M代表Move)。 |
|
L x,y |
创建一条到指定点的LineSegment几何图形。 |
|
H x |
使用指定的X值创建一条垂直的LineSegment集合图形,并保持Y值不变。 |
|
V y |
使用指定的Y值创建一条垂直的LineSegment集合图形,并保持X值不变。 |
|
A radiusX,radiusY Degrees isLargerArc isClockwise x,y |
创建一条到指定点的ArgSegment线段。指定描述弧线的椭圆半径、弧线旋转的度数,以及用于设置前面介绍的IsLargeArc和SweepDirection属性的布尔标志 |
|
C x1,y1,x2,y2,x,y |
创建到指定点的贝塞尔曲线,使用点(x1,y1)和(x2,y2)作为控制点。 |
|
Q x1,y1 x,y |
创建到指定点的二次贝塞尔曲线,使用一个控制点(x1,y1) |
|
S x2,y2 x,y |
通过将前一条贝塞尔曲线的第二个控制点作为新建贝塞尔曲线的第一个控制点,从而创建一条光滑的贝塞尔曲线 |
|
Z |
结束当前的PathFigure对象,并将Closed属性设置为true,如果不希望将IsClosed设置为true,就不必使用该命令。 |
使用微语言创建一个三角形图形:
<Path Stroke="Blue" Grid.Row="1" Data="M 10,100 L 100,50 Z"></Path>
这个路径使用一个包含4个命令的命令顺序,第一个命令M用于创建PathFilgure,并将起点设置为(10,100),接下来的两个命令(L)创建线段。最后一个命令Z结束PathFigure,并将IsClosed属性设置为true,这个字符串中的逗号是可选的。
5、使用集合图形进行裁剪。
集合图形另一个用途是用于设置Clip属性,可以通过设置Clip属性约束元素的外边界以符合特定的集合图形。
Xaml代码:
<Window x:Class="Clip.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Clip"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<GeometryGroup x:Key="clipGeometry" FillRule="Nonzero">
<EllipseGeometry RadiusX="75" RadiusY="50" Center="100,150"></EllipseGeometry>
<EllipseGeometry RadiusX="100" RadiusY="25" Center="200,150"></EllipseGeometry>
<EllipseGeometry RadiusX="75" RadiusY="130" Center="140,140"></EllipseGeometry>
</GeometryGroup>
</Window.Resources>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Clip="{StaticResource clipGeometry}" FontSize="30"></Button>
<Image Width="500" Height="500" Grid.Column="1" Clip="{StaticResource clipGeometry}" Source="Images/11.jpg"> </Image>
</Grid>
</Window>
效果图:
6、图画。
Geometry抽象类表示形状或路径,Drawing抽象类扮演了互补的角色,GeometryDrawing类增加了决定如何绘制图形的笔画和填充细节。可使用PathGeometry对象创建GeometryDrawing对象。GeometryDrawing类引入了一个新的细节,System.Windows.Media.Pen类。
Xaml代码:
<Window x:Class="Drawing.Drawings"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Drawings" Height="300" Width="300"
>
<Window.Resources>
<GeometryDrawing x:Key="Drawing" Brush="Yellow" >
<GeometryDrawing.Pen>
<Pen Brush="Blue" Thickness="3"></Pen>
</GeometryDrawing.Pen>
<GeometryDrawing.Geometry>
<PathGeometry>
<PathFigure IsClosed="True" StartPoint="10,100">
<LineSegment Point="100,100" />
<LineSegment Point="100,50" />
</PathFigure>
</PathGeometry>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</Window.Resources>
<StackPanel Orientation="Horizontal" Margin="5">
<Button Width="30" Height="30">
<Image>
<Image.Source>
<DrawingImage Drawing="{StaticResource Drawing}">
</DrawingImage>
</Image.Source>
</Image>
</Button>
<Button Width="30" Height="30">
<Button.Background>
<DrawingBrush Stretch="Uniform" Viewport="0,0 0.9,1" Drawing="{StaticResource Drawing}">
</DrawingBrush>
</Button.Background>
</Button>
</StackPanel>
</Window>
GeometryDrawing类不是WPF中唯一的图画类,还有以下其他几种。
|
图画类 |
||
|
类 |
说明 |
属性 |
|
GeometryDrawing |
封装一个几何图形,该集合图形具有填充它的画刷和绘制起边框的画笔。 |
Geometry、Brush、Pen |
|
ImageDrawing |
封装一副图画(通常是基于文件的位图图像),该图像具有定义图像边界的矩形。 |
ImageSource、Rect |
|
VideoDrawing |
用于播放视频文件。 |
Player、Rect |
|
GlyphRunDrawing |
封装低级文本对象。 |
GlyphRun、ForegroundBrush |
|
DrawingGroup |
组合各种类型的Drawing对象的集合。 |
BitmapEffect、Opacity等等 |
继承自Drawing的类不是元素,不能将他们放置到用户界面中,为了显示图画,需要使用以下3个类中的其中一个。
|
用于显示图画的类 |
||
|
类 |
父类 |
说明 |
|
DrawingImge |
ImageSource |
允许在Image元素中驻留图画。 |
|
DrawingBrush |
Brush |
允许使用画刷封装图画。 |
|
DrawingVisual |
Visual |
允许在低级的可视化对象中放置图画。 |
End。