zoukankan      html  css  js  c++  java
  • WPF,Silverlight与XAML读书笔记第三十四 可视化效果之2D变换

    说明:本系列基本上是《WPF揭秘》的读书笔记。在结构安排与文章内容上参照《WPF揭秘》的编排,对内容进行了总结并加入一些个人理解。

    Transform - 变换主要用于实现旋转缩放等效果,WPF中2D变换由System.Windows.Media命名空间的Transform类来处理。应用变换会影响元素的尺寸和位置。

    每个FrameworkElement都有如下两个类型的Transform属性,这些是变换可以应用的对象:

    • LayoutTransform:其在对元素布局以前被应用。
    • RenderTransform:(FrameworkElement继承自UIElement获得)其在布局结束后,元素被在渲染前应用。

    另外我们也可以通过Brush.Transform属性将变化应用到Brush, 包括像IamgeBrush等。通过定义Geometry.Transform属性可以对集合形状进行变形等等。

    这两个属性的变换信息可以通过<TransformGroup>元素来设置,这其中可以定义单个变换或一组变换的集合。(如果只定义一个转换,可以不写<TransformGroup>而只是写具体的转换)。

    以上这两种不同类型变化的效果可以由下列示例看出(以RotateTransform示例):

    前者为LayoutTransform,后者为RenderTransform:

    XAML:

     1 <StackPanel Width="66" HorizontalAlignment="Left">
     2     <Button>Top</Button>
     3     <Button>
     4         <Button.LayoutTransform>
     5             <RotateTransform Angle="45" />
     6         </Button.LayoutTransform>
     7         Middle
     8     </Button>
     9     <Button>Bottom</Button>
    10 </StackPanel>
    11 <StackPanel Width="66">
    12     <Button>Top</Button>
    13     <Button>
    14         <Button.RenderTransform>
    15             <RotateTransform Angle="45" />
    16         </Button.RenderTransform>
    17         Middle
    18     </Button>
    19     <Button>Bottom</Button>
    20 </StackPanel>

    运行效果图:

        如示例可以看出,布局前发生的变换(FlyoutTransform)会把其他元素挤开。而布局后发生的变换(RenderTransform)不会影响其他元素的布局位置。

    UIElement(FrameworkElement)中有一个RenderTransformOrigin属性表示变换的开始点(在变换过程中这个点保持固定)。(LayoutTransform没有同等的概念,被变换元素定位由父面板布局规则控制。)

    RenderTransformOrigin属性类型为System.Windows.Point,默认值为(0,0),表示左上角,另外(0,1)表示左下角,(1,0)表示右上角,(1,1)表示右下角。如果数字大于1则表示原点在元素之外,另外数字小于1表示原点在元素内部,如(0.5,0.5)表示元素中心。

    XAML中,可以通过RenderTransformOrigin="0.5,0.5",这样的方式来设置,这主要归功于System.Windows.PointConverter。

    变化主要用于产生一些动画等效果,下面将逐个介绍WPF中内建的2D变换效果,这些变换的类都位于System.Windows.Media命名空间中:

    1. RotateTransform

    RotateTransform用于在X-Y平面以特定点进行特定角度的旋转。主要属性介绍如下:

    如下3个浮点类型属性控制元素的旋转:

    • Angle:旋转角度,单位为度数,默认值为0,默认旋转方向为顺时针。
    • CenterX:旋转的水平中心,默认值为0。
    • CenterY:旋转的垂直中心,默认值为0。

    水平旋转中心与垂直旋转中心相结合即是旋转点,由上可看出这点默认值为(0,0),即包含选择元素的容器的左上角。

        注意,(CenterX, CenterY)只有RotateTransform被应用为RenderTransform时才有效,因为这两个属性影响元素的布局,而LayoutTransform的布局是受父元素控制的,所以对这些属性不敏感。

    细节:UIElement的RenderTransformOrigin属性与RotateTransform的CenterX与CenterY属性的不同。

    1. CenterX与CenterY可以用绝对坐标定位原点,而RenderTransform只允许用相对定位。这个区别可以举这样一个小例子:

      如一个宽度为20的元素,其右上角用CenterX和CenterY表示则分别为20,0。而RenderTransformOrigin表示则为(1,0)。

    2. 当RenderTransform包含多个Transform时,RenderTransformOrigin会对所有这些Transform产生影响。当这其中包含有RotateTransform且其CenterX和CenterY都有设置时,它们将被组合来计算最终的原点。
    3. 当CenterX和CenterY用于数据绑定时,将比RenderTransformOrigin类型方便。
    4. 如果是围绕元素的中心做变换等情况,则RenderTransformOrigin这种相对的方式更简单。如果用CenterX和CenterY完成,则需要编程计算得到绝对位置。

    RenderTransform也可以用于内容控件其中的内容,可以参考如下例子:

    1 <Button>
    2     <TextBlock RenderTransformOrigin="0.5,0.5">
    3         <TextBlock.RenderTransform>
    4             <RotateTransform Angle="45"/>
    5         </TextBlock.RenderTransform>
    6         Middle
    7     </TextBlock>
    8 </Button>

    RenderTransform构造函数有如下两类重载,可以接受这样的参数:

    • 一个角度值
    • 一个角度值,一个中心值

    2. ScaleTransform

    在X-Y平面进行缩放,即将元素在水平,垂直,或者水平垂直两个方向上扩大或者缩小一个元素。

    其有4个浮点类型的属性控制这个功能:

    • ScaleX:元素宽度的缩放倍数
    • ScaleY:元素高度的缩放倍数
    • CenterX:水平缩放的原点
    • CenterY:垂直缩放的原点

    属性的使用上,0.5的ScaleX/ScaleY会把水平/垂直方向缩小一半,而大小为2的ScaleX/ScaleY会把水平垂直大小放大一倍。而CenterX与CenterY则与RotateTransform中同名属性一样只在RenderTransform模式下有效。

        另外显而易见的是CenterX只有在ScaleX不为1时才能起作用。CenterY只有当ScaleY不为1时才起作用。CenterX与CenterY的默认值均为0,即变换元素所在容器的左上角,这样默认情况下水平向缩放会向右进行,垂直向缩放会向下进行。当CenterX与CenterY被设置为大于0的值后,变换也就会同时向左与向上进行。

        ScaleTransform也有重载的构造函数以方便在代码中创建变换。

    提示:ScaleTransform与Stretch Alignment之间的交互。

    当把ScaleTransform作为LayoutTransform应用到一个已经在伸缩尺度内拉伸的元素上,只有当ScaleTransform拉伸的量比控件本身的拉伸量大时,这个变换才会有效果。

    提示:ScaleTransform变换对FrameworkElement的ActualHeight与ActualWidth,及对UIElement的RenderSize属性的影响。

    如前文所述,控件的ActualHeight属性,ActualWidth属性的值与RenderSize的Height,Width属性分别都是相同的。在应用ScaleTransform变换后,虽然可视化效果上改变了,但这些属性值都不会被改变,是一种"虚报"的效果。

    提示:ScaleTransaction对Margin与Padding的影响

    Padding与内部内容会被一起缩放,但是Padding值不会变化,虽然视觉效果发生变化,这类似上一提示中的"虚报"现象。Margin不会受此影响。

     

    最后仍然是一段简单的代码:

    1 <Rectangle Fill="Pink" Stroke="Azure" Width="88" Height="66">
    2     <Rectangle.RenderTransform>
    3         <ScaleTransform ScaleX="2" CenterX="30" />
    4     </Rectangle.RenderTransform>
    5 </Rectangle>

    3. SkewTransform

    通过4个浮点属性来按元素的X轴与Y轴进行倾斜。直观上来说如果是一个正方形进行SkewTransform变换后看起来为一个平行四边形。

    • AngleX:水平倾斜的角度,默认值为0。
    • AngleY:垂直倾斜的角度,默认值为0。
    • CenterX:水平倾斜的原点。默认值为0。
    • CenterY:垂直倾斜的原点。默认值为0。

        这些属性与ScaleTransform中的属性,用法非常类似,这里不再赘述,给出一段代码:

    1 <Rectangle Fill="Pink" Stroke="Azure" Width="88" Height="66">
    2     <Rectangle.RenderTransform>
    3         <SkewTransform AngleX="36" />
    4     </Rectangle.RenderTransform>
    5 </Rectangle>

    4. TranslateTransform

    沿X轴或Y轴将对像移动指定的距离,有两个浮点属性控制元素移动。

    • X:水平移动量,默认值为0
    • Y:垂直移动量,默认值为0

    在LayoutTransform下此变化没有任何效果,在RenderTransform利用此变化可以按用户的操作来形成动画效果。当X,Y为正值时,变换对象将分别向右方与下方移动,反之为负值时将向左方与上方移动。

    给出一段简单的代码:

    1 <Rectangle Fill="Pink" Stroke="Azure" Width="88" Height="66">
    2     <Rectangle.RenderTransform>
    3         <TranslateTransform X="50" Y="-50"/>
    4     </Rectangle.RenderTransform>
    5 </Rectangle>

    5. MatrixTransform

    MatrixTransform用于自定义2D变换效果。这种变换效果的本质是一个System.Windows.Media.Matrix类型的Matrix属性。这种类型可以表示一个各元素的含义如下的3x3的矩阵:

    其中矩阵最后一列值是固定的(0 0 1),而前两列值可由Matrix类型属性来设置(前两列的这些属性的名称与Matrix类型中的属性同名)。

        所有之前介绍的变换都可以使用MatrixTransform来表示。

    提示:MatrixTransform的类型转换器

    MatrixTransform是唯一一个拥有类型转换器(TransformConverter这个转换器)的变换,这样在XAML中就可以使用一个字符串来设置Matrix属性。例如:

    <Button RenderTransform="1,0,0,1,10,20" />

    这条语句将按钮向右移动10个元素,向下移动20个元素。

    深入分析其中关系,有如下对应:

    所以很容易看出,"1,0,0,1,0,0 "就表示不做变换,而上文的设置就相当于设置了TranslateTransform的X属性与Y属性。而设置缩放的话可以设置第一个与第四个值,作用就相当于设置ScaleTransform的ScaleX与ScaleY。

    给出一个简单的例子:

    1 <Rectangle Fill="Pink" Stroke="Azure" Width="88" Height="66">
    2     <Rectangle.RenderTransform>
    3         <MatrixTransform Matrix="1 0 1 2 0 1"/>
    4     </Rectangle.RenderTransform>
    5 </Rectangle>

    运行时效果如下图:

    变换组合

    有多种方式可以将变换组合起来:

    1. 同时使用LayoutTransform变换和RenderTransform变换。
    2. 也可以使用一个适当的MatrixTransform来表示多条转换。
    3. 使用TransformGroup类。

    TransformGroup类是一个派生自Transform的类(所以可以像使用ScaleTransform或TranslateTransform等一样使用TransformGroup完成RenderTransform或LayoutTransform的设置),但TransformGroup类主要为组合"变换"而存在。这种组合通过设置TransformGroup的Children集合属性来完成。而Children属性作为一个内容属性在XAML就可以使用如下方式来设置:

     1 <Button>
     2     <Button.RenderTransform>
     3         <TransformGroup>
     4             <RotateTransform Angle="45" />
     5             <ScaleTransform ScaleX="5" ScaleY="1"/>
     6             <SkewTransform AngleX="30"/>
     7         </TransformGroup>
     8 </Button.RenderTransform>
     9 OK
    10 </Button>

    这段代码对目标对象进行了基于X轴45的旋转,在X轴方向进行5倍放大,基于X轴进行30度的倾斜。

    内幕:WPF处理TransformGroup的方式

    在内部WPF首先将TransformGroup计算为一个类似MatrixTransform的Matrix属性类似的值并将其应用到目标元素上,以提高性能。

    提示:可以将多个相同类型的变换应用到一个TransformGroup中。如,两个45度的RotateTransform放在一起可以产生一个90度RotateTransform的效果。

     

    提示:对变换的支持。

    所有宿主非WPF的元素不支持以上这些变化,如后文要介绍的HwndHost。另外Frame这个用来承载Html内容的元素本身支持变换,但其发生变换时内部元素不会发生变换。

      

    本文完

    参考:

    《WPF揭秘》

  • 相关阅读:
    MS SQL数据库在FAT32格式下数据大小不能超过4G
    屏蔽五项功能 让Windows XP极速狂飙
    FastReport安装
    电脑总是死机
    Win XP控制台命令详解
    一个人独自去看海
    my best love lover
    我的第一个blog
    我的学习生涯
    Codeforces Round #323 (Div. 2) C. GCD Table
  • 原文地址:https://www.cnblogs.com/lsxqw2004/p/4629171.html
Copyright © 2011-2022 走看看