十二,几何图形和图画

  1. Path类是功能最强大的形状类,它能够包含任何简单形状、多级形状及更更复杂的曲线。Path.Data属性,该属性接受一个Geometry对象,该对象定义路径包含的一个或多个图形,Geometry是一个抽象类,指定Data时需要使用以下Geometry类的派生类:
    QQ20140821001107_thumb2
    路径和几何图形之间的区别:几何图形定义形状,而路径用于绘制形状,因此,Geometry对象为形状定义了坐标、尺寸等细节,而Path对象提供了绘制形状所使用的Stroke和Fill画刷,Path类还继承自UIElement基础架构中的特性,如鼠标和键盘处理。
    Geometry继承自Freezable类,所以它的派生类都支持更改通知,因此,如果使用几何图形创建了一个路径,然后修改该几何图形,路径就会被重新绘制。
    1. LineGeometryRectangleGeometryEllipseGeometry几何形状直接和Line、Rectangle、Ellipse形状对应。如下标记分别将Rectangle、Line和Ellipse形状转换为Path元素的标记:    

      <Rectangle Width="80" Height="50" Fill="Red" Stroke="Yellow" RadiusX="10" RadiusY="10"></Rectangle>
      <Path Fill="Red" Stroke="Yellow" Canvas.Top="55">
          <Path.Data>
              <RectangleGeometry Rect="0,0,80,50" RadiusX="10" RadiusY="10"></RectangleGeometry>
          </Path.Data>
      </Path> 
      <Line Stroke="Yellow" X2="80" Y2="120" Y1="120" StrokeThickness="5"></Line>
      <Path Stroke="Yellow" StrokeThickness="5">
          <Path.Data>
              <LineGeometry StartPoint="0,140" EndPoint="80,140"></LineGeometry>
          </Path.Data>
      </Path> 
      <Ellipse Fill="Red" Stroke="Yellow" Width="80" Height="50" Canvas.Top="160"></Ellipse>
      <Path Fill="Red" Stroke="Yellow" Canvas.Top="215">
          <Path.Data>
              <EllipseGeometry RadiusX="40" RadiusY="25" Center="40,27"></EllipseGeometry>
          </Path.Data>
      </Path>
    2. 使用GeometryGroup来组合形状
      组合图形最简单的方法是使用GeometryGroup对象,该对象在内部嵌套其它Geometry类的派生类对象,如下示例是正方形旁边放了一个椭圆:

      <TextBlock Canvas.Top="338" FontSize="20" FontWeight="Bold" Canvas.Left="64">GeometryGroup Test</TextBlock> 
      <Path Fill="Red" Stroke="Blue" Canvas.Top="300"> 
          <Path.Data> 
              <GeometryGroup> 
                  <RectangleGeometry Rect="0 0 100 100"></RectangleGeometry> 
                  <EllipseGeometry Center="100 50" RadiusX="40" RadiusY="50"></EllipseGeometry> 
              </GeometryGroup> 
          </Path.Data> 
      </Path> 

      QQ20140822232927_thumb3
      上面的标记的效果和使用两个Path元素的效果相同,但这有一个优点:使用数量更少的较复杂几何图形元素的窗口比具有大量较简单几何图形元素的窗口的性能要高。在只有几十个形状的窗口中这一效果并不明显,但对于需要几百或几千个形状的窗口,这一问题就会变得很明显。 
      当形状相互重叠时,GeometryGroup不是将每个形状简单的进行组合,它使用FillRule属性决定填充区域,并且在GeometryGroup中,椭圆被看作为一个洞,而不是具有不同填充的其他形状,后面的任何内容都可以透过该洞显示。 
      GeometryGroup的另一个优点是可以使用它定义资源,如下所示:

      <Window.Resources> 
          <GeometryGroupx:Key="Geometry"> 
              <RectangleGeometryRect="0 0 100 100"></RectangleGeometry> 
              <EllipseGeometryCenter="100 50" RadiusX="40" RadiusY="50"></EllipseGeometry> 
          </GeometryGroup> 
      </Window.Resources> 
      
      <PathFill="Azure" Stroke="Black" Data="{StaticResource Geometry}" Canvas.Left="148.807" Canvas.Top="5"></Path> 
      <PathFill="Green" Stroke="Beige" Data="{StaticResource Geometry}" Canvas.Left="149" Canvas.Top="120.408"></Path> 
    3. 使用CombinedGeometry融合几何图形
      CombinedGeometry类专门用于组合重叠到一起的形状,与GeometryGroup不同,它只通过Geometry1Geometry2属性提供两个几何图形,它没有包含FillRule属性,而是包含了功能更加强大的GeometryCombineMode属性,它有四种取值:UnionIntersectXorExclude,用于分别求两个形状的并集、交集、异或集、差集。
      虽然CombinedGeometry只能提供两个几何图形进行组合,但是可以通过嵌套CombinedGeometry的方式组合任意复杂的几何图形。
      当为几何图形应用变换时,使用Transform,而不是RenderTransform或LayoutTransform,这是因为几何图形定义了形状,并且所有的变换总是在布局中使用路径之前被引用。
      QQ20140823010725_thumb1 

      <Path Fill="Red" Stroke="Blue" Canvas.Left="100.679" Canvas.Top="24.99">
          <Path.Data>
              <CombinedGeometry>
                  <CombinedGeometry.Geometry1>
                      <CombinedGeometry GeometryCombineMode="Exclude">
                          <CombinedGeometry.Geometry1>
                              <EllipseGeometry RadiusX="70" RadiusY="70" Center="70,70"></EllipseGeometry>
                          </CombinedGeometry.Geometry1>
                          <CombinedGeometry.Geometry2>
                              <EllipseGeometry RadiusX="50" RadiusY="50" Center="70,70"></EllipseGeometry>
                          </CombinedGeometry.Geometry2>
                      </CombinedGeometry>
                  </CombinedGeometry.Geometry1>
                  <CombinedGeometry.Geometry2>
                      <RectangleGeometry Rect="5 60 130 20">
                          <RectangleGeometry.Transform>
                              <RotateTransform CenterX="70" CenterY="70" Angle="-45"></RotateTransform>
                          </RectangleGeometry.Transform>
                      </RectangleGeometry>
                  </CombinedGeometry.Geometry2>
              </CombinedGeometry>
          </Path.Data>
      </Path>
    4. 使用PathGeometry绘制直线和曲线
      PathGeometry是功能最强大的图形,它能够绘制其他所有几何图形能够绘制的内容,并且也能够绘制其他所有几何图形所不能绘制的内容,它的唯一缺点就是语法比较长且更复杂。
      每个PathGeometry对象都是由一个或多个PathFigure对象构建的(存储在PathGeometry.Figures集合中),每个PathFigure对象又是由一系列继承自PathSegment类的线段绘制的形状,下面列出了这些线段类:
      QQ截图20140824204028

      1. LineSegment 直线
        使用LineSegment和PathGeometry类创建简单的线条非常容易,只需要设置StartPoint,并为线条中的每部分增加一条LineSegment直线段,LineSegment.Point标识每条线段的结束点。
        QQ截图20140824210216         

        <Path Fill="Red" Stroke="Black" Canvas.Left="262.144" Canvas.Top="22"> 
            <Path.Data> 
                <PathGeometry> 
                    <PathFigure StartPoint="10,100" IsClosed="True"> 
                        <LineSegment Point="100,100"/> 
                        <LineSegment Point="100,20"/> 
                    </PathFigure> 
                    <PathFigure IsClosed="True"> 
                        <LineSegment Point="90,0"/> 
                        <LineSegment Point="0,80"/> 
                    </PathFigure> 
                </PathGeometry> 
            </Path.Data> 
        </Path> 
      2. ArcSegment 弧线
        弧线实际上是椭圆边缘的一部分,使用PathFigure.StartPoint指定起点,使用ArcSegment.Point指定终点,在两点之间绘制一条曲线。使用Size属性指定椭圆的尺寸。
        IsLargeArc属性:用来设置弧线取自椭圆的哪一部分,默认是false,也就是默认取椭圆上最短的弧线。
        QQ截图20140824220143
        SweepDirection属性:该属性可以是Counterclockwise(逆时针,默认值)或Clockwise。它指定了以两点定义椭圆时的方向。
        QQ截图20140824220152
        QQ截图20140824220252

        <Path Fill="Red" Stroke="Black" Canvas.Left="399" Canvas.Top="72"> 
            <Path.Data> 
                <PathGeometry> 
                    <PathFigure StartPoint="0,50"> 
                        <ArcSegment Point="100,50" Size="60,60" IsLargeArc="True" SweepDirection="Clockwise"/> 
                    </PathFigure> 
                </PathGeometry> 
            </Path.Data> 
        </Path>
      3. BezierSegment 贝赛尔曲线
        贝赛尔曲线使用更复杂的数据公式定义两点间的曲线段,该公式包含的两个控制点决定了曲线的形状。在标记中定义贝赛尔曲线,需要定义三个点,Point1Point2是控制点,Point3是曲线的终点。
        QQ截图20140824223412
        <Path Fill="Red" Stroke="Black" Canvas.Left="262" Canvas.Top="144.54">
            <Path.Data>
                <PathGeometry>
                    <PathFigure StartPoint="10,10">
                        <BezierSegment Point1="100,10" Point2="0,90" Point3="100,100"/>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>
      4. 路径微语言
        以上的直线示例标记代码可以使用路径微语言表示为:        
        <Path Fill="Red" Stroke="Black" Data="M 10 100 L 100 100 L 100 20 Z M 0 0 L 90 0 L 0 80 Z " ></Path> 

        还可以精简为:       

        <Path Fill="Red" Stroke="Black" Data="M10 100 L100 100 L100 20 Z M0 0 L90 0 L0 80 Z " ></Path> 

        当使用微语言创建几何图形时,实际上是创建了一个StreamGeometry对象,而不是PathGeometry对象,因此,以后在代码中不能修改图形,如果希望修改,可以显式的创建PathGeometry对象,但使用相同的语法定义其PathFigure对象集合。如下所示:      

        <Path Fill="Red" Stroke="Black" Canvas.Left="490" Canvas.Top="22"> 
            <Path.Data> 
                <PathGeometry Figures="M 10 100 L 100 100 L 100 20 Z M 0 0 L 90 0 L 0 80 Z"></PathGeometry> 
            </Path.Data> 
        </Path>


        115
        以上命令,还可以使用小写来表明坐标是相对于前一个点的相对坐标,而不是绝对坐标

      5. 使用几何图形进行剪裁
        几何图形不仅可以用于Path元素,也可以用于设置Clip属性,所有元素都提供了Clip属性。示例如下:
        QQ截图20140825004234        
        <Window.Resources> 
            <GeometryGroup x:Key="GeometryForClip" 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> 
        <Button Clip="{StaticResource GeometryForClip}" >A Button</Button> 
        <Image Source="images/DSC_0937.jpg" Clip="{StaticResource GeometryForClip}" /> 

        使用剪裁存在一个限制,设置的剪裁不会考虑元素的尺寸,当元素的尺寸有变化时,剪裁区域不会变化。

  2. 图画
    Geometry表示一个形状或路径,抽象的Drawing类扮演了一个互补的角色,它表示一个2D图画。尽管有如下的几种图画类,但只有GeometryDrawing类能够使用几何图形,它增加了决定如何绘制图形的笔画和填充细节。从字面意思可以理解DeometryDwawing类为包含几何图形的图画。
    QQ截图20140825203937

    因为继承自Drawing的类不是元素,所以它们不能被放置到用户界面中,为了显示一个图画,需要使用以下三个类中的一个。
    QQ截图20140825204428 
    如下定义一个三角形的PathGeometry对象:      

    <PathGeometry> 
        <PathFigure StartPoint="20,20" IsClosed="True" > 
            <LineSegment Point="120,20"></LineSegment> 
            <LineSegment Point="120,90"></LineSegment> 
        </PathFigure> 
    </PathGeometry> 

    以下的标记是使用以上定义的PathGeometry对象,它定义了一个形状(一个三角形),创建一个GeometryDrawing对象,它定义形状的外观(具有蓝色边界的黄色三角形),然后再使用GeometryDrawing对象创建DrawingImage对象:        

    <DrawingImage> 
        <DrawingImage.Drawing> 
            <GeometryDrawing Brush="Yellow"> 
                <GeometryDrawing.Pen> 
                    <Pen Brush="Blue" Thickness="3"/> 
                </GeometryDrawing.Pen> 
                <GeometryDrawing.Geometry> 
                    <PathGeometry> 
                        <PathFigure StartPoint="20,20" IsClosed="True" > 
                            <LineSegment Point="120,20"></LineSegment> 
                            <LineSegment Point="120,90"></LineSegment> 
                        </PathFigure> 
                    </PathGeometry> 
                </GeometryDrawing.Geometry> 
            </GeometryDrawing> 
        </DrawingImage.Drawing> 
    </DrawingImage>

     

posted @ 2014-08-24 21:10  qing_sun  阅读(591)  评论(0编辑  收藏  举报