Panoramica delle trasformazioni

Informazioni su come usare le trasformazioni nell'API di Windows Runtime modificando i sistemi di coordinate relativi degli elementi nell'interfaccia utente. Può essere usato per regolare l'aspetto di singoli elementi XAML, ad esempio ridimensionamento, rotazione o trasformazione della posizione nello spazio x-y.

Che cos'è una trasformazione?

Una trasformazione definisce come effettuare il mapping o trasformare i punti da uno spazio di coordinate a un altro spazio di coordinate. Quando una trasformazione viene applicata a un elemento dell'interfaccia utente, modifica il rendering dell'elemento dell'interfaccia utente sullo schermo come parte dell'interfaccia utente.

Le trasformazioni possono essere suddivise in quattro ampie categorie: traslazione, rotazione, scalatura e inclinazione (o shear). Ai fini dell'uso delle API grafiche per modificare l'aspetto degli elementi dell'interfaccia utente, in genere è più semplice creare trasformazioni che definiscono una sola operazione alla volta. Windows Runtime definisce quindi una classe discreta per ognuna di queste classificazioni di trasformazione:

Di questi, è probabile che si usi TranslateTransform e ScaleTransform più spesso per gli scenari dell'interfaccia utente.

È possibile combinare le trasformazioni e sono disponibili due classi di Windows Runtime che supportano questa operazione: CompositeTransform e TransformGroup. Le trasformazioni in un CompositeTransformvengono applicate in questo ordine: scalatura, inclinazione, rotazione, traslazione. Usare TransformGroup anziché CompositeTransform se si desidera applicare le trasformazioni in un ordine diverso. Per ulteriori informazioni, vedi CompositeTransform.

Trasformazioni e layout

Nel layout XAML le trasformazioni vengono applicate dopo il completamento del passaggio di layout, quindi sono stati presi calcoli dello spazio disponibile e altre decisioni relative al layout prima dell'applicazione delle trasformazioni. Poiché il layout ha la priorità, a volte si ottengono risultati imprevisti se si trasformano gli elementi presenti in una cella Grid o in un qualsiasi contenitore di layout simile che alloca spazio durante il layout. L'elemento trasformato può apparire troncato o nascosto perché sta tentando di disegnare in un'area che non ha calcolato le dimensioni post-trasformazione durante la divisione dello spazio all'interno del contenitore padre. Potrebbe essere necessario sperimentare i risultati della trasformazione e regolare alcune impostazioni. Ad esempio, invece di basarsi su layout adattivo e sul ridimensionamento proporzionale, potrebbe essere necessario modificare le proprietà Center o dichiarare misure di pixel fisse per lo spazio di layout per assicurarsi che il genitore allochi spazio sufficiente.

Nota sulla migrazione: Windows Presentation Foundation (macchine virtuali Windows) aveva una proprietà LayoutTransform che applicava trasformazioni prima del passaggio di layout. Windows Runtime XAML non supporta una proprietà LayoutTransform. Microsoft Silverlight non disponeva di questa proprietà.

Suggerimento

In alternativa, Windows Community Toolkit fornisce LayoutTransformControl che applica trasformazioni Matrix in qualsiasi FrameworkElement dell'applicazione.

Applicare una trasformazione a un elemento dell'interfaccia utente

Quando si applica una trasformazione a un oggetto, in genere si imposta la proprietà UIElement.RenderTransform. L'impostazione di questa proprietà non modifica letteralmente l'oggetto pixel per pixel. La proprietà applica realmente la trasformazione all'interno dello spazio di coordinate locale in cui tale oggetto esiste. La logica di rendering e l'operazione (post-layout) eseguono quindi il rendering degli spazi di coordinate combinati, facendo sembrare che l'aspetto e potenzialmente anche la posizione di layout dell'oggetto siano cambiati (se è stata applicata la trasformazione TranslateTransform).

Per impostazione predefinita, ciascuna trasformazione di rendering è centrata sull'origine del sistema di coordinate locale dell'oggetto di destinazione, cioè (0,0). L'unica eccezione è un translateTransform, che non ha proprietà di centro da impostare perché l'effetto di traduzione è lo stesso indipendentemente dalla posizione in cui è centrato. Le altre trasformazioni hanno tuttavia proprietà che impostano i valori CenterX e CenterY .

