Vue d’ensemble des transformations

Découvrez comment utiliser des transformations dans l’API Windows Runtime en modifiant les systèmes de coordonnées relatifs d’éléments de l’interface utilisateur. Cela peut être utilisé pour ajuster l’apparence d’éléments XAML individuels, tels que la mise à l’échelle, la rotation ou la transformation de la position dans l’espace x-y.

Qu’est-ce qu’une transformation ?

Une transformation définit comment mapper ou transformer des points d’un espace de coordonnées à un autre espace de coordonnées. Lorsqu’une transformation est appliquée à un élément d’interface utilisateur, elle modifie la façon dont cet élément d’interface utilisateur est rendu à l’écran dans le cadre de l’interface utilisateur.

Considérez les transformations en quatre classifications générales : traduction, rotation, mise à l’échelle et asymétrie (ou shérif). Pour les besoins de l’utilisation d’API graphiques pour modifier l’apparence des éléments d’interface utilisateur, il est généralement plus simple de créer des transformations qui définissent une seule opération à la fois. Par conséquent, Windows Runtime définit une classe discrète pour chacune de ces classifications de transformation :

Parmi ceux-ci, vous êtes susceptible d’utiliser TranslateTransform et ScaleTransform le plus souvent pour les scénarios d’interface utilisateur.

Vous pouvez combiner des transformations et il existe deux classes Windows Runtime qui prennent en charge ceci : CompositeTransform et TransformGroup. Dans un CompositeTransform, les transformations sont appliquées dans cet ordre : mise à l’échelle, asymétrie, rotation, traduction. Utilisez TransformGroup au lieu de CompositeTransform si vous souhaitez que les transformations soient appliquées dans un ordre différent. Pour plus d’informations, consultez CompositeTransform.

Transformations et disposition

Dans la disposition XAML, les transformations sont appliquées une fois la passe de disposition terminée, de sorte que les calculs d’espace disponibles et d’autres décisions de disposition ont été pris avant l’application des transformations. Étant donné que la disposition est en premier lieu, vous obtiendrez parfois des résultats inattendus si vous transformez des éléments qui se trouvent dans une cellule Grid ou un conteneur de disposition similaire qui alloue de l’espace pendant la disposition. L’élément transformé peut apparaître tronqué ou masqué, car il tente de dessiner dans une zone qui n’a pas calculé les dimensions post-transformation lors de la division de l’espace dans son conteneur parent. Vous devrez peut-être expérimenter les résultats de la transformation et ajuster certains paramètres. Par exemple, au lieu de s’appuyer sur le dimensionnement adaptatif de la disposition et de l’étoile, vous devrez peut-être modifier les propriétés du Centre ou déclarer des mesures de pixel fixes pour l’espace de disposition pour vous assurer que les allots parents suffisamment d’espace.

Remarque de migration : Windows Presentation Foundation (WPF) a une propriété LayoutTransform qui a appliqué des transformations avant la passe de disposition. Toutefois, le code XAML Windows Runtime ne prend pas en charge une propriété LayoutTransform . (Microsoft Silverlight n’a pas non plus cette propriété.)

En guise d’alternative, le kit de ressources Communauté Windows fournit LayoutTransformControl, qui applique des transformations de matrice sur n’importe quel FrameworkElement de votre application.

Application d’une transformation à un élément d’interface utilisateur

Lorsque vous appliquez une transformation à un objet, vous le faites généralement pour définir la propriété UIElement.RenderTransform. La définition de cette propriété ne modifie pas littéralement le pixel d’objet par pixel. Ce que fait réellement la propriété est l’application de la transformation dans l’espace de coordonnées local dans lequel cet objet existe. Ensuite, la logique de rendu et l’opération (post-disposition) restituent les espaces de coordonnées combinés, ce qui le rend semblable à l’apparence de l’objet et potentiellement sa position de disposition (si TranslateTransform a été appliqué).

Par défaut, chaque transformation de rendu est centrée à l’origine du système de coordonnées local de l’objet cible , son (0,0). La seule exception est une TranslateTransform, qui n’a aucune propriété centrale à définir, car l’effet de traduction est le même, quel que soit l’emplacement où il est centré. Mais les autres transformations ont chacune des propriétés qui définissent les valeurs CenterX et CenterY .

