Сдвиг элементов в WinRT

51

Класс TranslateTransform определяет два свойства X и Y, при задании которых элемент отображается с заданным смещением относительно исходной позиции. Одно из простых применений TranslateTransform - имитация рельефа или тени при выводе текста:

Применение эффекта сдвига к текстовым надписям

Так как свет обычно падает сверху (а также потому, что мы привыкли, что трехмерные объекты на экране монитора освещаются от левого верхнего угла), верхний текст выглядит так, словно тень располагается внизу и справа, а буквы выступают из экрана. Во втором примере показан обратный эффект: тень находится слева сверху, а буквы словно «вырезаны» в плоскости.

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

<Page ...>

    <Page.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="FontFamily" Value="Arial" />
            <Setter Property="FontSize" Value="160" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="HorizontalAlignment" Value="Center" />
        </Style>
    </Page.Resources>

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <TextBlock Text="EMBOSS" />

        <TextBlock Text="EMBOSS" Foreground="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <TextBlock.RenderTransform>
                <TranslateTransform X="-2" Y="-2" />
            </TextBlock.RenderTransform>
        </TextBlock>

        <TextBlock Text="ENGRAVE"
                   Grid.Row="1" />

        <TextBlock Text="ENGRAVE"
                   Grid.Row="1"
                   Foreground="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <TextBlock.RenderTransform>
                <TranslateTransform X="2" Y="2" />
            </TextBlock.RenderTransform>
        </TextBlock>

        <TextBlock Text="Drop Shadow"
                   Grid.Row="2"
                   Foreground="Gray">
            <TextBlock.RenderTransform>
                <TranslateTransform X="6" Y="6" />
            </TextBlock.RenderTransform>
        </TextBlock>

        <TextBlock Text="Drop Shadow"
                   Grid.Row="2" />
    </Grid>
</Page>

Обратите внимание: эффект «приподнятого» текста требует отрицательных смещений (чтобы верхний объект TextBlock был сдвинут влево и вверх), а в эффекте «углубленного» текста задействованы положительные смещения. Те же эффекты можно (хотя и менее успешно) использовать с темной темой, но вам придется поменять знаки X и Y.

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

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

Создание эффекта глубины для текста

Генерирование элементов выполняется полностью в файле фонового кода:

using Windows.UI;
using Windows.UI.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;

namespace WinRTTestApp
{
    public sealed partial class MainPage : Page
    {
        const int COUNT = 48;   // ~1/2 дюйма

        public MainPage()
        {
            this.InitializeComponent();

            Grid grid = this.Content as Grid;
            Brush foreground = this.Resources["ApplicationForegroundThemeBrush"] as Brush;
            Brush grayBrush = new SolidColorBrush(Colors.Gray);

            for (int i = 0; i < COUNT; i++)
            {
                bool firstOrLast = i == 0 || i == COUNT - 1;

                TextBlock txtblk = new TextBlock
                {
                    Text = "DEPTH",
                    FontSize = 192,
                    FontWeight = FontWeights.Bold,
                    HorizontalAlignment = HorizontalAlignment.Center,
                    VerticalAlignment = VerticalAlignment.Center,
                    RenderTransform = new TranslateTransform
                    {
                        X = COUNT - i - 1,
                        Y = i - COUNT + 1,
                    },
                    Foreground = firstOrLast ? foreground : grayBrush
                };
                grid.Children.Add(txtblk);
            }
        }
    }
}

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

Ранее я приводил пример анимации вложенных свойств Canvas.Left и Canvas.Тор для перемещения объекта по экрану. Такого же эффекта можно добиться, определив преобразование TranslateTransform для перемещаемого элемента с применением анимации свойствам X и Y. Преимущество такого решения заключается в том, что анимированный объект не обязан быть потомком Canvas, однако особых различий в производительности не видно. Анимации обоих типов выполняются во вторичных потоках.

Пройди тесты
Лучший чат для C# программистов