Обзор преобразованийTransforms overview

Узнайте, как использовать преобразования в API среды выполнения Windows путем изменения относительных систем координат элементов в пользовательском интерфейсе.Learn how to use transforms in the Windows Runtime API, by changing the relative coordinate systems of elements in the UI. Эти действия могут применяться для корректировки внешнего вида отдельных XAML-элементов (например, при изменении масштаба, повороте или преобразовании положения в пространстве x-y).This can be used to adjust the appearance of individual XAML elements, such as scaling, rotating, or transforming the position in x-y space.

Что такое преобразование?What is a transform?

Преобразование определяет порядок сопоставления (или преобразования) точек при переходе из одного пространства координат в другое.A transform defines how to map, or transform, points from one coordinate space to another coordinate space. Когда преобразование применяется к элементу пользовательского интерфейса, это приводит к изменению способа отрисовки элемента на экране как части пользовательского интерфейса.When a transform is applied to a UI element, it changes how that UI element is rendered to the screen as part of the UI.

Преобразования можно поделить на четыре широкие категории: перевод, вращение, масштабирование и наклон (или сдвиг).Think of transforms in four broad classifications: translation, rotation, scaling and skew (or shear). При использовании API графики для изменения внешнего вида элементов пользовательского интерфейса обычно проще всего создавать преобразования, которые за один раз определяют только одну операцию трансформации.For the purposes of using graphics APIs to change the appearance of UI elements, it's usually easiest to create transforms that define only one operation at a time. Поэтому в среде выполнения Windows для каждой из этих категорий преобразования определен отдельный класс.So the Windows Runtime defines a discrete class for each of these transform classifications:

Скорее всего, для сценариев пользовательского интерфейса вы чаще всего будете использовать TranslateTransform и ScaleTransform.Of these, you're likely to use TranslateTransform and ScaleTransform most often for UI scenarios.

Преобразования можно комбинировать с помощью двух классов среды выполнения Windows: CompositeTransform и TransformGroup.You can combine transforms, and there are two Windows Runtime classes that support this: CompositeTransform and TransformGroup. В CompositeTransform преобразования применяются в следующем порядке: масштабирование, наклон, поворот и перенос.In a CompositeTransform, transforms are applied in this order: scale, skew, rotate, translate. Если вы хотите применять преобразования в другом порядке, используйте TransformGroup вместо CompositeTransform.Use TransformGroup instead of CompositeTransform if you want the transforms applied in a different order. Подробнее: CompositeTransform.For more info, see CompositeTransform.

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

В макете XAML преобразования применяются после завершения этапа разметки. Поэтому вычисление доступного пространства и принятие других решений относительно макета выполнялось еще до применения преобразований.In XAML layout, transforms are applied after the layout pass is complete, so available space calculations and other layout decisions have been made before the transforms are applied. Так как сначала создается макет, иногда вы будете получать неожиданные результаты при преобразовании элементов, находящихся в ячейке Grid или похожем контейнере макета, которому в процессе разметки выделяется пространство.Because layout comes first, you'll sometimes get unexpected results if you transform elements that are in a Grid cell or similar layout container that allocates space during layout. Преобразованный элемент может оказаться усеченным или загороженным, поскольку его пытаются переместить в область, для которой при делении пространства родительского контейнера не учитывались размеры после преобразования.The transformed element may appear truncated or obscured because it's trying to draw into an area that didn't calculate the post-transform dimensions when dividing space within its parent container. Возможно, вам стоит поэкспериментировать с результатами преобразования и скорректировать некоторые параметры.You may need to experiment with the transform results and adjust some settings. Например, вместо использования адаптивного макета и изменения размера с помощью Star вам, возможно, придется изменить свойства Center или объявить фиксированные размеры в пикселях для пространств макета, чтобы гарантировать, что родительский элемент выделяет достаточно места.For example, instead of relying on adaptive layout and star sizing, you may need to change the Center properties or declare fixed pixel measurements for layout space to make sure the parent allots enough space.

