Анимация вложенных свойств в WinRT
66WinRT --- Анимация вложенных свойств
Один из простейших вариантов использования трансформаций, о которых будет рассказано позже, обеспечивает перемещение объекта по экрану. Однако трансформации для этого не обязательны - вы можете разместить объект на панели Canvas и анимировать вложенные свойства Canvas.Left и Canvas.Top. Анимация вложенных свойств требует использования специального синтаксиса Storyboard.TargetProperty:
<Page ...>
<Page.Resources>
<Storyboard x:Key="storyboard">
<DoubleAnimation Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Left)"
From="0" Duration="0:0:2.5"
AutoReverse="True"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Top)"
From="0" Duration="0:0:1"
AutoReverse="True"
RepeatBehavior="Forever" />
</Storyboard>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Canvas SizeChanged="Canvas_SizeChanged"
Margin="0 0 48 48">
<Ellipse Name="ellipse" Width="48" Height="48" Fill="Red" />
</Canvas>
</Grid>
</Page>
Вложенные свойства Canvas.Left и Canvas.Top просто заключаются в круглые скобки. Целью анимации является объект Ellipse, окрашенный в красный цвет. Обратите внимание на отсутствие настройки EnableDependentAnimation. Это означает, что анимации не выполняются в потоке пользовательского интерфейса. Если вы не уверены в том, использовать EnableDependentAnimation или нет, попробуйте не указывать этот параметр. Если анимация работает - все хорошо!
Объект Storyboard содержит двух потомков DoubleAnimation, выполняемых синхронно. Обратите внимание: в каждом из определений DoubleAnimation свойству AutoReverse задается значение True, свойству RepeatBehavior - значение Forever, а свойствам Duration задается продолжительность 1 и 2,5 секунды соответственно. Для обеих анимаций задаются свойства From, но нет свойств To. Это происходит в файле фонового кода:
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;
namespace WinRTTestApp
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
Loaded += (sender, args) =>
{
(this.Resources["storyboard"] as Storyboard).Begin();
};
}
private void Canvas_SizeChanged(object sender, SizeChangedEventArgs e)
{
Storyboard storyboard = this.Resources["storyboard"] as Storyboard;
// Анимация свойства Canvas.Left
DoubleAnimation anima = storyboard.Children[0] as DoubleAnimation;
anima.To = e.NewSize.Width;
// Анимация свойства Canvas.Top
anima = storyboard.Children[1] as DoubleAnimation;
anima.To = e.NewSize.Height;
}
}
}
Выполнение Storyboard начинается в обработчике события Loaded. При каждом изменении размера Canvas (которое происходит при изменении размера окна) новые значения To вычисляются по ширине и высоте объекта Canvas, которому в файле XAML назначаются поля (Margin) для компенсации размера Ellipse. Казалось бы, изменение значений текущей анимации должно быть запрещено, но оно нормально работает. В результате получается шарик, который перемещается, отскакивая от краев экрана.
Оба определения DoubleAnimation включают одинаковые настройки AutoReverse и RepeatBehavior. Как упоминалось ранее, эти свойства определяются классом Timeline, который также является родительским классом для Storyboard. Нельзя ли перенести эти две настройки в тег Storyboard? Давайте попробуем:
<Storyboard x:Key="storyboard"
AutoReverse="True"
RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Left)"
From="0" Duration="0:0:2.5" />
<DoubleAnimation Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Top)"
From="0" Duration="0:0:1" />
</Storyboard>
Решение выглядит вполне разумно, но работает не так, как предыдущая разметка. Свойство Duration объекта Storyboard определяет продолжительность самой длинной дочерней анимации Storyboard, которая в данном случае равна 2,5 секунды. Анимация начинается с перемещения шарика по горизонтали и вертикали. Но по истечении 1 секунды шарик сталкивается с краем - нижним в альбомной ориентации. Анимация свойства Canvas.Top завершена, но анимация Canvas.Left продолжает перемещать шарик по горизонтали еще 1,5 секунды. В этой стадии шарик находится в правом нижнем углу экрана.
Обе анимации завершены, поэтому Storyboard инвертирует только что воспроизведенную анимацию, чтобы шарик снова оказался в левом верхнем углу экрана. Далее эта последовательность повторяется бесконечно.
Итак, свойства AutoReverse и RepeatBehavior можно переместить в Storyboard только в том случае, если все анимации в Storyboard имеют одинаковую длину.