Ogni volta che si usano trasformazioni con UIElement.RenderTransform, tenere presente che è presente un'altra proprietà in UIElement che influisce sul comportamento della trasformazione: RenderTransformOrigin. Ciò che RenderTransformOrigin dichiara è se l'intera trasformazione deve essere applicata al punto predefinito (0,0) di un elemento o a un altro punto di origine all'interno dello spazio di coordinate relativo di tale elemento. Per gli elementi tipici, (0,0) posiziona la trasformazione nell'angolo superiore sinistro. A seconda dell'effetto desiderato, è possibile scegliere di modificare RenderTransformOrigin invece di modificare i valori CenterX e CenterY nelle trasformazioni. Si noti che se si applicano sia RenderTransformOrigin che i valori CenterX / CenterY, i risultati possono essere piuttosto confusionari, soprattutto se si anima uno qualsiasi dei valori.

A scopo di hit testing, un oggetto a cui viene applicata una trasformazione continua a rispondere all'input in modo previsto coerente con l'aspetto visivo nello spazio x-y. Ad esempio, se è stato usato un TranslateTransform per spostare un Rectangle di 400 pixel lateralmente nell'interfaccia utente, tale Rectangle risponde agli eventi PointerPressed quando l'utente preme il punto in cui appare visivamente il Rectangle. Se l'utente preme l'area in cui era il Rettangolo prima di essere traslato, non si otterranno eventi falsi. Per eventuali considerazioni sugli indici z che influiscono sui hit testing, l'applicazione di una trasformazione non fa alcuna differenza; L'indice z che regola l'elemento che gestisce gli eventi di input per un punto nello spazio x-y viene comunque valutato usando l'ordine figlio dichiarato in un contenitore. Questo ordine è in genere uguale all'ordine in cui dichiari gli elementi in XAML, anche se per gli elementi figlio di un oggetto Canvas puoi modificare l'ordine applicando la proprietà associata Canvas.ZIndex agli elementi figlio.

Altre proprietà di trasformazione

  • Brush.Transform, Brush.RelativeTransform: influiscono sul modo in cui un Brush usa lo spazio delle coordinate all'interno dell'area applicata al Pennello per impostare proprietà visive quali primo piano e sfondi. Queste trasformazioni non sono rilevanti per i pennelli più comuni (che in genere impostano colori a tinta unita con SolidColorBrush), ma possono essere occasionalmente utili quando si disegnano aree con imageBrush o LinearGradientBrush.
  • Geometry.Transform: è possibile utilizzare questa proprietà per applicare una trasformazione a una geometria prima di utilizzare tale geometria per un valore della proprietà Path.Data .

Animazione di una trasformazione

Gli oggetti Transform possono essere animati. Per animare un Transform, applica un'animazione di un tipo compatibile alla proprietà che desideri animare. Ciò significa in genere che usi oggetti DoubleAnimation o DoubleAnimationUsingKeyFrames per definire l'animazione, poiché tutte le proprietà di trasformazione sono di tipo Double. Le animazioni che influiscono su una trasformazione usata per un valore UIElement.RenderTransform non vengono considerate animazioni dipendenti, anche se hanno una durata diversa da zero. Per altre info sulle animazioni dipendenti, vedi animazioni con storyboard.

Se si animano le proprietà per produrre un effetto simile a una trasformazione in termini di aspetto visivo netto, ad esempio animando Width e Height di un FrameworkElement anziché applicare un TranslateTransform, tali animazioni vengono considerate quasi sempre come animazioni dipendenti. Dovrai abilitare le animazioni e potrebbero verificarsi problemi significativi di prestazioni con l'animazione, soprattutto se stai provando a supportare l'interazione dell'utente mentre l'oggetto è animato. Per questo motivo è preferibile usare una trasformazione e animarla anziché animare qualsiasi altra proprietà in cui l'animazione verrebbe considerata come un'animazione dipendente.

Per impostare come destinazione la trasformazione, deve essere presente un Transform esistente come valore per RenderTransform. In genere si inserisce un elemento per il tipo di trasformazione appropriato nel codice XAML iniziale, a volte senza proprietà impostate su tale trasformazione.

In genere si usa una tecnica di destinazione indiretta per applicare animazioni alle proprietà di una trasformazione. Per altre informazioni sulla sintassi di destinazione indiretta, vedi Animazioni con storyboard e sintassi del percorso della proprietà.

Gli stili predefiniti per i controlli talvolta definiscono le animazioni delle trasformazioni come parte del comportamento dello stato visivo. Ad esempio, gli stati visivi per ProgressRing usano valori animati RotateTransform per "far ruotare" i puntini nell'anello.

