アニメーションの組み合わせ
これまでのアニメーション処理は、常にStoryboardオブジェクトに単一のTimelineを含ませるだけでした。しかし、複雑なアニメーションの実現には、より単純なTimelineを組み合わせる必要があります。アニメーションの組み合わせは難しいものではありません。複数のTimelineオブジェクトをStoryboardに登録すればよいのです。
<Rectangle xmlns="http://schemas.microsoft.com/client/2007" Width="0" Height="100" Fill="Black" Name="rect" > <Rectangle.Triggers> <EventTrigger RoutedEvent="Rectangle.Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="Width" To="400" Duration="0:0:1" AutoReverse="true" RepeatBehavior="Forever" /> <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="Opacity" To="0.1" Duration="0:0:4" AutoReverse="true" RepeatBehavior="Forever" /> </Storyboard> </BeginStoryboard> </EventTrigger> </Rectangle.Triggers> </Rectangle>
Sample09のXAMLコードはStoryboard要素内に2つのDoubleAnimation子要素を指定しています。このStoryboardオブジェクトが実行されると、子要素に指定したすべてのTimelineが同時に起動します。Sample09の場合、RectangleのWidthプロパティとOpacityプロパティを対象に同時にアニメーションするため、長方形の幅が伸縮しながら、透明度も変化します。
Storyboard内の個々のTimelineの起動のタイミングを調整することも可能です。デフォルトでは、すべての子Timelineが同時に実行されますが、TimelineオブジェクトのBeginTimeプロパティを変更することで、起動時間を設定できます。
<object BeginTime="TimeSpan" .../>
BeginTimeに設定するTimespanオブジェクトは、時間間隔を表すための値でDurationに設定した時間間隔と同じようにh:m:s形式で指定できます。Durationオブジェクトとの違いはAutomaticやForeverといった文字列を持たない点です。
例えば、Storyboard内のTimelineがBeginTimeプロパティに0:0:5を設定している場合、そのTimelineはStoryboardの起動から5秒経過した時点で開始します。複数のTimelineをStoryboard内に保有させている場合、一部のアニメーションの開始を遅らせることができます。
<Rectangle xmlns="http://schemas.microsoft.com/client/2007" Width="100" Height="100" Fill="Black" Name="rect" > <Rectangle.Triggers> <EventTrigger RoutedEvent="Rectangle.Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="Width" To="400" Duration="0:0:1" AutoReverse="true" /> <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="Height" To="300" Duration="0:0:1" BeginTime="0:0:2" AutoReverse="true" /> </Storyboard> </BeginStoryboard> </EventTrigger> </Rectangle.Triggers> </Rectangle>
Sample10は、最初に長方形の幅が伸縮し、その後、高さが伸縮するアニメーションを実行します。幅を伸縮させるDoubleAnimationオブジェクトと、高さを伸縮させるDoubleAnimationオブジェクトの2つのTimelineが用意されていますが、このうち高さを伸縮させるDoubleAnimationオブジェクトにはBeginTimeプロパティで2秒後に起動するように指示しています。そのため、最初に幅を伸縮させるDoubleAnimationのみが進行し、このアニメーションが終了する2秒後に高さを伸縮するDoubleAnimationが開始されます。
Storyboardの中のStoryboard
Timelineの抽象的な概念で最も重要なのはStoryboardもまたTimelineオブジェクトであるという点です。よって、StoryboardのChildrenプロパティが管理している子TimelineオブジェクトとしてStoryboardを追加することが可能です。いくつかの異なるTimelineオブジェクトのグループを組み合わせることができるのです。
また、Storyboard内の子Timelineオブジェクトが対象とするオブジェクトやプロパティを、親StoryboardのStoryboard.TargetNameプロパティやStoryboard.TargetPropertyプロパティで共有することも可能です。子TimelineオブジェクトのStoryboard.TargetNameが同じである場合、Storyboardに設定することで共有させることができます。
AutoReverseプロパティやRepeatBehaviorプロパティも、Timelineオブジェクトで宣言されているプロパティなので、Storyboard単位で設定することが可能です。
<Canvas xmlns="http://schemas.microsoft.com/client/2007" > <Ellipse Width="100" Height="100" Fill="Black" Name="ellipse"> <Ellipse.Triggers> <EventTrigger RoutedEvent="Ellipse.Loaded"> <BeginStoryboard> <Storyboard Storyboard.TargetName="ellipse"> <Storyboard AutoReverse="true" > <DoubleAnimation To="280" Duration="0:0:4" Storyboard.TargetProperty="(Canvas.Left)" /> <DoubleAnimation To="180" Duration="0:0:4" Storyboard.TargetProperty="(Canvas.Top)" /> </Storyboard> <Storyboard AutoReverse="true" RepeatBehavior="Forever"> <DoubleAnimation By="20" Duration="0:0:0.2" Storyboard.TargetProperty="Width" /> <DoubleAnimation By="20" BeginTime="0:0:0.1" Duration="0:0:0.2" Storyboard.TargetProperty="Height" /> </Storyboard> </Storyboard> </BeginStoryboard> </EventTrigger> </Ellipse.Triggers> </Ellipse> </Canvas>
Sample11のXAMLコードでStoryboard要素の子要素としてStoryboardを設定しているところに注目してください。StoryboardオブジェクトもまたTimelineを継承するオブジェクトなので、StoryboardオブジェクトのChildrenプロパティが管理している子Timelineとして登録できるのです。
Timelineが対象とするオブジェクトは、トップレベルのStoryboardのStoryboard.TargetNameに設定しています。子TimelineオブジェクトのStoryboard.TargetNameプロパティに適切なオブジェクト名が設定されていない場合、親StoryboardのStoryboard.TargetNameプロパティがデフォルトの値として用いられます。
さらに、AutoReverseプロパティやRepeatBehaviorプロパティの設定もStoryboard単位で行うことができます。いくつかのTimelineを組み合わせたStoryboard単位でアニメーション全体の動きを管理できます。Sample11では、オブジェクトを移動させるStoryboardと、オブジェクトを伸縮させるStoryboardに役割を分離してアニメーションを行います。
最後に
本稿で解説させていただいたSilverlightのアニメーション機能は、XAMLコードをテキストエディタで記述することを想定した学習用のサンプルです。より曲線的な動きをするより複雑なアニメーションを作成することもできますが、複合的な動きをするアニメーションをテキストエディタで書く場合はコード量が膨大になることを覚悟しなければなりません。
プロフェッショナルのデザイナが求めるような実用的なレベルのアニメーション処理となれば、ExpressionBlendのようなデザインツールを使って作成した方が合理的です。しかし、アニメーションを実現する具体的な処理の流れを理解することは、スクリプトを書く場合に重要になります。
また、Webアプリケーションによってデータベースの情報から動的にXAMLを生成し、棒グラフなどをアニメーションさせるといった演出も可能です。いろいろなアイデアを試してみてください。
参考
- MSDN:「Silverlight 1.0 Reference」
