Анимации и трансформации

Анимация

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

Анимация в коде

За анимацию в Silverlight отвечает пространство имен System.Windows.Media.Animation. Оно содержит довольно большой набор классов, позволяющих анимировать различные свойства. Правда, готовые классы анимации есть только для свойств зависимостей. Например, для изменения таких свойств, как длина, ширина, предназначен класс DoubleAnimation. Для изменения цвета фона или шрифта - ColorAnimation, для изменения свойства Margin - ThiknessAnimation. Для большинства свойств подобраны определенные классы из пространства имен System.Windows.Media.Animation. Это важно учитывать, поскольку мы не можем использовать анимацию типа DoubleAnimation для анимирования свойства с типом Color.

Например, у нас есть кнопка button1 - проанимируем ее свойство Width:

using System.Windows.Media.Animation;
.....................................
	private void Button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation a = new DoubleAnimation();
            a.From = button1.ActualWidth;
            a.To = 150;
            a.Duration = TimeSpan.FromSeconds(3);
            Storyboard.SetTarget(a, button1);
            Storyboard.SetTargetProperty(a, new PropertyPath(Button.WidthProperty));
            Storyboard animation = new Storyboard();
            animation.Children.Add(a);
            animation.Begin();  
        }  

В данном случае мы сначала задаем тип анимации и создаем ее. Поскольку изменяется свойство Width, это будет DoubleAnimation. Свойство From - объявляет начальное значение, с которого будет начинаться анимация, а свойство To- конечное значение. Свойство Duration - задает время анимации.

Далее мы используем класс Storyboard для привязки анимации к определенному свойству. Сначала с помощью метода SetTarget мы устанавливаем анимацию для определенного элемента - в данном случае для кнопки button1. Затем с помощью метода SetTargetProperty привязываем анимацию к определенному свойству - в данном случае для свойства Width. Обратите внимание, что здесь употребляется не свойство как таковое, а соответствующее ему свойство зависимостей, поэтому вместо Width мы пишем WidthProperty.

В конце мы создаем объект Storyboard, к которому добавляем ранее созданный объект DoubleAnimation и с помощью метода Begin запускаем.

Объект анимации также обладает рядом других важных свойств. Например, установка свойства a.AutoReverse = True - после окончания расширения кнопки, вызвало бы обратный эффект, и кнопка достигла бы первоначальной ширины, которая была у нее до анимации.

Также на действие после окночания анимации можно повлиять с помощью свойства FillBehavior. Если оно имеет значение Stop, то после окончания анимации объект возвращает прежние значения: a.FillBehavior = FillBehavior.Stop

Если же оно имеет значение HoldEnd : a.FillBehavior = FillBehavior.HoldEnd, то анимация присваивает объекту новое значение.

А свойство BeginTime позволяет устанавить время задержки между запуском и началом анимации.

Чтобы повторить анимацию несколько раз подряд используется свойство RepeatBehavior:

private void Button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation a = new DoubleAnimation();
            a.Completed += a_Completed;
            a.AutoReverse = true;
            a.RepeatBehavior = new RepeatBehavior(3);
            a.From = button1.ActualWidth;
            a.To = 160;
            a.Duration = TimeSpan.FromSeconds(4);
            Storyboard.SetTarget(a, button1);
            Storyboard.SetTargetProperty(a, new PropertyPath(Button.WidthProperty));
            Storyboard animation = new Storyboard();
            animation.Children.Add(a);
            animation.Begin();  
        }
        private void a_Completed(object sender, EventArgs e)
        {
            MessageBox.Show("Анимация завершена");
        }

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

Анимация в XAML

Тот же самый пример мы могли определить в xaml-коде следующим образом:

<UserControl x:Class="TestApplication.MainPage"
    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:TestApplication"
    mc:Ignorable="d"
    d:DesignHeight="200" d:DesignWidth="250">
    <UserControl.Resources>
                    <Storyboard x:Name="stor1">
                        <DoubleAnimation Storyboard.TargetProperty="Width" From="80" To="150" Storyboard.TargetName="button1" 
                                         AutoReverse="True" RepeatBehavior="0:0:10" Duration="0:0:2" Completed="a_Completed" />
                    </Storyboard>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot">
        <Button x:Name="button1" Width="80" Height="30" Content="Нажми" Background="Red" Click="Button_Click" />
    </Grid>
</UserControl>

При этом код мы могли сократить следующим образом:

private void Button_Click(object sender, RoutedEventArgs e)
        {
            stor1.Begin();  
        }
        private void a_Completed(object sender, EventArgs e)
        {
            MessageBox.Show("Анимация завершена");
        }

