Главная » Silverlight » Инкапсуляция анимаций

0

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

Например, можно создать класс FadeElementEffeet для плавного удаления элемен­та с экрана путем его затенения. После этого удалять элемент можно с помощью следу­ющего кода.

FadeElementEffeet fade = new FadeElementEffect();

fade.Animate(canvas);

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

Переход между страницами

В главе 7 рассматривается создание средств перехода к другим страницам прило­жения Silverlight. Для этого обычно используется базовый контейнер в качестве корне­вого элемента приложения. В базовый контейнер можно добавлять пользовательские элементы управления и при необходимости удалять их. Переход от одной страницы к другой состоит в удалении одних элементов управления и добавлении других.

Приложив немного усилий, можно дополнить эту методику средствами анимации. Например, легко создать анимацию, которая плавно затеняет одну страницу и прорисо­вывает другую или перемещает размытую линию, оставляющую после себя новую стра­ницу (эффект занавеса). Для реализации любого из этих методов нужно добавить обе страницы (старую и новую) в корневой элемент одну поверх другой. Легче всего это сде­лать, разместив обе страницы в одной ячейке Grid, но можно разместить их и в контей­нере Canvas. Затем нужно анимировать свойства вышележащей страницы. Например, можно изменять свойство Opacity, чтобы плавно прорисовать страницу, или свойства объекта TranslateTransform для вывода замещающей линии. Можно даже создать ряд других эффектов, например расширять новую страницу с угла, одновременно осветляя ее.

Далее рассматривается создание эффекта занавеса, который плавно закрывает ста­рую страницу и открывает новую (рис. 10.13). На среднем рисунке выведено по полови­не каждой страницы; граница между страницами размыта.

Рис. 10.13. Переход между страницами с помощью занавеса

Корневой элемент приложения — контейнер Grid, поэтому в классе Application необходим следующий код.

// Создание контейнера Grid, хостирующего обе страницы

private Grid rootvisual = new GridO ;

private void Application_Startup(object sender,

StartupEventArgs e)

(

// Загрузка первой страницы

this. RootVisual = rootvisual;

rootvisual.Children.Addfnew PageO);                                                      x

}

Использованная методика описана в главе 7.

Базовый класс

Анимировать переход на другую страницу легче всего путем кодирования перехода непосредственно в классе Арр с помощью метода Navigate (). Однако приложение будет более гибким (но его создание немного более трудоемким), если разместить код анима­ции в отдельном классе. Стандартизировав анимацию в абстрактном классе или интер­фейсе, вы получите возможность легко добавлять новые эффекты.

В рассматриваемом примере все переходы наследуют абстрактный класс PageTransitonBase, в полях которого хранятся раскадровка, предыдущая страница и новая страница.

public abstract class PageTransitionBase {

protected Storyboard storyboard = new Storyboard(); protected UserControl oldPage; protected UserControl newPage;

public PageTransitionBase () {

storyboard.Completed += TransitionCompleted;

}

Для перехода от одной страницы к другой приложение вызывает метод PageTransitionBase.Navigate О . Вызванный метод добавляет обе страницы в контей­нер Grid, вызывает метод PrepareStoryboardO , чтобы подготовить раскадровку, и за­пускает анимацию.

public void Navigate(UserControl newPage) {

// Установка страниц this.newPage = newPage;

Grid grid = (Grid)Application.Current.RootVisual; oldPage = (UserControl)grid.Children[0];

II Вставка новой страницы

grid.Children.Insert(0, newPage);

// Подготовка анимации PrepareStoryboard ();

// Запуск анимации storyboard.Begin();

}

Метод PrepareStoryboard () абстрактный, поэтому его нужно переопределить в про­изводном классе, создающем необходимый объект анимации.

protected abstract void PrepareStoryboard();

Обработчик события TransitionCompleted () реагирует на завершение анимации, удаляя старую страницу.

private void TransitionCompleted(object sender, EventArgs e) {

II Удаление старой страницы

Grid grid = (Grid)Application.Current.RootVisual; grid.Children.Remove(oldPage);

) }

Этот же обработчик при необходимости можно использовать для очистки прило­жения. Однако в данном примере анимация обрабатывает старую страницу, которая после перехода отбрасывается, поэтому очистка не нужна.

Реализация метода занавеса

Для реализации перехода на другую страницу методом занавеса необходим как минимум один производный класс, создающий объекты анимации. В данном разделе рассматривается класс WipeTransition, который плавно удаляет старую страницу, по­степенно приоткрывая новую.

Эффект занавеса создается путем анимации кисти, в которой используется полу­прозрачная маска OpacityMask. В главе 9 показано, что полупрозрачная маска опре­деляет, какая часть изображения или элемента должна быть видна. В данном примере в маске применяется кисть LinearGradientBrush. Анимация изменяет смещение маски, постепенно делая прозрачным вышележащий элемент (старую страницу) и открывая нижележащее содержимое (новую страницу). Обычно задают движение занавеса слева направо или сверху вниз, однако, используя разные маски, можно создавать более эк­зотические эффекты.