Примечание по переносу Windows Presentation Foundation (WPF) содержит свойство LayoutTransform, применяющее преобразования перед этапом разметки.Migration note: Windows Presentation Foundation (WPF) had a LayoutTransform property that applied transforms prior to the layout pass. Однако XAML среды выполнения Windows не поддерживает свойство LayoutTransform.But Windows Runtime XAML doesn't support a LayoutTransform property. (В Microsoft Silverlight нет этого свойства.)(Microsoft Silverlight didn't have this property either.)

В качестве альтернативы в наборе средств сообщества Windows предоставляется инструмент LayoutTransformControl, который применяет преобразования матрицы к любому элементу FrameworkElement приложения.As an alternative, the Windows Community Toolkit provides the LayoutTransformControl that applies Matrix transformations on any FrameworkElement of your application.

Применение преобразования к элементу пользовательского интерфейсаApplying a transform to a UI element

Применение преобразования к объекту обычно выполняется для назначения свойства UIElement.RenderTransform.When you apply a transform to an object, you typically do so to set the property UIElement.RenderTransform. Назначение этого свойства не приводит к буквальному попиксельному изменению объекта.Setting this property does not literally change the object pixel by pixel. На самом деле назначение свойства состоит в применении преобразования в локальном пространстве координат, в котором существует объект.What the property really does is apply the transform within the local coordinate space in which that object exists. Затем с помощью логики и операции отрисовки (после создания макета) отрисовываются комбинированные пространства координат, создавая впечатление, что изменился внешний вид объекта, а также, возможно, его позиция в макете (если применялся класс TranslateTransform).Then the rendering logic and operation (post-layout) renders the combined coordinate spaces, making it look like the object has changed appearance and also potentially its layout position (if TranslateTransform was applied).

По умолчанию центр каждого преобразования отрисовки совпадает с началом локальной системы координат целевого объекта (0,0).By default, each render transform is centered at the origin of the target object's local coordinate system—its (0,0). Единственным исключением является TranslateTransform, в котором нет задаваемых свойств выравнивания по центру, так как эффект переноса остается неизменным независимо от местонахождения центра.The only exception is a TranslateTransform, which has no center properties to set because the translation effect is the same regardless of where it is centered. Но у каждого из остальных преобразований есть свойства, задающие значения CenterX и CenterY.But the other transforms each have properties that set CenterX and CenterY values.

Каждый раз, когда вы используете преобразования по отношению к UIElement.RenderTransform, помните, что в UIElement есть другое свойство, влияющее на поведение преобразования, — RenderTransformOrigin.Whenever you use transforms with UIElement.RenderTransform, remember that there's another property on UIElement that affects how the transform behaves: RenderTransformOrigin. RenderTransformOrigin объявляет, нужно ли применять полное преобразование к точке по умолчанию (0,0) элемента или же к другой точке начала координат в относительном координатном пространстве данного элемента.What RenderTransformOrigin declares is whether the whole transform should apply to the default (0,0) point of an element or to some other origin point within the relative coordinate space of that element. В случае типичных элементов (0,0) означает, что преобразование размещается в верхнем левом углу.For typical elements, (0,0) places the transform to the top left corner. В зависимости от желаемого эффекта вы можете изменять RenderTransformOrigin вместо корректировки значений CenterX и CenterY при преобразованиях.Depending on what effect you want, you might choose to change RenderTransformOrigin rather than adjusting the CenterX and CenterY values on transforms. Учтите, что если применяется и значение RenderTransformOrigin, и значение CenterX / CenterY, результаты могут оказаться неожиданными, особенно если вы анимируете какие-либо из этих значений.Note that if you apply both RenderTransformOrigin and CenterX / CenterY values, the results can be pretty confusing, especially if you're animating any of the values.