В предыдущем случае анимация запускалась после возникновения события нажатия кнопки. Но мы можем ее запустить, абсолютно не используя код c#. Для этого нужно воспользоваться объектом EventTrigger. Этот объект имеет свойство Actions, которое включает ряд действий возникающих после возникновения события (в данном случае после события Loaded). Затем объект BeginStoryboard начинает анимацию, которая задается объектом Storyboard. Storyboard же и объявляет объект анимации со всеми ее свойствами и параметрами.

Уже в разметке объекта анимации задается объект с помощью прикрепленного свойства Storyboard.TargetName и анимируемое свойство этого объекта с помощью свойства Storyboard.TargetProperty. В случае, если анимируется прикрепленное свойство, например, Canvas.Top, то оно заключается в скобки : Storyboard.TargetProperty="(Canvas.Top)" Если переписать вышеприведенный пример в XAML, то получится следующее:

 <UserControl x:Class="TestApplication.MainPage"
    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"
    mc:Ignorable="d"
    d:DesignHeight="200" d:DesignWidth="250">
    <UserControl.Triggers>
        <EventTrigger>
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="Width" From="80" To="150" Storyboard.TargetName="button1" 
                                         AutoReverse="True" RepeatBehavior="0:0:10" Duration="0:0:2" Completed="a_Completed" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </UserControl.Triggers>
    <Grid x:Name="LayoutRoot">
        <Canvas>
            <Button x:Name="button1" Width="80" Height="30" Content="Нажми" Canvas.Top="20" />
        </Canvas>
    </Grid>
</UserControl>
 

К сожалению одно из сильных ограничений Silverlight по сравнению с WPF состоит в том, что мы не можем запускать анимацию только после события Loaded. Поэтому, чтобы проигрывать анимацию после нажатия кнопки, опять же придется писать код.

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

Например, создадим имитацию прыгающего и отскакивающего шара:

<UserControl x:Class="TestApplication.MainPage"
    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"
    mc:Ignorable="d"
    d:DesignHeight="200" d:DesignWidth="250">
    <UserControl.Triggers>
        <EventTrigger>
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="ellips" Storyboard.TargetProperty="(Canvas.Top)"
                                 From="160" To="0" AutoReverse="True" Duration="0:0:2.5" RepeatBehavior="Forever"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </UserControl.Triggers>
    <Grid x:Name="LayoutRoot">
        <Grid Background="Black">
            <Canvas Background="White" x:Name="canvas1" Height="170" Width="220">
                <Ellipse Name="ellips" Fill="Red" Width="10" Height="10" Canvas.Top="160" Canvas.Left="130"  />
            </Canvas>
        </Grid>
    </Grid>
</UserControl>

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

<UserControl.Triggers>
        <EventTrigger>
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="Width" From="80" To="150" Storyboard.TargetName="button1" 
                                         AutoReverse="True" RepeatBehavior="0:0:10" Duration="0:0:2" Completed="a_Completed" />
                        <DoubleAnimation Storyboard.TargetProperty="Height" From="30" To="100" Storyboard.TargetName="button1" 
                                         AutoReverse="True" RepeatBehavior="0:0:10" Duration="0:0:2" />
                        <ColorAnimation Storyboard.TargetName="buttonColor" Storyboard.TargetProperty="Color"
                                        From="{Binding ElementName=buttonColor, Path=Color}" To="DarkGreen"
                                         AutoReverse="True" RepeatBehavior="0:0:10" Duration="0:0:2" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </UserControl.Triggers>
    <Grid x:Name="LayoutRoot">
        <Button x:Name="button1" Width="80" Height="30" Content="Кнопка" VerticalAlignment="Center" >
            <Button.Background>
                <SolidColorBrush x:Name="buttonColor" Color="Black" />
            </Button.Background>
        </Button>
    </Grid>

Плавность анимации

Для создания плавности анимации используется различные фукнции плавности или эластичности (Easing functions). Например, одна из них - ElasticEase. Она ее свойство Oscillations определяет количество колебательных движений во время анимации, а элемент как бы пружинится. Свойство Springiness позволяет установить жесткость, и чем больше это значение, тем быстрее затухают колебания.

Еще одно свойство EasingMode указывает на режим эластичности и может принимать одно из трех значений:

  • EaseIn - функция плавности применяется в начале анимации

  • EaseOut - функция плавности применяется в конце анимации

  • EaseInOut - функция плавности применяется в начале и в конце анимации

