Составные преобразования в WinRT
146WinRT --- Составные преобразования
При объединении разнотипных преобразований важен порядок выполнения операций. Впрочем, на практике разные преобразования обычно применяются в более или менее стандартном порядке.
Предположим, требуется выполнить поворот, масштабирование и сдвиг элемента. Преобразование ScaleTransform обычно выполняется первым, потому что масштабирование удобнее определять для неповернутого элемента. Преобразование TranslateTransform завершает цепочку, потому что обычно вы не хотите, чтобы масштабирование и повороты влияли на величину сдвига. Получается, что преобразование RotateTransform должно выполняться в середине, а операции выполняются в порядке: масштабирование, поворот, сдвиг.
Если такой порядок вас устраивает, используйте класс CompositeTransform. Он содержит набор свойств, определенных для выполнения преобразований в следующем порядке:
Масштабирование.
Отклонение.
Поворот.
Перенос.
Список свойств:
CenterX и CenterY определяют центр масштабирования, отклонения и вращения.
ScaleX и ScaleY.
SkewX и SkewY.
Rotation.
TranslateX и TranslateY.
Ниже приведена небольшая программа, использующая класс CompositeTransform для удобного объединения масштабирования с отклонением:
<Page ...>
<Page.Resources>
<Style x:Key="txbStyle" TargetType="TextBlock">
<Setter Property="Text" Value="qabcdy" />
<Setter Property="FontFamily" Value="Arial" />
<Setter Property="FontSize" Value="180" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Page.Resources>
<Grid Background="#FF1D1D1D">
<!-- Теневой элемент TextBlock -->
<TextBlock Foreground="Gray" Style="{StaticResource txbStyle}"
RenderTransformOrigin="0 1">
<TextBlock.RenderTransform>
<CompositeTransform ScaleY="1.2" SkewX="-65" />
</TextBlock.RenderTransform>
</TextBlock>
<!-- TextBlock со стилевыми свойствами -->
<TextBlock Style="{StaticResource txbStyle}" />
</Grid>
</Page>
XAML создает экземпляры двух элементов TextBlock, свойства которых задаются стилем (включая свойство Text), и с точки зрения системы формирования макета оба экземпляра занимают одно и то же пространство. Однако нижний экземпляр окрашен в серый цвет и к нему применяются преобразования масштабирования и отклонения:
Обратите внимание: свойству RenderTransformOrigin задается значение (0 1), то есть преобразование выполняется относительно левого нижнего угла. Однако вместо него также можно использовать точку (1, 1) или любую промежуточную точку; результат останется неизменным. Необходимо лишь то, чтобы два элемента TextBlock имели одинаковую нижнюю сторону. Масштабный коэффициент ScaleY, равный 1.2, увеличивает высоту тени на 20%. Значение SkewX, равное -65°, сдвигает нижнюю сторону влево, но поскольку на нижней стороне находится центр масштабирования и отклонения, верх сдвигается вправо.
Присмотревшись повнимательнее, вы заметите, что нижние края выносных элементов не совсем точно совпадают. Дело в том, что TextBlock опускается чуть ниже нижних выносных элементов. Для повышения точности совпадения можно задать свойству RenderTransformOrigin значение (0, 0.96).
А если потребуется добиться аналогичного эффекта с текстом, не имеющим нижних выносных элементов? Пример:
Проблема в том, что для свойства RenderTransformOrigin требуется подобрать значение Y, равное относительной высоте текста над базовой линией, а эта характеристика зависит от шрифта. Для этого конкретного примера я экспериментировал до тех пор, пока не пришел к значению (0, 0.78), но оно подходит только для шрифта Times New Roman. Для создания универсального решения потребуется доступ к метрикам шрифтов, с которыми приложение Windows 8 может работать только через DirectX. Позже я покажу, как это делается.