Для проверки столкновения фигур неправильной формы объект, к которому применяется преобразование, продолжает отвечать на входные данные ожидаемым образом, который согласуется с внешним видом объекта в пространстве x-y.For hit-testing purposes, an object to which a transform is applied continues to respond to input in an expected way that's consistent to its visual appearance in x-y space. Например, если вы использовали TranslateTransform для перемещения Rectangle на 400 пикселей в сторону в пользовательском интерфейсе, Rectangle может реагировать на события PointerPressed, когда пользователь нажимает точку, где визуально появляется Rectangle.For example, if you've used a TranslateTransform to move a Rectangle 400 pixels laterally in the UI, that Rectangle responds to PointerPressed events when the user presses the point where the Rectangle appears visually. Вы не получите ложных событий, если пользователь нажмет область, в которой Rectangle находился перед переносом.You won't get false events if the user presses the area where the Rectangle was before being translated. Применение преобразования не влияет на аспекты индекса z, влияющие на тестирование нажатия. Индекс z, определяющий, какой именно элемент обрабатывает события ввода для точки пространства x-y, по-прежнему оценивается с помощью дочернего порядка, объявленного в контейнере.For any z-index considerations that affect hit testing, applying a transform makes no difference; the z-index that governs which element handles input events for a point in x-y space is still evaluated using the child order as declared in a container. Обычно применяется тот же порядок, что и при объявлении элементов в XAML, хотя для дочерних элементов объекта Canvas его можно скорректировать путем применения присоединенного свойства Canvas.ZIndex к дочерним элементам.That order is usually the same as the order in which you declare the elements in XAML, although for child elements of a Canvas object you can adjust the order by applying the Canvas.ZIndex attached property to child elements.

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

  • Brush.Transform, Brush.RelativeTransform. Эти свойства влияют на то, как Brush использует пространство координат в области, к которой применили Brush для задания таких визуальных свойств, как передние планы и фоны.Brush.Transform, Brush.RelativeTransform: These influence how a Brush uses coordinate space within the area that the Brush is applied to set visual properties such as foregrounds and backgrounds. Эти преобразования обычно не применяются для большинства распространенных кистей (для которых обычно задается сплошной цвет с помощью свойства SolidColorBrush), но иногда могут оказаться полезными при рисовании областей при помощи ImageBrush или LinearGradientBrush.These transforms aren't relevant for the most common brushes (which are typically setting solid colors with SolidColorBrush) but might be occasionally useful when painting areas with an ImageBrush or LinearGradientBrush.
  • Geometry.Transform. Это свойство можно использовать для применения преобразования к геометрии перед использованием этой геометрии для значения свойства Path.Data.Geometry.Transform: You might use this property to apply a transform to a geometry prior to using that geometry for a Path.Data property value.

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

Объекты Transform можно анимировать.Transform objects can be animated. Чтобы анимировать Transform, примените анимацию совместимого типа к свойству, которое требуется анимировать.To animate a Transform, apply an animation of a compatible type to the property you want to animate. Как правило, это значит, что вы используете объекты DoubleAnimation или DoubleAnimationUsingKeyFrames для определения анимации, так как все свойства преобразования относятся к типу Double.This typically means you're using DoubleAnimation or DoubleAnimationUsingKeyFrames objects to define the animation, because all of the transform properties are of type Double. Анимации, которые влияют на преобразование, используемое для значения UIElement.RenderTransform, не считаются зависимыми даже тогда, когда их продолжительность не является нулевой.Animations that affect a transform that's used for a UIElement.RenderTransform value are not considered to be dependent animations, even if they have a nonzero duration. Подробнее о зависимых анимациях: Раскадрованные анимации.For more info about dependent animations, see Storyboarded animations.

Если вы настраиваете анимацию свойств для создания эффекта, аналогичного преобразованию по визуальному представлению, например анимируете свойства Width и Height элемента FrameworkElement, а не применяете к нему TranslateTransform, такие анимации почти всегда считаются зависимыми.If you animate properties to produce an effect similar to a transform in terms of the net visual appearance—for example, animating the Width and Height of a FrameworkElement rather than applying a TranslateTransform—such animations are almost always treated as dependent animations. Вам придется включить анимации и, возможно, столкнуться с серьезным снижением производительности из-за этой анимации, особенно если вы пытаетесь поддерживать взаимодействие с пользователем во время анимации данного объекта.You'd have to enable the animations and there could be significant performance issues with the animation, especially if you're trying to support user interaction while that object is being animated. По этой причине предпочтительней использовать преобразование и анимировать его, а не любое другое свойство, где анимация воспринималась бы в качестве зависимой.For that reason it's preferable to use a transform and animate it rather than animating any other property where the animation would be treated as a dependent animation.

