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揭秘》

  • 相关阅读:
    Unity The Method Signature Matching Rule
    Unity The Property Matching Rule
    Unity The Type Matching Rule
    Unity The Custom Attribute Matching Rule
    Unity The Member Name Matching Rule
    Unity No Policies
    Unity The Return Type Matching Rule
    Unity The Parameter Type Matching Rule
    Unity The Namespace Matching Rule
    关于TSQL递归查询的(转)
  • 原文地址:https://www.cnblogs.com/lsxqw2004/p/4629171.html
Copyright © 2011-2022 走看看