понедельник, 7 января 2013 г.

Анимация в WPF

Перед тем, как поговорить об анимации в Windows Store приложениях, давайте немного посмотрим, как можно воспользоваться анимацией в обычный WPF приложениях. Я как то уже приводил пример анимации в статье про триггеры. Но он там был один, к тому же на самый простой.
Итак, повторение - мать учения. Поэтому первый пример, на анимацию числового значения.

<Button Width="100" Height="40">
    <Button.Triggers>
        <EventTrigger RoutedEvent="Button.MouseEnter">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Width" BeginTime="00:00:00" Duration="00:00:00.5" To="110" />
                    <DoubleAnimation Storyboard.TargetProperty="Height" BeginTime="00:00:00.2" Duration="00:00:00.5" To="45" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="Button.MouseLeave">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Width" BeginTime="00:00:00" Duration="00:00:00.5" To="100" />
                    <DoubleAnimation Storyboard.TargetProperty="Height" BeginTime="00:00:00.2" Duration="00:00:00.5" To="40" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Button.Triggers>
</Button>
Теперь, при наведении указателя мышки на кнопку, у нас она будет увеличиваться в размерах (сначала по ширине, а потом начнет и по высоте). После того, как мышку с кнопки уберут, кнопка вернется к исходным размерам.
Чуть более сложный пример, поанимируем текст. Пусть, при наведении машки на кнопку, у нас будет появляться по буквам "Нажми меня". Для этого, достаточно добавить вот такую анимацию:
<StringAnimationUsingKeyFrames Storyboard.TargetProperty="Content" Duration="0:0:1.1" RepeatBehavior="Forever" >
    <DiscreteStringKeyFrame Value="Н" KeyTime="0:0:0.1" />
    <DiscreteStringKeyFrame Value="На" KeyTime="0:0:0.2" />
    <DiscreteStringKeyFrame Value="Наж" KeyTime="0:0:0.3" />
    <DiscreteStringKeyFrame Value="Нажм" KeyTime="0:0:0.4" />
    <DiscreteStringKeyFrame Value="Нажми" KeyTime="0:0:0.5" />
    <DiscreteStringKeyFrame Value="Нажми " KeyTime="0:0:0.6" />
    <DiscreteStringKeyFrame Value="Нажми м" KeyTime="0:0:0.7" />
    <DiscreteStringKeyFrame Value="Нажми ме" KeyTime="0:0:0.8" />
    <DiscreteStringKeyFrame Value="Нажми мен" KeyTime="0:0:0.9" />
    <DiscreteStringKeyFrame Value="Нажми меня" KeyTime="0:0:1" />
</StringAnimationUsingKeyFrames>
Благодоря   RepeatBehavior, надпись будет набираться по буквам до конца, потом исчезать, чтобы опять появится в побуквенном режиме. Убрать эту анимацию, можно аналогично анимации с размерами:
<StringAnimationUsingKeyFrames Storyboard.TargetProperty="Content" Duration="0:0:0" RepeatBehavior="Forever" >
    <DiscreteStringKeyFrame Value="" KeyTime="0:0:0" />
</StringAnimationUsingKeyFrames>
Ну и еще пример, на покадровую анимацию, с цветами. В отличии от текста, цвет нельзя сразу присвоить к свойству. Ведь всякие Foreground и Background не цвет, а кисть. Поэтому, анимацию цвета, придется задавать вот так:
<Button Width="100" Height="40">
    <Button.Foreground>
        <SolidColorBrush x:Name="foregroundBrush" Color="Green" />
    </Button.Foreground>
    <Button.Triggers>
        <EventTrigger RoutedEvent="Button.MouseEnter">
            <BeginStoryboard>
                <Storyboard>
                    <ColorAnimationUsingKeyFrames Storyboard.TargetName="foregroundBrush" Storyboard.TargetProperty="Color">
                        <DiscreteColorKeyFrame Value="Red" />
                    </ColorAnimationUsingKeyFrames>
По большому счету, никакой разницы, только нам, кроме свойства, приходится задавать имя кисти, которая присвоена свойству Foreground.
Собственно, как используя анимацию, можно сделать панельку, типа той, что всплывает справа в Windows 8. Для этого, можно задать вот такую простую разметку:
<Grid>
    <DataGrid x:Name="dgMatrix" />
    <StackPanel Width="5" Background="Black" HorizontalAlignment="Right" >
        <StackPanel.Triggers>
            <EventTrigger RoutedEvent="StackPanel.MouseEnter">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="Width" To="100" Duration="00:00:01" />
                        <DoubleAnimation Storyboard.TargetProperty="Opacity" To="0.8" Duration="00:00:01" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
            <EventTrigger RoutedEvent="StackPanel.MouseLeave">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="Width" To="5" Duration="00:00:01" />
                        <DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:01" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </StackPanel.Triggers>
        <Button Margin="5">Настройки</Button>
        <Button Margin="5">Доступ</Button>           
    </StackPanel>
</Grid>
Выглядит все это вот так:
Ладно, на сегодня все. В следующий раз, продолжим.

4 комментария:

  1. только два дня убил на Popup окно. Такого же функционала. А так всё просто с разметкой оказалось. :)

    ОтветитьУдалить
  2. Я думал будет сложнее чем на WinForms, отдалено напоминает css свойста

    ОтветитьУдалить
    Ответы
    1. Насколько я понимаю, такая идея и стояла при разработке WPF, отделить внешний вид от отработки в во внешнем виде задание элементов отделить от их визуального оформления.

      Удалить