Поделиться через


Общие сведения о преобразованиях

Узнайте, как использовать преобразования в API среда выполнения Windows, изменив относительные системы координат элементов в пользовательском интерфейсе. Это можно использовать для настройки внешнего вида отдельных элементов XAML, таких как масштабирование, поворот или преобразование позиции в пространстве x-y.

Что такое преобразование?

Преобразование определяет, как сопоставлять или преобразовывать точки из одного пространства координат в другое пространство координат. При применении преобразования к элементу пользовательского интерфейса он изменяет способ отображения этого элемента пользовательского интерфейса на экране в рамках пользовательского интерфейса.

Думайте о преобразованиях в четырех широких классификациях: перевод, поворот, масштабирование и размыкание (или сдвига). Для использования графических API для изменения внешнего вида элементов пользовательского интерфейса обычно проще всего создавать преобразования, определяющие только одну операцию одновременно. Поэтому среда выполнения Windows определяет дискретный класс для каждой из этих классификаций преобразований:

Из них вы, скорее всего, используете TranslateTransform и ScaleTransform чаще всего для сценариев пользовательского интерфейса.

Вы можете объединить преобразования и два класса среда выполнения Windows, которые поддерживают это: CompositeTransform и TransformGroup. В составнойtransform преобразования применяются в этом порядке: масштабирование, отклонение, поворот, перевод. Используйте TransformGroup вместо СоставнойTransform , если требуется, чтобы преобразования применялись в другом порядке. Дополнительные сведения см. в разделе CompositeTransform.

Преобразования и макет

В макете XAML преобразования применяются после завершения прохождения макета, поэтому доступные вычисления пространства и другие решения макета были приняты до применения преобразований. Так как макет начинается первым, иногда при преобразовании элементов, которые находятся в ячейке сетки или аналогичном контейнере макета, который выделяет пространство во время макета. Преобразованный элемент может отображаться усеченным или неопубликованным, так как он пытается привлечь в область, которая не вычисляла измерения после преобразования при делении пространства в родительском контейнере. Возможно, потребуется поэкспериментировать с результатами преобразования и настроить некоторые параметры. Например, вместо того чтобы полагаться на адаптивный макет и размер звезд, может потребоваться изменить свойства центра или объявить фиксированные измерения пикселей для пространства макета, чтобы убедиться, что родительские выделения достаточно места.

Примечание по миграции: Windows Presentation Foundation (WPF) имеет свойство LayoutTransform , которое применяло преобразования до прохождения макета. Но среда выполнения Windows XAML не поддерживает свойство LayoutTransform. (Microsoft Silverlight не имеет этого свойства.)

В качестве альтернативы в наборе средств сообщества Windows предоставляется инструмент LayoutTransformControl, который применяет преобразования матрицы к любому элементу FrameworkElement приложения.

Применение преобразования к элементу пользовательского интерфейса

При применении преобразования к объекту обычно необходимо задать свойство UIElement.RenderTransform. Задание этого свойства не буквально изменяет пиксель объекта по пикселю. То, что действительно делает свойство, применяет преобразование в локальном пространстве координат, в котором существует этот объект. Затем логика отрисовки и операции (после макета) отрисовывает объединенные пространства координат, что делает его похожим на внешний вид объекта, а также потенциально его положение макета (если было применено преобразованиеTransform).

По умолчанию каждое преобразование отрисовки сосредоточено в источнике локальной системы координат целевого объекта — его (0,0). Единственным исключением является ПреобразованиеTransform, которое не имеет свойств центра для задания, так как эффект перевода одинаков независимо от того, где он находится в центре. Но другие преобразования имеют свойства, которые задают значения CenterX и CenterY .

При использовании преобразований с UIElement.RenderTransform помните, что в UIElement есть другое свойство, которое влияет на поведение преобразования: RenderTransformOrigin. То, что renderTransformOrigin объявляет, должно ли все преобразование применяться к точке по умолчанию (0,0) элемента или к другой точке источника в относительном пространстве координат этого элемента. Для типичных элементов (0,0) преобразуется в левый верхний угол. В зависимости от нужного эффекта можно изменить RenderTransformOrigin , а не настраивать значения CenterX и CenterY для преобразований. Обратите внимание, что при применении значений RenderTransformOrigin и CenterX / CenterY результаты могут быть довольно запутанными, особенно если вы анимируете любое из значений.

В целях тестирования попаданий объект, к которому применяется преобразование, продолжает реагировать на входные данные ожидаемым образом, согласованным с его внешним видом в пространстве x-y. Например, если вы использовали TranslateTransform для перемещения прямоугольника 400 пикселей в боковой части пользовательского интерфейса, прямоугольник реагирует на события PointerPressed, когда пользователь нажимает точку, в которой прямоугольник отображается визуально. Вы не получите ложные события, если пользователь нажимает область, в которой был прямоугольник , прежде чем переводиться. Для любых соображений z-индекса, влияющих на тестирование попаданий, применение преобразования не имеет никакой разницы; Z-индекс, определяющий, какой элемент обрабатывает входные события для точки в пространстве x-y, по-прежнему оценивается с помощью дочернего порядка, объявленного в контейнере. Этот порядок обычно совпадает с порядком объявления элементов в XAML, хотя для дочерних элементов объекта Canvas можно настроить порядок, применив присоединенное свойство Canvas.ZIndex к дочерним элементам.

Другие свойства преобразования

Анимация преобразования

Объекты Transform можно анимировать. Чтобы анимировать преобразование, примените анимацию совместимого типа к свойству, которое нужно анимировать. Обычно это означает, что для определения анимации используются объекты DoubleAnimation или DoubleAnimationUsingKeyFrames, так как все свойства преобразования имеют тип Double. Анимации, влияющие на преобразование, используемое для значения UIElement.RenderTransform , не считаются зависимыми анимациями, даже если они имеют ненулевое время. Дополнительные сведения о зависимых анимациях см. в разделе раскадровки анимаций.

