Я решил немного углубиться в Silverlight и сделать с его помощью что-нибудь крутое.
Эта крутая штука, конечно, должна плавно двигаться, переливаться и подергиваться, ведь у нас есть вебванол или где? :).
И здесь мне пришлось иметь дело с по сути хорошей системой анимации в WPF/Silverlight. Покурив MSDN, я быстро начал писать анимацию на XAML. Я написал одно, второе, третье.
А потом мне захотелось убедиться, что они идут в определенной последовательности.
И тогда я понял, что XAML, блин, очень избыточен.
Он идеален для описания интерфейсов: сразу понятно, что к чему относится и необходимость в визуальном редакторе отпадает чуть менее чем полностью.
Но когда пытаешься написать в этом XAML какую-то логику, начинает проявляться вся ее абсурдность.
Погуглив, я был очень удивлён тем, что большинство людей упорно пытаются запихнуть в XAML. все .
Они ругаются, путаются в коде, плачут, но продолжают писать.
Честно говоря, как те мыши с кактусом.
И тогда мне пришла в голову идея аккуратно описать анимации, используя обычный код C#.
Мы, так сказать, олдфаги, рисующие интерфейс прямыми обращениями к WinAPI, неужели нас пугают какие-то анимации? :) В результате получается такой переносимый класс: АнимацияСумка .
Он портативен, поскольку его можно использовать как в WPF, так и в Silverlight без каких-либо модификаций.
Как видно из кода, класс предельно прост. Вот пример использования.public class AnimationItem { public event EventHandler Completed; private void OnStoryboardComplete(object sender, EventArgs e) { if (Completed != null) Completed(this, EventArgs.Empty); } private Storyboard storyboard; public Storyboard Storyboard { get { return storyboard; } set { if (storyboard != null) storyboard.Completed -= OnStoryboardComplete; storyboard = value; storyboard.Completed += OnStoryboardComplete; } } public Action BeginAction { get; set; } public Action EndAction { get; set; } } public class AnimationBag { private readonly Dictionary<string, AnimationItem> storyboards = new Dictionary<string, AnimationItem>(); public void AddAnimation(string name, DependencyObject control, string propertyName, Timeline animation, Action beginAction = null, Action endAction = null) { Storyboard board = new Storyboard(); AnimationItem item = new AnimationItem { BeginAction = beginAction, EndAction = endAction }; Storyboard.SetTarget(animation, control); Storyboard.SetTargetProperty(animation, new PropertyPath(propertyName)); board.Children.Add(animation); if (endAction != null) item.Completed += item_Completed; item.Storyboard = board; storyboards[name] = item; } private void item_Completed(object sender, EventArgs e) { KeyValuePair<string, AnimationItem> pair = storyboards.Where(x => x.Value.Equals(sender)).
FirstOrDefault(); if (pair.Value != null && pair.Value.EndAction != null) pair.Value.EndAction.Invoke(); } public void StartAnimation(string name) { if (!storyboards.ContainsKey(name)) return; if (storyboards[name].
BeginAction != null) storyboards[name].
BeginAction.Invoke(); storyboards[name].
Storyboard.Begin(); } public void StopAnimation(string name) { if (!storyboards.ContainsKey(name)) return; storyboards[name].
Storyboard.Stop(); if (storyboards[name].
EndAction != null) storyboards[name].
EndAction.Invoke(); } public static DoubleAnimation CreateDoubleAnimation(double? to, long durationMs, double? from = null, bool repeat = false) { DoubleAnimation ret = new DoubleAnimation { To = to, From = from, Duration = new Duration(TimeSpan.FromMilliseconds(durationMs)) }; if (repeat) ret.RepeatBehavior = RepeatBehavior.Forever; return ret; } }
КСАМЛ: <Window x:Class="Animation.MainWindow"
xmlns=" http://schemas.microsoft.com/winfx/2006/xaml/presentation "
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml "
Title="Главное окно" Height="350" Width="525">
<Grid>
<Rectangle Height="110" HorizontalAlignment="Left" Margin="55,71,0,0" Name="rectangle1" Stroke="Black" VerticalAlignment="Top" Width="181" Fill="#FF9D3434" />
<Button Content="Кнопка" Height="36" HorizontalAlignment="Left" Margin="286,93,0,0" Name="button1" VerticalAlignment="Top" Width="149" Click="button1_Click" />
</Grid>
</Window>
Код программной части: public partial class MainWindow : Window
{
private readonly AnimationBag animations = new AnimationBag();
public MainWindow()
{
InitializeComponent();
InitAnimations();
}
private void InitAnimations()
{
animations.AddAnimation(
"fadeOut",
rectangle1,
"Opacity",
AnimationBag.CreateDoubleAnimation(0, 500),
null,
() => animations.StartAnimation("fadeIn"));
animations.AddAnimation(
"fadeIn",
rectangle1,
"Opacity",
AnimationBag.CreateDoubleAnimation(1, 500));
}
private void button1_Click(object sender, RoutedEventArgs e)
{
animations.StartAnimation("fadeOut");
}
}
Сам класс представляет собой что-то вроде словаря с ключами — названиями анимаций и значениями — анимацией.
В методе InitAnimations В коллекцию добавляются две анимации с указанием имени, элемента управления, над которым будет выполняться действие, свойства этого элемента управления и самого объекта анимации.
Вы можете создать его вручную или добавить статические помощники к существующему методу для Двойная анимация .
Помимо прочего, метод Добавить анимацию может принять два делегата, которые будут выполняться до и после самой анимации.
Например, здесь после завершения анимации «fadeOut» сразу запускается «fadeIn».
В результате мы имеем достаточно удобный механизм, позволяющий описывать анимацию одной строкой кода вместо килобайт перегруженного XAML. Скачать исходники с тестовыми проектами Теги: #.
NET #wpf #silverlight #XAML #silverlight
-
Промышленные Компьютеры: Не Отставать
19 Oct, 24 -
Яндекс Пробки Для Дальтоников
19 Oct, 24 -
Быстрый Старт Openpnp
19 Oct, 24 -
Музыка Для Программистов
19 Oct, 24 -
Что Будет С Бобрдобр.ру?
19 Oct, 24