30 приложений для Windows Phone: Пока горит свеча
Вот втором нашем приложении мы сделаем анимированную свечу. Для анимации нам понадобится шестьдесят отдельных изображений, которые будут сменяться со скоростью 20 кадров в секунду. Картинки были взяты с Wikipedia.
Анимацию можно сделать разными способами. Например, использовать таймер, как это мы делали в предыдущем приложении. Другой метод заключается в использовании раскадровки (storyboard). Мы можем создать раскадровку двуамя методами: через XAML или программно. Для нашего примера мы сделаем анимацию программным способом, а потом покажем способ через XAML.
Настройка интерфейса
Добавим на страницу элемент Image с именем CandleImage и установим следующие свойства.
- Margin: Clear (Сбросим все настройки)
- Horizontal и Vertical Alignment: Stretch
Создание раскадровки
К сожалению, Expression Blend не поддерживет тип DiscreteObjectKeyFrame, который нам нужен для приложения. Поэтому нам придется самостоятельно написать код в XAML или реализовать раскодровку в коде программно.
В событии Loaded создадим новые объекты Storyboard и ObjectAnimationUsingKeyFrames. Для Storyboard установим поведение RepeatBehavior в Forever (постоянная анимация) и укажем для изображения пути ко всем 60 картинкам через свойство Source.
Затем в цикле пройдемся по всем изображениям анимации и создадим из них отдельные кадры, которые буут сменяться каждые 50 миллисекунд и укажем точный путь к картинке для каждого кадра.
Затем добавим раскадровку в ресурсы страницы и запустим аниманию.
public partial class MainPage { public MainPage() { InitializeComponent(); Loaded += OnLoaded; } private void OnLoaded(object sender, RoutedEventArgs e) { var storyboard = new Storyboard {RepeatBehavior = RepeatBehavior.Forever}; var animation = new ObjectAnimationUsingKeyFrames(); Storyboard.SetTarget(animation, CandleImage); Storyboard.SetTargetProperty(animation, new PropertyPath("Source")); storyboard.Children.Add(animation); for(int i = 1; i <= 60; i++) { var keyframe = new DiscreteObjectKeyFrame { KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(50 * i)), Value = String.Format("/Images/candle_{0:D2}.jpg", i) }; animation.KeyFrames.Add(keyframe); } Resources.Add("CandleStoryboard", storyboard); storyboard.Begin(); } }
Если вы хотите построить раскадровку через XAML, то вам придется повторять одни и те же строчки, что довольно утомительно.
<Storyboard x:Key="CandleStoryboardXaml" RepeatBehavior="Forever"> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CandleImage" Storyboard.TargetProperty="Source"> <DiscreteObjectKeyFrame KeyTime="0:0:0.50" Value="/images/candle_01.jpg" /> <DiscreteObjectKeyFrame KeyTime="0:0:0.100" Value="/images/candle_02.jpg" /> <DiscreteObjectKeyFrame KeyTime="0:0:0.150" Value="/images/candle_03.jpg" /> <DiscreteObjectKeyFrame KeyTime="0:0:0.200" Value="/images/candle_04.jpg" /> <DiscreteObjectKeyFrame KeyTime="0:0:0.250" Value="/images/candle_05.jpg" /> ... </ObjectAnimationUsingKeyFrames> </Storyboard>
Код приведен с сокращениями, но программно проще создать такой же эффект. Выбирайте сами.