Например,

  <UserControl.Triggers>
        <EventTrigger>
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="Width" From="80" To="150" Storyboard.TargetName="button1" 
                                         Duration="0:0:2">
                            <DoubleAnimation.EasingFunction>
                                <ElasticEase EasingMode="EaseOut" Oscillations="5" Springiness="4"></ElasticEase>
                            </DoubleAnimation.EasingFunction>
                        </DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetProperty="Height" From="30" To="100" Storyboard.TargetName="button1" 
                                         Duration="0:0:2" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </UserControl.Triggers>
    <Grid x:Name="LayoutRoot">
        <Button x:Name="button1" Width="70" Height="25" Content="Кнопка" />
    </Grid>

Следующие функции плавности имеют только один параметр - EasingMode и создают эластичность анимации на основе некоторой функции:

  • QuadraticEase - функция плавности на основе квадратичной функции

  • CubicEase - функция плавности на основе кубической функции

  • QuarticEase - создает анимацию с помощью формулы f(t) = t^4.

  • QuinticEase - создает анимацию с помощью формулы f(t) = t^5.

Эти же функции можно задать в другой функии плавности - PowerEase - она также строится на некотой алгебраической функции, а свойство Power задает степень функции.

В Silverlight есть еще несколько встроенных функций плавности:

  • BackEase возвращает анимацию назад, а ее свойство Amplitute задает амплитуду возврата

  • BounceEase создает эффект отскока, а свойство Bounces устанавливает количество отскоков.

  • CircleEase создает анимацию с помощью цикличной функции.

  • SineEase создает анимацию с помощью формулы синуса

  • ExponentialEase создает анимацию с помощью экспоненциальной формулы.

Анимации по ключевым кадрам

Все вышеприведенные типы анимаций, такие как ColorAnimation или DoubleAnimation, основывались на плавном смене значения. Есть еще второй род анимаций - анимации по ключевым кадрам, которые анимирует те же свойства, что и обычные анимации. Например, ColorAnimationUsingKeyFrames анимирует цвет, а DoubleAnimationUsingKeyFrames - различные числовые значение.

Анимации по ключевым кадрам имеет практически все те же свойства, что и обычные анимации. Основное отличие - анимации по кадрам имеют свойство KeyFrames, которое задают коллекцию кадров. Каждый кадр (KeyFrame) определяет значение для анимируемого свойства с помощью свойства Value и продолжительность кадра с помощью свойства KeyTime

     <UserControl.Triggers>
        <EventTrigger>
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)"
                                        AutoReverse="True" RepeatBehavior="Forever" Storyboard.TargetName="ellipse1">
                        <LinearDoubleKeyFrame KeyTime="0:0:1" Value="0" />
                        <LinearDoubleKeyFrame KeyTime="0:0:1" Value="40" />
                        <LinearDoubleKeyFrame KeyTime="0:0:1" Value="80" />
                        <LinearDoubleKeyFrame KeyTime="0:0:1" Value="120" />
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </UserControl.Triggers>
    <Grid x:Name="LayoutRoot">
        <Canvas Background="Black" Height="180" Width="230">
            <Ellipse Name="ellipse1" Width="15" Height="15" Canvas.Top="160" Canvas.Left="120">
                <Ellipse.Fill>
                    <RadialGradientBrush RadiusX="1" RadiusY="1" GradientOrigin="0.3, 0.3">
                        <GradientStop Color="White" Offset="0" />
                        <GradientStop Color="Black" Offset="1" />
                    </RadialGradientBrush>
                </Ellipse.Fill>
            </Ellipse>
        </Canvas>
    </Grid>

Тип кадра анимации определяется следующим образом: тип анимации задает тип изменяемого значения, например, ColorAnimationUsingKeyFrames - изменяемое значение типа Color. Тип кадра состоит из трех частей: вид кадра, например, линейный (Linear), тип изменяемого значения, и ключевого слова KeyFrame. То есть выше тип кадра был LinearColorKeyFrame.

Кроме линейных есть еще несколько видов кадров анимации:

  • Дискретные кадры, например, DiscreteColorKeyFrame, они обеспечивают резкую смену кадров.

  • Кадры, на основе сплайнов, например, SplineDoubleKeyFrame. В этом случае анимация строиться на основе кривой Безье. Свойство KeySpline определяет начальную и конечную точки участка сплайна. При чем начальная точка сплайна находится в начале координат (0,0), а конечная - в конце (1,1). Получаемый сплайн является отношением между временем (координата X) и анимируемым значением (координата Y).

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