Ecco un semplice esempio di come animare una trasformazione. In questo caso, sta animando l'angolo di un RotateTransform per far ruotare un Rectangle sul posto intorno al suo centro visivo. In questo esempio viene assegnato il nome RotateTransform in modo che non sia necessaria la destinazione dell'animazione indiretta, ma in alternativa è possibile lasciare senza nome la trasformazione, denominare l'elemento a cui viene applicata la trasformazione e usare la destinazione indiretta, (UIElement.RenderTransform).(RotateTransform.Angle)ad esempio .

<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();
}

Considerazione dei sistemi di riferimento delle coordinate in tempo di esecuzione

UIElement ha un metodo denominato TransformToVisual, che può generare un Transform che mette in relazione i sistemi di coordinate di riferimento per due elementi dell'interfaccia utente. Puoi usarlo per confrontare un elemento con il sistema di coordinate predefinito di riferimento dell'app, se passi il visuale radice come primo parametro. Ciò può essere utile se hai acquisito un evento di input da un elemento diverso o se stai cercando di prevedere il comportamento del layout senza effettivamente richiedere un passaggio di layout.

Annotazioni

(UWP) I dati dell'evento ottenuti dagli eventi puntatore forniscono l'accesso a un metodo GetCurrentPoint , in cui è possibile specificare un parametro relativeTo per modificare il frame di coordinate del riferimento a un elemento specifico anziché all'impostazione predefinita dell'app. Questo approccio applica semplicemente internamente una trasformazione di traslazione e trasforma per te i dati delle coordinate x-y quando crea l'oggetto PointerPoint restituito.

Descrizione matematica di una trasformazione

Una trasformazione può essere descritta in termini di matrice di trasformazione. Una matrice 3×3 viene usata per descrivere le trasformazioni in un piano x-y bidimensionale. Le matrici di trasformazione affine possono essere moltiplicate per formare un qualsiasi numero di trasformazioni lineari, come la rotazione e l’inclinazione (shear), seguite dalla traslazione. La colonna finale di una matrice di trasformazione affine è uguale a (0, 0, 1), quindi è necessario specificare solo i membri delle prime due colonne nella descrizione matematica.

La descrizione matematica di una trasformazione può essere utile se si ha un background matematico o una familiarità con le tecniche di programmazione grafica che usano anche matrici per descrivere le trasformazioni dello spazio delle coordinate. Esiste una classe derivata da Transform che consente di esprimere una trasformazione direttamente in termini di matrice 3×3: MatrixTransform. MatrixTransform ha una proprietà Matrix, che contiene una struttura con sei proprietà: M11, M12, M21, M22, OffsetX e OffsetY. Ogni proprietà Matrix usa un valore Double e corrisponde ai sei valori pertinenti (colonne 1 e 2) di una matrice di trasformazione affine.

Colonna 1 Colonna 2 Colonna 3
M11 M12 0
M21 M22 0
offsetX OffsetY 1

Qualsiasi trasformazione che è possibile descrivere con un TranslateTransform, ScaleTransform, RotateTransform, o un SkewTransform, può essere descritta allo stesso modo da una MatrixTransform con un Matrix valore. Ma in genere si usa TranslateTransform e gli altri perché le proprietà di tali classi di trasformazione sono più facili da concettualizzare rispetto all'impostazione dei componenti vettoriali in una matrice. È anche più facile animare le proprietà discrete delle trasformazioni; una matrice di è in realtà una struttura e non un DependencyObject, quindi non può supportare valori individuali animati.

Alcuni strumenti di progettazione XAML che consentono di applicare operazioni di trasformazione serializzeranno i risultati come MatrixTransform. In questo caso potrebbe essere preferibile usare di nuovo lo stesso strumento di progettazione per modificare l'effetto di trasformazione e serializzare di nuovo il codice XAML, invece di tentare di modificare i valori matrix direttamente nel codice XAML.

trasformazioni 3D

In Windows 10 XAML ha introdotto una nuova proprietà , UIElement.Transform3D, che può essere usata per creare effetti 3D con l'interfaccia utente. A tale scopo, usare PerspectiveTransform3D per aggiungere una prospettiva 3D condivisa o una "fotocamera" alla scena e quindi usare CompositeTransform3D per trasformare un elemento nello spazio 3D, come si usa CompositeTransform. Per informazioni su come implementare trasformazioni 3D, vedere UIElement.Transform3D .

Per effetti 3D più semplici che si applicano solo a un singolo oggetto, è possibile usare la proprietà UIElement.Projection . L'uso di PlaneProjection come valore per questa proprietà equivale all'applicazione di una trasformazione prospettica fissa e di una o più trasformazioni 3D all'elemento. Questo tipo di trasformazione viene descritto in modo più dettagliato negli effetti di prospettiva 3D per l'interfaccia utente XAML.