Главная » Разработка для Windows Phone 7 » Некоторые вариации Windows Phone 7

0

Я задал целевое свойство анимации, используя полное имя свойства-зависимости:

Storyboard.SetTargetProperty(anima, new PropertyPath(RotateTransform.AngleProperty));

Альтернативный вариант – использование строки:

Storyboard.SetTargetProperty(anima, new PropertyPath("Angle"));

Этот синтаксис может казаться более привлекательным, поскольку он короче, однако, в этом случае велика вероятность ошибочного написания имени свойства.

Преимущество применения строк для задания свойств в том, что так мы можем задавать несколько имен свойств подряд. Это позволяет применять анимацию к свойству объекта без ссылки на сам объект. Например, в приведенном выше обработчике событий Click целью анимации можно задать Button, а не RotateTransform:

Storyboard.SetTarget(anima, btn);

RotateTransform по-прежнему должен присутствовать, и мы по-прежнему должны указывать, что целью является свойство Angle этого объекта, но посмотрите, как это делается:

Storyboard.SetTargetProperty(anima,

new PropertyPath("(Button.RenderTransform).(RotateTransform.Angle)"));

Этот синтаксис (несомненно более типичный для XAML, чем для кода) показывает, что RenderTransform является свойством Button, и Angle – свойство RotateTransform, и RotateTransform задан как значение свойства RenderTransform. Если объект RotateTransform не задан как значение свойства RenderTransform, ничего не получится.

Этот синтаксис можно немного упростить, удалив развернутое описание свойства Angle:

Storyboard.SetTargetProperty(anima,

new PropertyPath("(Button.RenderTransform).Angle"));

Но такой синтаксис может быть непонятным. Кажется, что Angle является свойством RenderTransform, а это на самом деле не так. Angle – это свойство объекта RotateTransform, который задан как значение свойства RenderTransform.

Независимо от того как оно задается, анимированное свойство должно быть свойством- зависимостью.

Классы Storyboard и DoubleAnimation на самом деле являются классами одного уровня, как видно из следующей иерархии классов:

Object

DependencyObject (абстрактный) Timeline (абстрактный)

DoubleAnimation

DoubleAnimationUsingKeyFrames

ColorAnimation

ColorAnimation UsingKeyFrames PointAnimation

PointAnimationUsingKeyFrames

ObjectAnimationUsingKeyFrames

Storyboard

Storyboard определяет свойство Children типа TimelineCollection (Коллекция временной шкалы). Это означает, что Storyboard может включать не только объекты анимации, но и другие объекты Storyboard для управления сложными коллекциями анимаций. Storyboard также описывает присоединенные свойства, используемые для связывания анимации с определенным объектом и свойством-зависимостью.

Класс Timeline (Временная шкала) определяет свойство Duration, для которого задано значение 0,5 секунды:

anima.Duration = new Duration(TimeSpan.FromSeconds(0.5));

При этом для раскадровки также можно задать меньшую продолжительность:

storyboard.Duration = new Duration(TimeSpan.FromSeconds(0.25));

Тогда анимация будет обрезана на 0,25 секунде. По умолчанию за продолжительность раскадровки берется самая большая продолжительность дочерних Timeline (в данном случае это 0,5 секунды), и в большинстве случаев это значение не переопределяется.

Timeline также описывает свойство BeginTime (Момент начала), которое можно задать либо для Storyboard, либо для DoubleAnimation:

anima.BeginTime = TimeSpan.FromSeconds(1);

Теперь запуск анимации будет отложен на 1 секунду.

Свойство AutoReverse (Автоматический возврат) типа Boolean со значением по умолчанию false. Зададим ему значение true:

anima.AutoReverse = true;

Теперь кнопка поворачивается на 360° по часовой стрелке и затем на 360° в обратном направлении . Общая продолжительность анимации составляет 1 секунду.

Свойство RepeatBehavior (Поведение повтора) указывает на то, сколько раз должна повториться анимация:

anima.RepeatBehavior = new RepeatBehavior(3);

Теперь кнопка делает три оборота общей продолжительностью 1,5 секунды. RepeatBehavior можно комбинировать с AutoReverse: anima.RepeatBehavior = new RepeatBehavior(3); anima.AutoReverse = true;

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

А если мы хотим, чтобы кнопка сделала три оборота по часовой стрелке и затем три оборота против? Нет ничего проще. Просто зададим RepeatBehavior для анимации:

anima.RepeatBehavior = new RepeatBehavior(3);

И AutoReverse для Storyboard:

storyboard.AutoReverse = true;

Значением RepeatBehavior может быть не только количество повторов, но единицы времени:

anima.RepeatBehavior = new RepeatBehavior(TimeSpan.FromSeconds(0.7 5));

Теперь анимация кнопки будет повторяться в течение заданного для RepeatBehavior времени. В данном случае это составит разворота, и кнопка остановится в перевернутом положении (чтобы вернуть ее в нормальное состояние, AutoReverse должно быть задано true).

Свойству RepeatBehavior также может быть задано статическое значение RepeatBehavior.Forever (Постоянно), но, вероятно, для данного конкретного примера применять его нежелательно!

Для следующих нескольких экспериментов удалим все внесенные до сих пор изменения, приводя приложение в исходное состояние, только зададим продолжительность анимации равной 5, чтобы более ясно видеть, что происходит:

anima.Duration = new Duration(TimeSpan.FromSeconds(5));

Можно последовательно нажать все три кнопки, и анимации будут выполняться независимо. Такое поведение вполне ожидаемо, поскольку анимации являются независимыми объектами. Но что произойдет, если щелкнуть кнопку, для которой уже выполняется анимация? Как выясняется, она начнет движение заново. По сути, в этом случае мы применяем новую анимацию, которая замещает предыдущую, и новая анимация всегда начинается с угла 0° и выполняется до угла 360°. Рассмотрим, как описаны эти свойства:

anima.From = 0; anima.To = 360;

Свойства-зависимости, такие как свойство Angle объекта RotateTransform, имеют базовое значение. Это значение свойства, когда анимация неактивна. Класс DependencyObject определяет метод GetAnimationBaseValue (Получить базовое значение анимации), с помощью которого можно получить это значение. GetAnimationBaseValue может быть вызван для любого производного от DependencyObject. В качестве аргумента в него передается DependencyProperty, например, RotateTransform.AngleProperty.

Если вызвать GetAnimationBaseValue для данного свойства Angle, будет возвращено значение нуль. Закомментируем свойство From, оставляя только To:

// anima.From = 0; anima.To = 360;

И все работает! Выполняется анимация свойства Angle от ее базового значения нуль до заданного 360. Но если многократно щелкнуть Button во время вращения, происходит нечто странное. Возвращения кнопки в исходное положение к 0° не происходит, потому что

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

На самом ли деле такой сценарий работоспособен? Нажмем на кнопку еще раз после того, как анимация будет завершена. Ничего не происходит! После выполнения анимации свойство Angle остается с заданным значением 360, поэтому последующим анимациям просто нечего делать!

Теперь попробуем следующее:

anima.From = -360; anima.To = null;

Выражение для свойства To кажется странным, поскольку из всего увиденного выше можно предположить, что From и To типа double. Но на самом деле эти свойства являются допускающими пустое значение double, и их значение по умолчанию – null. Задание null равноценно незаданию свойства вообще. Поведение в этом случае во многом похоже на поведение при исходных значениях: при каждом щечке кнопка перескакивает к значению – 360°, и затем анимация возвращает ее к базовому значению, каковым является 0.

Посмотрим на это еще раз:

// anima.From = 0; anima.To = 360;

По завершении анимации свойство Angle сохраняет значение 360. Такое поведение обусловлено свойством FillBehavior (Поведение завершения), определенным Timeline. Значением этого свойства по умолчанию является член перечисления FillBehavior.HoldEnd (Сохранять конечное значение), при котором свойство будет сохранять конечное значение по завершении анимации. Попробуем такой альтернативный вариант:

// anima.From = 0; anima.To = 360;

anima.FillBehavior = FillBehavior.Stop;

Эти настройки приводят к удалению из свойства последствий анимации. По завершении анимации свойству Angle будет возвращено исходное значение 0. Визуально изменения значения увидеть нельзя, потому что 0° аналогично 360°, но значение изменяется. Если задать свойству To значение 180, то возвращение свойства к исходному значению будет более наглядным.

Альтернативой свойствам To и From является By (На):

// anima.From = 0; // anima.To = 360; anima.By = 90;

anima.FillBehavior = FillBehavior.HoldEnd;

В данном случае FillBehavior задано значение по умолчанию HoldEnd. По каждому щелчку кнопка разворачивается на 90°. Но если щелкнуть кнопку во время ее движения, отсчет угла поворота для новой анимации начнется с текущего положения кнопки, т.е. в итоге кнопка будет развернута на какой-то непонятный угол. Значение By позволяет прогрессивно увеличивать свойство на определенную величину при каждом последующем применении анимации.

Источник: Чарльз Петзольд, Программируем Windows Phone 7, Microsoft Press, © 2011.

По теме:

  • Комментарии