Класс WipeTransition переопределяет метод PrepareStoryboard (), главная задача которого — создать маску и добавить ее на старую страницу (вышележащий элемент кон­тейнера Grid). В маске используется градиент с двумя элементами GradientStop. Цвет первого элемента — Black (изображение видно полностью), а второго — Transparent (изображение полностью прозрачное). Сначала оба смещения GradientStop позицио­нированы слева на странице. Элемент с цветом Black объявлен последним, поэтому его приоритет выше и сначала изображение непрозрачное.

public class WipeTransition : PageTransitionBase {

protected override void PrepareStoryboard () {

// Создание маски

LinearGradientBrush mask = new LinearGradientBrush (); mask.StartPoint = new Point (0,0); mask.EndPoint = new Point (1,0);

GradientStop transparentStop = new GradientStopl);

transparentStop.Color = Colors.Transparent;

transparentStop.Offset = 0;

mask.GradientStops.Add(transparentStop);

GradientStop visibleStop = new GradientStop ();

visibleStop.Color = Colors.Black;

visibleStop.Offset = 0;

mask.GradientStops.Add(visibleStop);

oldPage. OpacityMask = mask;

Далее необходимо анимировать смещения кисти LinearGradientBrush. В данном примере оба смещения перемещаются слева направо, открывая нижележащее изобра­жение. Чтобы край занавеса был размытым, смещения находятся не в одинаковых по­зициях. Смещение Transparent следует за смещением Black с интервалом 0 .2 секунды.

// Создание анимаций для маски DoubleAnimation visibleStopAnimation =

new DoubleAnimation (); Storyboard.SetTarget(visibleStopAnimation, visibleStop); Storyboard.SetTargetProperty(visibleStopAnimation,

new PropertyPath("Offset")); visibleStopAnimation.Duration = TimeSpan.FromSeconds(1.2); visibleStopAnimation.From = 0;

visibleStopAnimation.То = 1.2;

DoubleAnimation transparentStopAnimation =

new DoubleAnimation(); Storyboard.SetTarget(transparentStopAnimation,

transparentStop); Storyboard.SetTargetProperty(transparentStopAnimation,

new PropertyPath("Offset")); transparentStopAnimation.BeginTime =

TimeSpan.FromSeconds(0.2); transparentStopAnimation.From = 0; transparentStopAnimation.To = 1;

transparentStopAnimation.Duration = TimeSpan.FromSeconds(1);

Смещение Black доходит до точки 1.2, а не 1, т.е. немного дальше правого края изображения. Это необходимо для того, чтобы оба смещения двигались с одинаковой скоростью (пройденное расстояние должно быть пропорционально продолжительности анимации).

Обе анимации нужно добавить в раскадровку. Запускать раскадровку не нужно, по­тому что это происходит в базовом классе PageTransitionBase после возврата метода

PrepareStoryboard().

// Добавление анимации в раскадровку

storyboard.Children.Add(transparentStopAnimation);

storyboard;Children.Add(visibleStopAnimation); }

}

Для перехода к другой странице используется следующий код.

WipeTransition transition = new WipeTransition() ; transition.Navigate(new Page2 ());

Как и в случае примера BombDropper, есть много способов улучшить данную техно­логию.

•       Добавление свойств перехода. Класс WipeTransition можно расширить, доба­вив дополнительные возможности. Например, можно сконфигурировать направ­ление движения занавеса, изменить продолжительность движения и т.д.

•       Создание других способов перехода. Для этого нужно создать класс, произво­дный от PageTransitionBase, и переопределить метод PrepareStoryboard ().

•       Рефакторинг кода PageTransitionBase. Рассматриваемый пример максималь­но упрощен. Структуру приложения можно усовершенствовать путем извлечения кода, который добавляет и удаляет страницы, и размещения его в пользователь­ском классе приложения. Такая операция открывает дополнительные возможно­сти, позволяя использовать разные контейнеры. Например, можно анимировать переход на одной панели, а не на всей странице. Кроме того, такая операция по­зволит добавлять службы приложения. Например, удаленную страницу можно хранить в кеше в активном состоянии (см. главу 7), а затем восстановить ее с те­кущими значениями элементов.

Прекрасный пример использования анимированных переходов можно найти в Интернете по такому адресу:

www.flawlesscode.com/post/2008/03/Silverlight-2-Navigating- Between-Xaml-Pages.aspx.

Для создания еще более впечатляющих эффектов примените коллекцию пользова­тельских классов раскрашивания и переходов, приведенную в бесплатной библиотеке WPF Shader Effects Library (www. codeplex. com/wpf fx).

Источник: Мак-Дональд, Мэтью. Silverlight 3 с примерами на С# для профессионалов. : Пер. с англ. —- М. : ООО «И.Д. Вильяме», 2010. — 656 с. : ил. — Парал. тит. англ.

По теме:

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