WPF dynamic transform (RenderTransform and LayoutTransform)

Keywords: C# WPF

Layout system

WPF provides two transformation methods, LayoutTransform and RenderTransform. Literally, LayoutTransform is a layout transform, while RenderTransform is a rendering transform.

In WPF, many drawing tasks can be made easier by using transform - an object that changes the way the shape or element is drawn by switching the coordinate system used by the shape or element without notice. In WPF, most of the transformed classes inherit from System.Windows.Media.Trandform. Here is a list of these classes:

  • TranslateTransform: moves the coordinate system a certain distance.
  • RolateTransform: rotates the coordinate system.
  • ScaleTransform: zoom in or out of the minimum coordinate system.
  • SkewTransform: distorts the coordinate system by tilting a certain angle.
  • MatrixTransform: modifies the coordinate system using the product of the provided matrix.
  • TransfromGroup: combines multiple transforms.

  Transform shape

In order to transform the shape, specify the RenderTransform attribute as the transformation object you want to use. According to the transformation object used, you need to fill in different attributes to configure the transformation object, that is, some of the classes listed above. For example:

 <Button Content="I AM Rotated 35" Width="100">
         <Button.RenderTransform>
                 <RotateTransform Angle="35"></RotateTransform>
           </Button.RenderTransform>
 </Button>

Here we rotate the button 35 degrees. However, RenderTransform is not the only transform related attribute defined in WPF accumulation. The FrameworkElement class also defines a LayoutTransform property. The LayoutTransform attribute transforms elements in the same way, but it performs work before layout, which is more expensive than RenderTransform. Let's see the difference between the two:

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <StackPanel>
            <Button Content="I AM Rotated 35" Width="100">
                <Button.RenderTransform>
                    <RotateTransform Angle="35"></RotateTransform>
                </Button.RenderTransform>
            </Button>
            <Button>I am not</Button>
        </StackPanel>

        <StackPanel Grid.Row="1">
            <Button Content="I AM Rotated 35" Width="100">
                <Button.LayoutTransform>
                    <RotateTransform Angle="35"></RotateTransform>
                </Button.LayoutTransform>
            </Button>
            <Button>I am not</Button>
        </StackPanel>
    </Grid>

The window contains two stackpanels, each with two buttons. One uses the RenderTransform attribute and the other uses the LayoutTransform. When the first StackPanel lays out the two buttons, the first button is positioned normally, and the change button is rotated immediately before rendering. Therefore, the rotated buttons are overlapped below. In the second StackPanel container, the first button is rotated after rendering, that is, LayoutTransform performs its work before layout. Take a look at the effect:

  Translatetransform:

It contains X and Y attributes. Take the original object as the coordinate origin (0,0), and then translate and transform to the x-axis and y-axis.

<Canvas>
         <Image Canvas.Top="160" Canvas.Left="140" Source="sun.jpg" Opacity="0.5"></Image>
         <Image Canvas.Top="160" Canvas.Left="140"  Source="sun.jpg">
             <Image.RenderTransform>
                 <TranslateTransform X="120" Y="120"></TranslateTransform>
             </Image.RenderTransform>
         </Image>
</Canvas>

RotateTransform:

Including the attributes Angle, CenterX and CenterY

<Canvas>
         <Image Canvas.Top="160" Canvas.Left="140" Source="sun.jpg" Opacity="0.5"></Image>
         <Image Canvas.Top="160" Canvas.Left="140"  Source="sun.jpg">
             <Image.RenderTransform>
                 <RotateTransform Angle="45" CenterX="0" CenterY="0"></RotateTransform>
             </Image.RenderTransform>
         </Image>
</Canvas>

 

  Scaletransform:

It includes attributes ScaleX, ScaleY, CenterX and CenterY, where ScaleX and ScaleY represent the multiple of the object scaling on the X and Y axes, and CenterX is used   and   The CenterY property specifies a center point.

<Canvas>
         <Image Canvas.Top="160" Canvas.Left="140" Source="sun.jpg" Opacity="0.5"></Image>
         <Image Canvas.Top="160" Canvas.Left="140"  Source="sun.jpg">
             <Image.RenderTransform>
                 <ScaleTransform ScaleX="0.5" ScaleY="0.5"></ScaleTransform>
             </Image.RenderTransform>
         </Image>
</Canvas>

 

Skewtransform:  

Includes attributes AngleX, AngleY, CenterX, CenterY. Where AngleX is used to tilt the element relative to the X axis, and AngleY is the tilt angle of the element around the Y axis. Similarly, CenterX and CenterY are the center point locations.

<Canvas>
         <Image Canvas.Top="160" Canvas.Left="140" Source="sun.jpg" Opacity="0.5"></Image>
         <Image Canvas.Top="160" Canvas.Left="140"  Source="sun.jpg">
             <Image.RenderTransform>
                 <SkewTransform AngleX="30" AngleY="10"></SkewTransform>
             </Image.RenderTransform>
         </Image>
</Canvas>

TransformGroup:  