Chaque fois que vous utilisez des transformations avec UIElement.RenderTransform, n’oubliez pas qu’il existe une autre propriété sur UIElement qui affecte le comportement de la transformation : RenderTransformOrigin. Ce que RenderTransformOrigin déclare est que la transformation entière doit s’appliquer au point par défaut (0,0) d’un élément ou à un autre point d’origine dans l’espace de coordonnées relatif de cet élément. Pour les éléments classiques, (0,0) place la transformation en haut à gauche. Selon l’effet souhaité, vous pouvez choisir de modifier RenderTransformOrigin plutôt que d’ajuster les valeurs CenterX et CenterY sur les transformations. Notez que si vous appliquez à la fois les valeurs RenderTransformOrigin et CenterX / CenterY, les résultats peuvent être assez confus, en particulier si vous animez l’une des valeurs.

À des fins de test de positionnement, un objet auquel une transformation est appliquée continue de répondre à l’entrée d’une manière attendue qui est cohérente avec son apparence visuelle dans l’espace x-y. Par exemple, si vous avez utilisé un TranslateTransform pour déplacer un rectangle de 400 pixels ultérieurement dans l’interface utilisateur, ce rectangle répond aux événements PointerPressed lorsque l’utilisateur appuie sur le point où le Rectangle apparaît visuellement. Vous n’obtiendrez pas de faux événements si l’utilisateur appuie sur la zone où le rectangle était avant d’être traduit. Pour toutes les considérations relatives à z-index qui affectent les tests de positionnement, l’application d’une transformation ne fait aucune différence ; l’index z qui régit l’élément qui gère les événements d’entrée d’un point dans l’espace x-y est toujours évalué à l’aide de l’ordre enfant tel qu’il est déclaré dans un conteneur. Cet ordre est généralement le même que l’ordre dans lequel vous déclarez les éléments en XAML, bien que pour les éléments enfants d’un objet Canvas, vous pouvez ajuster l’ordre en appliquant la propriété jointe Canvas.ZIndex aux éléments enfants.

Autres propriétés de transformation

Animation d’une transformation

Les objets Transform peuvent être animés. Pour animer une transformation, appliquez une animation d’un type compatible à la propriété que vous souhaitez animer. Cela signifie généralement que vous utilisez des objets DoubleAnimation ou DoubleAnimationUsingKeyFrames pour définir l’animation, car toutes les propriétés de transformation sont de type Double. Les animations qui affectent une transformation utilisée pour une valeur UIElement.RenderTransform ne sont pas considérées comme des animations dépendantes, même si elles ont une durée différente de zéro. Pour plus d’informations sur les animations dépendantes, consultez animations storyboarded.

Si vous animez des propriétés pour produire un effet similaire à une transformation en termes d’apparence visuelle nette( par exemple, animer la largeur et la hauteur d’un FrameworkElement plutôt que d’appliquer un TranslateTransform), ces animations sont presque toujours traitées comme des animations dépendantes. Vous devrez activer les animations et il peut y avoir des problèmes de performances significatifs avec l’animation, en particulier si vous essayez de prendre en charge l’interaction utilisateur pendant que cet objet est animé. Pour cette raison, il est préférable d’utiliser une transformation et de l’animer plutôt que d’animer une autre propriété où l’animation serait traitée comme une animation dépendante.

Pour cibler la transformation, il doit y avoir une transformation existante en tant que valeur pour RenderTransform. Vous placez généralement un élément pour le type de transformation approprié dans le code XAML initial, parfois sans propriétés définies sur cette transformation.

Vous utilisez généralement une technique de ciblage indirect pour appliquer des animations aux propriétés d’une transformation. Pour plus d’informations sur la syntaxe de ciblage indirect, consultez les animations storyboarded et la syntaxe property-path.

Les styles par défaut pour les contrôles définissent parfois des animations de transformations dans le cadre de leur comportement d’état visuel. Par exemple, les états visuels de ProgressRing utilisent des valeurs RotateTransform animées pour « tourner » les points de l’anneau.

Voici un exemple simple d’animation d’une transformation. Dans ce cas, il anime l’angle d’un RotateTransform pour faire tourner un rectangle en place autour de son centre visuel. Cet exemple nomme le RotateTransform de sorte qu’il n’a pas besoin de ciblage d’animation indirecte, mais vous pouvez également laisser la transformation sans nom, nommer l’élément auquel la transformation est appliquée et utiliser le ciblage indirect tel que (UIElement.RenderTransform).(RotateTransform.Angle).

<StackPanel Margin="15">
  <StackPanel.Resources>
    <Storyboard x:Name="myStoryboard">
      <DoubleAnimation
       Storyboard.TargetName="myTransform"
       Storyboard.TargetProperty="Angle"
       From="0" To="360" Duration="0:0:5" 
       RepeatBehavior="Forever" />
    </Storyboard>
  </StackPanel.Resources>
  <Rectangle Width="50" Height="50" Fill="RoyalBlue"
   PointerPressed="StartAnimation">
    <Rectangle.RenderTransform>
      <RotateTransform x:Name="myTransform" Angle="45" CenterX="25" CenterY="25" />
    </Rectangle.RenderTransform>
  </Rectangle>
