Анимация в XAML

Последнее обновление: 04.03.2016

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

Непосредственно для определения анимации используется объект Storyboard. Он объявляет объект анимации со всеми ее свойствами и параметрами. Например, проанимируем ширину кнопки:

<Window x:Class="AnimationApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:AnimationApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Window.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard TargetProperty="Width" TargetName="helloButton">
                        <DoubleAnimation From="70" To="150" 
    AutoReverse="True" 
    RepeatBehavior="0:0:10" 
    Duration="0:0:3" 
    Completed="ButtonAnimation_Completed" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Window.Triggers>
    <Grid>
        <Button x:Name="helloButton" Width="70" Height="30" Content="Hello" />
    </Grid>
</Window>

У объекта EventTrigger с помощью атрибута RoutedEvent определяется событие, которое будет запускать анимацию. В данном случае это событие Loaded - загрузка окна.

Ряд настроек анимации устанавливает элемент Storyboard: TargetName задает анимируемый элемент, а TargetProperty определяет свойство элемента, которое будет анимироваться.

В принципе эти настройки также можно было бы вынести в объект анимации в виде прикрепляемых свойств:

<Storyboard>
    <DoubleAnimation Storyboard.TargetProperty="Width" Storyboard.TargetName="helloButton" 
						From="70" To="150"  ...>

И далее в самом объекте Storyboard определяется объект анимации DoubleAnimation с рядом настроек. Все настройки в прицнипе тут те же, что использовались для анимации в прошлой теме. Правда, при определении значений свойств здесь есть некоторые отличия.

Так, свойство RepeatBehavior инициализируется временем - "0:0:10", которое будет повторяться анимация. Чтобы указать число повторов, структуру RepeatBehavior надо инициализировать так: RepeatBehavior="2x", где 2 - количество повторов, а x - просто префикс, указывающий, что речь идет о количестве итераций, без него бы число интерпретировалось как количество дней. Третий способ задания этого свойства - RepeatBehavior="Forever" - в этом случае анимация будет продолжаться все время работы приложения.

Например, ниже установлено RepeatBehavior="Forever", а свойство DecelerationRatio замедляет анимацию, что создает эффект подскока шара в верх, где он, достигая максимальной точки, теряет скорость, а при падении вновь ее увеличивает:

<Window x:Class="AnimationApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:AnimationApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Window.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard Timeline.DesiredFrameRate="60">
                        <DoubleAnimation Storyboard.TargetName="ball" Storyboard.TargetProperty="(Canvas.Bottom)"
                                 From="0" To="160" AutoReverse="True" Duration="0:0:2.5" RepeatBehavior="Forever"
                                 DecelerationRatio="1"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Window.Triggers>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Canvas Background="LightPink">
            <Ellipse Name="ball" Fill="Red" Stroke="Black"  Width="15" Height="15" 
						Canvas.Left="130" Canvas.Bottom="0" />
        </Canvas>
        <Button Width="70" Height="25" Content="Кнопка" Grid.Row="1" Margin="10" />
    </Grid>
</Window>

В данном случае так как в EventTrigger в качестве события определено Button.Click, то анимация будет запускаться по нажатию на кнопку.

По умолчанию анимация вызывается 60 раз в секунду, однако с помощью прикрепленного свойства Timeline.DesiredFrameRate можно задать частоту кадров в секунду, как в предыдущем примере.

Анимация свойств вложенных объектов

Анимация может применяться и к свойствам вложенных объектов, которые являются свойствами, например:

<Ellipse Name="ball" Stroke="Black"  Width="20" Height="20" Canvas.Left="130" Canvas.Bottom="0">
    <Ellipse.Fill>
        <RadialGradientBrush RadiusX="1" RadiusY="1" GradientOrigin="0.3, 0.3">
            <GradientStop Color="White" Offset="0" />
            <GradientStop Color="Blue" Offset="1" />
        </RadialGradientBrush>
    </Ellipse.Fill>
    <Ellipse.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <ColorAnimation Storyboard.TargetProperty="Fill.GradientStops[1].Color"
                            To="Yellow" Duration="0:0:8" AutoReverse="True"
                            RepeatBehavior="Forever" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Ellipse.Triggers>
</Ellipse>

Здесь свойство Fill элемента Ellipse инициализируется кистью RadialGradientBrush, которая имеет коллекцию GradientStops. Анимация же применяется ко второму объекту коллекции и его свойству Color.

Комплексные анимации

С помощью объекта Storyboard можно создавать и более комплексные анимации. Например, сделаем кнопку, которая одновременно меняет ширину, длину и цвет:

<Button x:Name="helloButton" Foreground="White" Width="70" Height="25" Content="Кнопка">
    <Button.Background>
        <SolidColorBrush x:Name="buttonColor" Color="Black" />
    </Button.Background>
    <Button.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="Width" Storyboard.TargetName="helloButton"
							  From="80" To="150"  AutoReverse="True" RepeatBehavior="0:0:10" Duration="0:0:2"  />
                        <DoubleAnimation Storyboard.TargetProperty="Height" Storyboard.TargetName="helloButton"
                              From="30" To="100" AutoReverse="True" RepeatBehavior="0:0:10" Duration="0:0:2" />
                        <ColorAnimation Storyboard.TargetName="buttonColor" Storyboard.TargetProperty="Color"
                              From="{Binding ElementName=buttonColor, Path=Color}" To="Red"
                              AutoReverse="True" RepeatBehavior="0:0:10" Duration="0:0:2" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Button.Triggers>
</Button>

Определение анимации в стиле

При этом необязательно знать имя элемента для анимации, можно прикрепить анимацию ко всем элементам одного типа и установить ее через стиль:

<Window x:Class="AnimationApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:AnimationApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Window.Resources>
        <Style TargetType="Button">
            <Style.Triggers>
                <EventTrigger RoutedEvent="Button.Click">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetProperty="Background.Color"
   To="Red" AutoReverse="True" Duration="0:0:2" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel>
        <Button Width="70" Height="25" Content="Кнопка 1" Margin="10" />
        <Button Width="70" Height="25" Content="Кнопка 2" Margin="10" />
    </StackPanel>
</Window>

Так как у стиля задан атриубут TargetType="Button", то анимация внутри триггера будет применяться ко всем кнопкам. В качестве анимируемого свойства указывается "Background.Color". То есть у класса Button есть свойство Background, представленное объектом SolidColorBrush, а у этого объекта есть свойство Color. Напрямую анимировать свойство Background мы не можем, так как ColorAnimation требует типа Color.

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

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

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850