WPFのアニメーションとは、TVアニメみたいな奴じゃなくて指定した時間の間でプロパティの値を変更していくとかいうものをさすらしい。
とりあえず色々実験するための下地のアプリケーションを作ってみよう。
WpfAnimeStudyという名前のプロジェクトを新規作成して、Window1.xamlを下のような感じにしてみた。
<Window x:Class="WpfAnimeStudy.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Canvas>
<Rectangle Name="animationTarget"
Canvas.Top="10"
Canvas.Left="10"
Width="100"
Height="100"
Fill="Aqua" />
<Button Canvas.Bottom="10" Canvas.Left="10">きっかけ!</Button>
</Canvas>
</Window>
この時点では、まだ何も仕込んでないので下のような水色の四角形とボタンが表示されるだけになってる。
この四角形をアニメーションを使って色々いじくってみようと思う。とりあえず巨大化させるところからだよね。
アニメーションのためのクラスは、<型名>Animationという風にクラス名が統一されている。サイズ指定のためのプロパティのWidthやHeightはDouble型なので、もれなくDoubleAnimationというクラスを使うことになる。
<型名>Animationという名前のクラスにはFromプロパティとToプロパティが定義されている。Fromにアニメーション開始時の値、Toにアニメーション終了時の値を指定することができる。
UIElementクラスには、アニメーションを開始するためのメソッドBeginAnimation(DependencyProperty, AnimationTimeline)というメソッドが用意されている。第一引数にアニメーションさせるプロパティを指定する。第二引数に、アニメーションを指定する。
ということで、10から200にアニメーションさせるDoubleAnimationを作ってRectangleの横幅をずずずぃ~~っと変更させるコードを書いてみた。
using System.Windows;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace WpfAnimeStudy
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// Double型で10から200までアニメーションさせる
var animation = new DoubleAnimation
{
From = 10,
To = 200
};
// そぉぃ
animationTarget.BeginAnimation(Rectangle.WidthProperty, animation);
}
}
}
実行すると...
クリック!
静止画じゃ非常にわかりにくいけど、水色の四角形が1秒間かけて幅10から200へ広がっている。この1秒というのも任意の値を指定できるようになっている。Durationというプロパティがそれだ。Durationプロパティは、Durationという型で定義されているが、暗黙の型変換でも定義されているのだろう。TimeSpanを指定できるようになっている。とりあえず、10秒かけてアニメーションするようにコードを変更してみた。
private void Button_Click(object sender, RoutedEventArgs e)
{
// Double型で10から200までアニメーションさせる
var animation = new DoubleAnimation
{
From = 10,
To = 200,
// 10秒間かけてアニメーションしてね!
Duration = TimeSpan.FromMilliseconds(10000)
};
// そぉぃ
animationTarget.BeginAnimation(Rectangle.WidthProperty, animation);
}
実行結果は、じわりじわりと大きくなっていくだけだから、絵では表しにくい…ということで省略だ。
ストーリーボード
ちなみに、1つ1つのアニメーションを順次BeginAnimationしていくとなると複雑なアニメーションを定義するときに呼び出しがめんどくさいことになる。そういうときのために、複数のアニメーションを1つに取りまとめてくれるストーリーボードなるものがある。
ストーリーボードは、ChildrenプロパティにTimelineオブジェクトをいっぱい格納できるようになっている。
そして、添付プロパティを使って、アニメーションに対して、どのプロパティがターゲットかを教えてあげることができるようになってる。ということで、早速これを使ってWidthとHeightを同時に変化させるアニメーションを定義してみようと思う。
private void Button_Click(object sender, RoutedEventArgs e)
{
var storyboard = new Storyboard();
// 横幅!
{
// Double型で10から200までアニメーションさせる
var animation = new DoubleAnimation
{
From = 10,
To = 200,
// 10秒間かけてアニメーションしてね!
Duration = TimeSpan.FromMilliseconds(10000)
};
Storyboard.SetTargetProperty(animation, new PropertyPath("Width"));
storyboard.Children.Add(animation);
}
// 縦幅!
{
// Double型で10から200までアニメーションさせる
var animation = new DoubleAnimation
{
From = 10,
To = 200,
// 10秒間かけてアニメーションしてね!
Duration = TimeSpan.FromMilliseconds(10000)
};
Storyboard.SetTargetProperty(animation, new PropertyPath("Height"));
storyboard.Children.Add(animation);
}
// そぉぃ
animationTarget.BeginStoryboard(storyboard);
}
ストーリーボードを使用すると、アニメーション開始のメソッドがBeginStoryboardになる。まぁ、些細な変更だけど。ということで実行!
この状態からクリックすると…
10秒かけてじわじわと大きくなっていく。これがアニメーションの基本っぽい。
因みに、FromプロパティやToプロパティを省略するとアニメーションの開始時点の値や終了時点の値をプロパティに設定されているデフォルト値に設定できるようになっている。
この例でFromを省略すると幅と高さ100から200へのアニメーションになるっていう寸法だ。ふむふむ。