Scale, rotate, twist and other change effects are combined. The above four basic changes are only single changes. If you want to realize the superposition of multiple effects, you must use TransformGroup, otherwise an error will be reported. The function of TransformGroup is similar to the function embedded in the StackPanel in the control layout. It is to combine a variety of change elements into a change container.

<Canvas Width="640" Height="480">
         <Rectangle Canvas.Top="20" Canvas.Left="200" Width="400" Height="300" Stroke="Black" StrokeThickness="5">
             <Rectangle.RenderTransform>
                 <TransformGroup>
                     <!--RotateTransform Transformation-->
                     <RotateTransform Angle="10"></RotateTransform>
                     <!--SkewTransform Transformation-->
                     <SkewTransform AngleX="-10" AngleY="30" CenterX="20" CenterY="50"></SkewTransform>
                 </TransformGroup>
             </Rectangle.RenderTransform>
             <Rectangle.Fill>
                 <ImageBrush ImageSource="sun.jpg"></ImageBrush>
             </Rectangle.Fill>
         </Rectangle>
 </Canvas>

MatrixTransform matrix transformation:

In fact, it is the bottom implementation code of other deformation classes. Other classes are based on the extension of this class, so that users can apply it more simply and conveniently. As for MatrixTransform, the corresponding deformation effect is obtained through a matrix algorithm.

The value of the third column in the matrix is fixed!


Principle:

The original coordinates (x0, Y0) can be obtained by matrix multiplication through this 3 * 3 matrix (x0 * M11+x0 * M21,y0 * M12+y0 * M22), and then (OffsetX,OffsetY) can be added to obtain the new coordinates (x1,y1). That is, the final coordinates (x1,y1):   x1 =    x0 * M11 + x0 * M21 + OffsetX  ,  y1 = y0 * M12 + y0 * M22 + OffsetY.

<!--Source code usage--> 
<MatrixTransform Matrix="M11 M12 M21 M22 OffsetX OffsetY"></MatrixTransform>

  The following uses MatrixTransform matrix transformation to realize the above five basic transformation effects.

<Canvas Width="1200" Height="300">
         <StackPanel Orientation="Horizontal" Canvas.Top="50">
             <!-- TranslateTransform translation -->
             <Image Source="Images/adobe_Ai.png" Height="100" Width="100" Stretch="Fill"
                    Margin="10" Opacity="0.5"></Image>
             <Image Source="Images/adobe_Ai.png" Height="100" Width="100" Stretch="Fill"
                    Margin="10">
                 <Image.RenderTransform>
                     <MatrixTransform Matrix="1 0 0 1 -80 30"></MatrixTransform>
                 </Image.RenderTransform>
             </Image>
 
             <!-- RotateTransform rotate -->
             <Image Source="Images/adobe_Dw.png" Height="100" Width="100" Stretch="Fill"
                    Margin="10" Opacity="0.5"></Image>
             <Image Source="Images/adobe_Dw.png" Height="100" Width="100" Stretch="Fill"
                    Margin="10">
                 <Image.RenderTransform>
                     <!-- 90°rotate -->
                     <MatrixTransform Matrix="0 1 -1 0 30 0"></MatrixTransform>
                 </Image.RenderTransform>
             </Image>
 
             <!-- ScaleTransform zoom -->
             <Image Source="Images/adobe_Fl.png" Height="100" Width="100" Stretch="Fill"
                    Margin="10" Opacity="0.5"></Image>
             <Image Source="Images/adobe_Fl.png" Height="100" Width="100" Stretch="Fill"
                    Margin="10">
                 <Image.RenderTransform>
                     <!--Zoom in 1.5 times-->
                     <MatrixTransform Matrix="1.5 0 0 1.5 -80 0"></MatrixTransform>
                 </Image.RenderTransform>
             </Image>
 
             <!-- SkewTransform Twist tilt -->
             <Image Source="Images/adobe_Fw.png" Height="100" Width="100" Stretch="Fill"
                    Margin="10" Opacity="0.5"></Image>
             <Image Source="Images/adobe_Fw.png" Height="100" Width="100" Stretch="Fill"
                    Margin="10">
                 <Image.RenderTransform>
                     <!-- x Axis tilt -->
                     <MatrixTransform Matrix="1 0 1 1 -80 0"></MatrixTransform>
                 </Image.RenderTransform>
             </Image>
 
             <!-- TransformGroup Twist, scale -->
             <Image Source="Images/adobe_Id.png" Height="100" Width="100" Stretch="Fill"
                    Margin="10" Opacity="0.5"></Image>
             <Image Source="Images/adobe_Id.png" Height="100" Width="100" Stretch="Fill"
                    Margin="10">
                 <Image.RenderTransform>
                     <!-- x Axis tilt -->
                     <!--Zoom in 1.5 times-->
                     <MatrixTransform Matrix="1.5 0 1 1.5 -120 0"></MatrixTransform>
                 </Image.RenderTransform>
             </Image>
         </StackPanel>
 </Canvas>

 

 

Posted by sunnyk on Wed, 01 Dec 2021 02:12:52 -0800