Анимация в XAML-графике
Анимация вдоль заданной траектории
Одна из самых интересных возможностей компьютерной анимации – это движение фигуры вдоль произвольно задаваемой траектории (рис. 7.9):

Рис. 7.9. 1. Два отдельных объекта. 2. Эллипс становится траекторией движения. 3. Движение вдоль заданной траектории (иллюстрация из справки Microsoft Expression Blend)
В качестве траектории может использоваться не только замкнутая фигура, но и вообще, любая кривая, нарисованная, например, с помощью инструмента "Кисть". К сожалению, на момент написания этого курса, в Silverlight-проектах не поддерживается привязка движения к траектории. Однако эта возможность реализована в WPF-приложениях. Рассмотрим такой пример на практике. Создаем новый WPF – проект (рис. 7.10):
Сначала нарисуем окружность, которая будет служить траекторией. Для этого выбираем инструмент эллипс и рисуем фигуру – можно даже без всякой заливки (рис. 7.11):
Теперь добавим окружность, которая и будет двигаться. Ее расположение на холсте, цвет заливки и оформления могут быть совершенно произвольными. Но на панели "Properties", в поле "Name " введем имя фигуры, например, "myBall" (рис. 7.12):
увеличить изображение
Рис. 7.12. Фигура, которая будет двигаться по траектории, должна иметь заполненное значение поля Name
Выделяем исходный эллипс, который будет служить траекторией и в главном меню выбираем пункт "Object \ Path \ Convert to Motion Path" (рис. 7.13):
При этом происходит преобразование текущей кривой в траекторию движения. В появившемся диалоговом окне "Convert to Motion Path" нам нужно выбрать объект, который будет привязан к создаваемой траектории. Здесь мы указываем объект "myBall" (рис. 7.14):
Практически все готово. Вид редактора Microsoft Expression Blend меняется – шарик перескакивает на свою стартовую позицию, причем его центр совмещен с траекторией (рис. 7.15):
увеличить изображение
Рис. 7.15. Вид редактора Microsoft Expression Blend после завершения привязки объекта к траектории
Запускаем приложение, нажимая клавишу F5. Объект двигается по замкнутой траектории (рис. 7.16):
Если сделать направляющую нулевой толщины или установить для нее белый цвет контура, то она будет не видна. Дальнейшее оформление ограничено лишь фантазией разработчика. Код, сгенерированный средой, достаточно громоздок:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/
xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Motion_Path.Window1"
x:Name="Window"
Title="Window1"
Width="640" Height="480">
<Window.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingPath BeginTime="00:00:00"
Duration="00:00:02" Storyboard.TargetName="myBall"
Storyboard.TargetProperty="(UIElement.RenderTransform).(
TransformGroup.Children)[3].
(TranslateTransform.X)" Source="X">
<DoubleAnimationUsingPath.PathGeometry>
<PathGeometry>
<PathFigure IsClosed="True"
StartPoint="241.5,12">
<BezierSegment Point1="241.5,53.1452138623941"
Point2="167.179268471912,86.5" Point3="75.5,86.5" IsSmoothJoin="True"/>
<BezierSegment Point1="-16.1792684719117,86.5"
Point2="-90.5,53.1452138623941" Point3="-90.5,12" IsSmoothJoin="True"/>
<BezierSegment Point1="-90.5,-29.1452138623941"
Point2="-16.1792684719117,-62.5" Point3="75.5,-62.5" IsSmoothJoin="True"/>
<BezierSegment Point1="167.179268471912,-62.5"
Point2="241.5,-29.1452138623941" Point3="241.5,12" IsSmoothJoin="True"/>
</PathFigure>
</PathGeometry>
</DoubleAnimationUsingPath.PathGeometry>
</DoubleAnimationUsingPath>
<DoubleAnimationUsingPath
BeginTime="00:00:00" Duration="00:00:02"
Storyboard.TargetName="myBall" Storyboard.
TargetProperty="(UIElement.RenderTransform).
(TransformGroup.Children)[3].(TranslateTransform.Y)" Source="Y">
<DoubleAnimationUsingPath.PathGeometry>
<PathGeometry>
<PathFigure IsClosed="True" StartPoint="241.5,12">
<BezierSegment Point1="241.5,53.1452138623941"
Point2="167.179268471912,86.5" Point3="75.5,86.5" IsSmoothJoin="True"/>
<BezierSegment Point1="-16.1792684719117,86.5"
Point2="-90.5,53.1452138623941" Point3="-90.5,12" IsSmoothJoin="True"/>
<BezierSegment Point1="-90.5,-29.1452138623941"
Point2="-16.1792684719117,-62.5" Point3="75.5,-62.5" IsSmoothJoin="True"/>
<BezierSegment Point1="167.179268471912,-62.5"
Point2="241.5,-29.1452138623941" Point3="241.5,12" IsSmoothJoin="True"/>
</PathFigure>
</PathGeometry>
</DoubleAnimationUsingPath.PathGeometry>
</DoubleAnimationUsingPath>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Ellipse Margin="144,0,147,53" VerticalAlignment="Bottom"
Height="150" Fill="#FFFFFFFF" Stroke="#FF000000"/>
<Ellipse HorizontalAlignment="Left" Margin="210,0,0,115"
VerticalAlignment="Bottom" Width="50" Height="50"
Fill="#FFFF0000"
Stroke="#FF000000" x:Name="myBall" RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse>
</Grid>
</Window>
7.1.
Его можно упростить, если убрать дробные значения в координатах, а также удалить ненужные команды трансформации:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Motion_Path.Window1"
x:Name="Window"
Title="Window1"
Width="640" Height="480">
<Window.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingPath BeginTime="00:00:00"
Duration="00:00:02" Storyboard.TargetName="myBall"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" Source="X">
<DoubleAnimationUsingPath.PathGeometry>
<PathGeometry>
<PathFigure IsClosed="True" StartPoint="241.5,12">
<BezierSegment Point1="241.5,53.1"
Point2="167.1,86.5" Point3="75.5,86.5" />
<BezierSegment Point1="-16.1,86.5"
Point2="-90.5,53.1" Point3="-90.5,12" />
<BezierSegment Point1="-90.5,-29.1"
Point2="-16.1,-62.5" Point3="75.5,-62.5" />
<BezierSegment Point1="167.179268471912,-62.5"
Point2="241.5,-29.1" Point3="241.5,12" />
</PathFigure>
</PathGeometry>
</DoubleAnimationUsingPath.PathGeometry>
</DoubleAnimationUsingPath>
<DoubleAnimationUsingPath BeginTime="00:00:00"
Duration="00:00:02" Storyboard.TargetName="myBall" Storyboard.
TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)" Source="Y">
<DoubleAnimationUsingPath.PathGeometry>
<PathGeometry>
<PathFigure IsClosed="True" StartPoint="241.5,12">
<BezierSegment Point1="241.5,53.1"
Point2="167.1,86.5" Point3="75.5,86.5" />
<BezierSegment Point1="-16.1,86.5"
Point2="-90.5,53.1" Point3="-90.5,12" />
<BezierSegment Point1="-90.5,-29.1"
Point2="-16.1,-62.5" Point3="75.5,-62.5" />
<BezierSegment Point1="167.179268471912,-62.5"
Point2="241.5,-29.1" Point3="241.5,12" />
</PathFigure>
</PathGeometry>
</DoubleAnimationUsingPath.PathGeometry>
</DoubleAnimationUsingPath>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Ellipse Margin="144,0,147,53" VerticalAlignment="Bottom"
Height="150" Fill="Transparent" Stroke="Black"/>
<Ellipse HorizontalAlignment="Left" Margin="210,0,0,115"
VerticalAlignment="Bottom" Width="50" Height="50"
Fill="Red" x:Name="myBall" RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Ellipse.RenderTransform>
</Ellipse>
</Grid>
</Window>
7.2.
Здесь мы видим, что привязка к траектории, описываемая объектом Path, осуществляется дважды – для команды TranslateTransform.X и TranslateTransform.Y. Вместо данных, подставляемых в объект Path, можно подставлять свои значения, созданные без всяких визуальных средств.
Завершив изучение этой лекции, полезно прочитать статью Деклана Бреннана (Declan Brennan) "Создание сложной трехмерной анимации с помощью Silverlight 2.0" http://msdn.microsoft.com/ru-ru/magazine/cc500570.aspx.