</StackPanel>
void StartAnimation (object sender, RoutedEventArgs e) {
    myStoryboard.Begin();
}

Prise en compte des systèmes de coordonnées de référence au moment de l’exécution

UIElement contient une méthode nommée TransformToVisual, qui peut générer un Transform qui met en corrélation les systèmes de coordonnées de référence pour deux éléments d’interface utilisateur. Vous pouvez l’utiliser pour comparer un élément au cadre de référence de coordonnées par défaut de l’application si vous transmettez le visuel racine comme premier paramètre. Cela peut être utile si vous avez capturé un événement d’entrée à partir d’un autre élément, ou si vous essayez de prédire le comportement de disposition sans demander réellement une passe de disposition.

Les données d’événement obtenues à partir d’événements de pointeur permettent d’accéder à une méthode GetCurrentPoint, où vous pouvez spécifier un paramètre relativeTo pour modifier le cadre de coordonnées de référence à un élément spécifique plutôt que la valeur par défaut de l’application. Cette approche applique simplement une transformation de traduction en interne et transforme les données de coordonnées x-y pour vous lorsqu’elle crée l’objet PointerPoint retourné.

Description mathématique d’une transformation

Une transformation peut être décrite en termes de matrice de transformation. Une matrice 3×3 est utilisée pour décrire les transformations dans un plan x-y à deux dimensions. Les matrices de transformation affine peuvent être multipliées pour former n’importe quel nombre de transformations linéaires, telles que la rotation et l’asymétrie (shérif), suivies de la traduction. La dernière colonne d’une matrice de transformation affine est égale à (0, 0, 1), vous devez donc spécifier uniquement les membres des deux premières colonnes de la description mathématique.

La description mathématique d’une transformation peut vous être utile si vous avez un arrière-plan mathématique ou une connaissance des techniques de programmation graphique qui utilisent également des matrices pour décrire les transformations de l’espace de coordonnées. Il existe une classe dérivée de transformation qui vous permet d’exprimer une transformation directement en termes de sa matrice 3×3 : MatrixTransform. MatrixTransform a une propriété Matrix, qui contient une structure qui a six propriétés : M11, M12, M21, M22, OffsetX et OffsetY. Chaque propriété Matrix utilise une valeur double et correspond aux six valeurs pertinentes (colonnes 1 et 2) d’une matrice de transformation affine.

Colonne 1 Colonne 2 Colonne 3
M11 M12 0
M21 M22 0
OffsetX OffsetY 1

Toute transformation que vous pouvez décrire avec un objet TranslateTransform, ScaleTransform, RotateTransform ou SkewTransform peut être décrite de façon égale par une matrice avec une valeur Matrix. Toutefois, vous utilisez généralement TranslateTransform et les autres, car les propriétés de ces classes de transformation sont plus faciles à conceptualiser que de définir les composants vectoriels dans une matrice. Il est également plus facile d’animer les propriétés discrètes des transformations ; Une matrice est en fait une structure et non un DependencyObject, de sorte qu’elle ne peut pas prendre en charge les valeurs individuelles animées.

Certains outils de conception XAML qui vous permettent d’appliquer des opérations de transformation sérialisent les résultats en tant que MatrixTransform. Dans ce cas, il est préférable d’utiliser à nouveau le même outil de conception pour modifier l’effet de transformation et sérialiser à nouveau le code XAML, plutôt que d’essayer de manipuler les valeurs de matrice vous-même directement dans le code XAML.

Transformations 3D

Dans Windows 10, XAML a introduit une nouvelle propriété, UIElement.Transform3D, qui peut être utilisée pour créer des effets 3D avec l’interface utilisateur. Pour ce faire, utilisez PerspectiveTransform3D pour ajouter une perspective 3D partagée ou une « caméra » à votre scène, puis utilisez CompositeTransform3D pour transformer un élément dans l’espace 3D, comme vous utiliseriez CompositeTransform. Consultez UIElement.Transform3D pour une discussion sur la façon d’implémenter des transformations 3D.

Pour des effets 3D plus simples qui s’appliquent uniquement à un seul objet, la propriété UIElement.Projection peut être utilisée. L’utilisation d’un PlaneProjection comme valeur pour cette propriété équivaut à appliquer une transformation de perspective fixe et une ou plusieurs transformations 3D à l’élément. Ce type de transformation est décrit plus en détail dans les effets de perspective 3D pour l’interface utilisateur XAML.