Чтобы выбрать цель преобразования, необходимо наличие класса Transform, выступающего в качестве значения RenderTransform.To target the transform, there must be an existing Transform as the value for RenderTransform. Обычно вы помещаете элемент для соответствующего типа преобразования в исходный код XAML, не задавая свойства для этого преобразования.You typically put an element for the appropriate transform type in the initial XAML, sometimes with no properties set on that transform.

Как правило, для применения анимаций к свойствам преобразования используется метод косвенного выбора.You typically use an indirect targeting technique to apply animations to the properties of a transform. Подробнее о синтаксисе косвенного выбора можно узнать в разделах Раскадрованные анимации и Синтаксис пути к свойству.For more info about indirect targeting syntax, see Storyboarded animations and Property-path syntax.

Иногда стандартные стили элементов управления определяют анимации преобразований как часть своего поведения визуального состояния.Default styles for controls sometimes define animations of transforms as part of their visual-state behavior. Например, визуальные состояния для ProgressRing используют анимированные значения RotateTransform для "кружения" точек в кольце.For example, the visual states for ProgressRing use animated RotateTransform values to "spin" the dots in the ring.

Вот простой пример анимации преобразования.Here's a simple example of how to animate a transform. В данном случае анимируется свойство Angle класса RotateTransform для вращения Rectangle на месте вокруг его визуального центра.In this case, it's animating the Angle of a RotateTransform to spin a Rectangle in place around its visual center. В этом примере RotateTransform присваивается имя, и поэтому косвенный выбор анимации не требуется. Но вместо этого преобразование можно оставить безымянным, присвоить имя элементу, к которому применяется преобразование, и использовать косвенный выбор (например, (UIElement.RenderTransform).(RotateTransform.Angle).This example names the RotateTransform so doesn't need indirect animation targeting, but you could alternatively leave the transform unnamed, name the element that the transform's applied to, and use indirect targeting such as (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();
}

Учет координатных систем отсчета во время выполненияAccounting for coordinate frames of reference at run time

В UIElement есть метод TransformToVisual, способный создавать класс Transform, соотносящий координатные системы отсчета для двух элементов пользовательского интерфейса.UIElement has a method named TransformToVisual, which can generate a Transform that correlates the coordinate frames of reference for two UI elements. Его можно использовать для сравнения элемента со стандартной для приложения координатной системой отсчета, если вы передаете в качестве первого параметра корневой визуальный элемент.You can use this to compare an element to the app's default coordinate frame of reference if you pass the root visual as the first parameter. Это может быть удобно в случае, если вы перенаправили событие ввода из другого элемента или пытаетесь предсказать поведение макета без фактического запроса этапа разметки.This can be useful if you've captured an input event from a different element, or if you are trying to predict layout behavior without actually requesting a layout pass.

Данные о событии, полученные из событий указателя, обеспечивают доступ к методу GetCurrentPoint, где вы можете указать параметр relativeTo, чтобы заменить координатную систему отсчета определенным элементом, а не стандартным значением приложения.Event data obtained from pointer events provides access to a GetCurrentPoint method, where you can specify a relativeTo parameter to change the coordinate frame of reference to a specific element rather than the app default. Этот подход просто вызывает внутреннее применение преобразования переноса и преобразует данные координат x-y при создании возвращенного объекта PointerPoint.This approach simply applies a translate transform internally and transforms the x-y coordinate data for you when it creates the returned PointerPoint object.

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

Преобразование можно описать с помощью матрицы преобразования.A transform can be described in terms of a transformation matrix. Для описания преобразований на двухмерной плоскости x-y применяется матрица 3×3.A 3×3 matrix is used to describe the transformations in a two-dimensional, x-y plane. Матрицы аффинных преобразований можно умножать в целях формирования любого количества таких линейных преобразований, как поворот и наклон (сдвиг), вслед за которыми выполняется перенос.Affine transformation matrices can be multiplied to form any number of linear transformations, such as rotation and skew (shear), followed by translation. Последний столбец матрицы аффинных преобразований равен (0, 0, 1), поэтому в математическом описании вам нужно определить только члены первых двух столбцов.The final column of an affine transformation matrix is equal to (0, 0, 1), so you need to specify only the members of the first two columns in the mathematical description.

Математическое описание преобразования может быть полезно, если у вас есть математический опыт или вы знакомы с методами программирования графики, которые также используют матрицы для описания преобразований пространства координат.The mathematical description of a transform might be useful to you if you have a mathematical background or a familiarity with graphics-programming techniques that also use matrices to describe transformations of coordinate space. Существует класс, производный от класса Transform и позволяющий выразить преобразование непосредственно в виде матрицы 3×3, — MatrixTransform.There's a Transform-derived class that enables you to express a transformation directly in terms of its 3×3 matrix: MatrixTransform. Класс MatrixTransform имеет свойство Matrix, которое содержит структуру из шести свойств: M11, M12, M21, M22, OffsetX и OffsetY.MatrixTransform has a Matrix property, which holds a structure that has six properties: M11, M12, M21, M22, OffsetX and OffsetY. В каждом свойстве Matrix используется значение Double, которое соотносится с шестью релевантными значениями (в столбцах 1 и 2) матрицы аффинного преобразования.Each Matrix property uses a Double value and corresponds to the six relevant values (columns 1 and 2) of an affine transformation matrix.

M11M11 M12M12 00
M21M21 M22M22 00
OffsetXOffsetX OffsetYOffsetY 11

Любое преобразование, которое можно описать с помощью TranslateTransform, ScaleTransform, RotateTransform или SkewTransform, можно точно так же описать при помощи MatrixTransform со значением Matrix.Any transform that you could describe with a TranslateTransform, ScaleTransform, RotateTransform, or SkewTransform object could be described equally by a MatrixTransform with a Matrix value. Но обычно вы просто используете TranslateTransform и другие классы, потому что проще представить себе свойства этих классов преобразования, чем задавать компоненты вектора в Matrix.But you typically just use TranslateTransform and the others because the properties on those transform classes are easier to conceptualize than setting the vector components in a Matrix. Также проще анимировать отдельные свойства преобразований, тогда как Matrix — фактически структура, а не DependencyObject, и поэтому не может поддерживать анимированные отдельные значения.It's also easier to animate the discrete properties of transforms; a Matrix is actually a structure and not a DependencyObject, so it can't support animated individual values.

Ряд средств проектирования на XAML, позволяющих применять операции преобразования, будет упорядочивать результаты в виде MatrixTransform.Some XAML design tools that enable you to apply transformation operations will serialize the results as a MatrixTransform. При этом, возможно, лучше снова использовать то же средство проектирования, чтобы изменить эффект преобразования и переупорядочить XAML, вместо того чтобы пытаться манипулировать значениями Matrix непосредственно в XAML.In this case it may be best to use the same design tool again to change the transformation effect and serialize the XAML again, rather than trying to manipulate the Matrix values yourself directly in the XAML.

Трехмерные преобразования3-D transforms

В Windows 10 XAML появилось новое свойство, UIElement.Transform3D, которое можно использовать для создания трехмерных эффектов пользовательского интерфейса.In Windows 10, XAML introduced a new property, UIElement.Transform3D, that can be used to create 3D effects with UI. Для этого используйте PerspectiveTransform3D, чтобы добавить общую трехмерную перспективу ("камеру") к сцене, а затем с помощью CompositeTransform3D преобразуйте элемент в трехмерном пространстве так же, как при использовании CompositeTransform.To do this, use PerspectiveTransform3D to add a shared 3D perspective or "camera" to your scene, and then use CompositeTransform3D to transform an element in 3D space, like you would use CompositeTransform. Описание реализации трехмерных преобразований см. в разделе UIElement.Transform3D.See UIElement.Transform3D for a discussion of how to implement 3D transforms.

Для простых трехмерных эффектов, которые применяются только к одному объекту, можно использовать свойство UIElement.Projection.For simpler 3D effects that only apply to a single object, the UIElement.Projection property can be used. Использование значения PlaneProjection для этого свойства эквивалентно применению фиксированного преобразования перспективы и одного или нескольких трехмерных преобразований к элементу.Using a PlaneProjection as the value for this property is equivalent to applying a fixed perspective transform and one or more 3D transforms to the element. Этот тип преобразования подробно описан в разделе Объемные эффекты перспективы для пользовательского интерфейса на XAML.This type of transform is described in more detail in 3-D perspective effects for XAML UI.

Связанные темыRelated topics