Cervelat、アニメーション、古き良きコードビハインド

私は、Silverlightについて少し掘り下げて、何かクールなものにすることにしました。 もちろん、このクールなものは、webdanolを持っているか、どこにあるのか、移動し、溢れ出て、スムーズに痙攣するはずです。 :)。 そして、ここで私は、WPF / Silverlightの優れた、実際のアニメーションシステムに直面しなければなりませんでした。 MSDNを吸った後、私は元気にXAMLでアニメーションを書き始めました。 1つ目、2つ目、3つ目を書きました...そして、それらを特定の順序で実行したかったのです。 そして、感染であるXAMLは非常に冗長であることに気付きました。 インターフェースを記述するのに理想的です。それが何を指しているのかをすぐに確認でき、ビジュアルエディターの必要性は完全に消えます。 しかし、このXAMLで何らかのロジックを記述しようとすると、その不条理がすべて現れ始めます。 Googleを吸った後、ほとんどの人が頑固にすべてをXAMLにプッシュしようとしていることに非常に驚きました。 彼らは誓い、コードに混乱し、泣きますが、書き続けます。 サボテン、チェスロボを持つマウスのように。 そして、通常のC#コードを使用してアニメーションを正確に記述するというアイデアを得ました。 いわば、昔の話ですが、WinAPIを直接呼び出してインターフェイスを作成しましたが、本当に怖いアニメーションはありますか? :)





結果は、そのような移植性のあるクラスAnimationBagです。 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; } }
      
      







コードからわかるように、クラスは非常に単純です。 以下に使用例を示します。



XAML:

 <Window x:Class="Animation.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" 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="Button" 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メソッドでは、名前、アクションが実行されるコントロール、このコントロールのプロパティ、およびアニメーションオブジェクト自体の2つのアニメーションがコレクションに追加されます。 ペンで作成するか、既存のDoubleAnimationのメソッドに静的ヘルパーを追加できます。 とりわけ、 AddAnimationメソッドは、アニメーション自体の前後に実行される2つのデリゲートを受け入れることができます。 たとえば、ここではアニメーション「fadeOut」が完了した後、「fadeIn」がすぐに開始されます。



その結果、キロバイトのオーバーロードされたXAMLではなく、1行のコードでアニメーションを記述することができる、かなり便利なメカニズムが得られました。



テストプロジェクトのソースをダウンロードする



All Articles