Если вы анимируете свойства для создания эффекта, аналогичного преобразованию с точки зрения внешнего вида чистого визуального элемента, например, анимирование ширины и высоты FrameworkElement, а не применение ПреобразованияTransform, такие анимации почти всегда рассматриваются как зависимые анимации. Вам потребуется включить анимацию и возникнуть значительные проблемы с производительностью анимации, особенно если вы пытаетесь поддерживать взаимодействие с пользователем во время анимации этого объекта. По этой причине предпочтительнее использовать преобразование и анимировать его, а не анимировать любое другое свойство, где анимация будет рассматриваться как зависимой анимации.

Для целевого преобразования необходимо иметь существующее преобразование в качестве значения для RenderTransform. Обычно элемент для соответствующего типа преобразования помещается в исходный XAML, иногда без набора свойств для этого преобразования.

Обычно для применения анимаций к свойствам преобразования используется непрямая целевая методика. Дополнительные сведения о синтаксисе косвенного целевого назначения см. в разделе "Раскадрованная анимация " и синтаксис пути к свойству.

Стили по умолчанию для элементов управления иногда определяют анимацию преобразований в рамках их поведения визуального состояния. Например, визуальные состояния для ProgressRing используют анимированные значения RotateTransform для "спины" точек в кольце.

Ниже приведен простой пример анимации преобразования. В этом случае это анимация угла поворотаTransform для спины прямоугольника на месте вокруг своего визуального центра. В этом примере именуется объект RotateTransform , поэтому не требуется непрямая анимация, но вы также можете оставить преобразование неназванным, присвоить элементу, к которому применено преобразование, и использовать непрямую целевую ориентацию, например (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();
}

Учет координатных систем отсчета во время выполнения

В UIElement есть метод TransformToVisual, способный создавать класс Transform, соотносящий координатные системы отсчета для двух элементов пользовательского интерфейса. Это можно использовать для сравнения элемента с рамкой координат по умолчанию приложения, если передать корневой визуальный элемент в качестве первого параметра. Это может быть полезно, если вы захватили входное событие из другого элемента или если вы пытаетесь прогнозировать поведение макета без фактического запроса передачи макета.

Данные событий, полученные из событий указателя, предоставляют доступ к методу GetCurrentPoint, где можно указать параметр relativeTo, чтобы изменить кадр координат ссылки на определенный элемент, а не приложение по умолчанию. Этот подход просто применяет преобразование перевода внутренне и преобразует данные координат x-y для вас при создании возвращаемого объекта PointerPoint .

Математическое описание преобразования

Преобразование можно описать с точки зрения матрицы преобразования. Матрица 3×3 используется для описания преобразований в двухмерной плоскости x-y. Матрицы аффинного преобразования можно умножить, чтобы сформировать любое количество линейных преобразований, таких как поворот и смещение (сдвига), за которым следует перевод. Окончательный столбец матрицы аффинного преобразования равен (0, 0, 1), поэтому необходимо указать только элементы первых двух столбцов в математическом описании.

Математическое описание преобразования может оказаться полезным для вас, если у вас есть математический фон или знакомство с методами графического программирования, которые также используют матрицы для описания преобразований координатного пространства. Существует класс, производный от преобразования, который позволяет выразить преобразование непосредственно с точки зрения его матрицы 3×3: MatrixTransform. MatrixTransform имеет свойство Matrix, которое содержит структуру с шестью свойствами: M11, M12, M21, M22, OffsetX и OffsetY. Каждое свойство Matrix использует двойное значение и соответствует шести соответствующим значениям (столбцам 1 и 2) матрицы аффинного преобразования.

Столбец 1 Столбец 2 Столбец 3
M11 M12 0
M21 M22 0
OffsetX OffsetY 1

Любое преобразование, которое можно описать с помощью объекта TranslateTransform, ScaleTransform, RotateTransform или SkewTransform, можно описать одинаково с помощью MatrixTransform со значением Matrix. Но обычно вы просто используете TranslateTransform и другие, так как свойства этих классов преобразования проще концептуальнее, чем настройка векторных компонентов в матрице. Кроме того, проще анимировать дискретные свойства преобразований; Матрица на самом деле является структурой, а не ЗависимостьObject, поэтому она не может поддерживать анимированные отдельные значения.

Некоторые средства разработки XAML, позволяющие применять операции преобразования, сериализуют результаты в виде MatrixTransform. В этом случае можно снова использовать то же средство разработки, чтобы изменить эффект преобразования и сериализовать XAML еще раз, а не пытаться управлять значениями матрицы непосредственно в XAML.

Трехмерные преобразования

В Windows 10 XAML представила новое свойство UIElement.Transform3D, которое можно использовать для создания трехмерных эффектов с пользовательским интерфейсом. Для этого используйте PerspectiveTransform3D, чтобы добавить общую трехмерную перспективу или "камеру" в сцену, а затем использовать CompositeTransform3D для преобразования элемента в трехмерном пространстве, например с помощью CompositeTransform. Сведения о реализации трехмерных преобразований см. в разделе UIElement.Transform3D.

Для более простых трехмерных эффектов, которые применяются только к одному объекту, можно использовать свойство UIElement.Projection. Использование PlaneProjection в качестве значения этого свойства эквивалентно применению преобразования фиксированной перспективы и одного или нескольких трехмерных преобразований к элементу. Этот тип преобразования подробно описан в эффектах перспективы 3-D для пользовательского интерфейса XAML.