更新日: 2010 年 1 月 22 日

C# の内容はこちらに掲載しています。10 行でズバリ !! アニメーションの作成 (C#)

このコンテンツのポイント

  • プロパティ値の変化による WPF のアニメーション
  • ストーリーボードを使ったアニメーションの定義
  • イベント トリガによるアニメーションの制御

今回紹介するコード

Visual Basic
<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="370" Width="450">

    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">

            <!-- 背景色のアニメーション -->
            <BeginStoryboard>
                <Storyboard AutoReverse="True" RepeatBehavior="Forever">
                    <ColorAnimation From="Green" To="Yellow" Duration="0:0:2"
                                    Storyboard.TargetName="myBrush"
                                    Storyboard.TargetProperty="Color" />
                </Storyboard>
            </BeginStoryboard>

        </EventTrigger>
    </Window.Triggers>

    <Grid>
        <Canvas Width="400" Height="300">

            <!-- 背景色の設定 -->
            <Canvas.Background>
                <SolidColorBrush x:Name="myBrush" Color="Green" />
            </Canvas.Background>

            <Canvas.Triggers>
                <EventTrigger RoutedEvent="Canvas.Loaded">

                    <!-- ボールのアニメーション -->
                    <BeginStoryboard x:Name="myBoard">
                        <Storyboard>
                            <!-- 縦方向の移動 -->
                            <DoubleAnimation From="0" To="260" Duration="0:0:0.7"
                                             Storyboard.TargetName="myEllipse"
                                             Storyboard.TargetProperty="(Canvas.Top)"
                                             AutoReverse="True" RepeatBehavior="Forever" />

                            <!-- 横方向の移動 -->
                            <DoubleAnimation From="0" To="360" Duration="0:0:1"
                                             Storyboard.TargetName="myEllipse"
                                             Storyboard.TargetProperty="(Canvas.Left)"
                                             AutoReverse="True" RepeatBehavior="Forever" />
                        </Storyboard>
                    </BeginStoryboard>

                </EventTrigger>
            </Canvas.Triggers>

            <!-- 赤いボールの記述 -->
            <Ellipse x:Name="myEllipse" Fill="Red"
                     Width="40" Height="40"
                     Canvas.Left="0" Canvas.Top="0" />
        </Canvas>
    </Grid>
</Window>
 

目次

  1. はじめに
  2. サンプル アプリケーションの画面
  3. WPF アプリケーションの開発準備
  4. ストーリーボードによるアニメーションの定義
  5. イベント トリガによるストーリーボードの開始
  6. 背景色のアニメーション
  7. ボールのアニメーション
  8. トリガ アクションの追加

1. はじめに

ここでは WPF (Windows Presentation Foundation) アプリケーションでアニメーションを実装する基本的な方法について解説します。一般にアニメーションというと、複数の少しずつ異なる絵を連続して表示することにより動きを表現しますが、WPF のアニメーションでは、コントロールなどの画面要素の特定のプロパティの値を、開始値から終了値まで、指定された時間で変化させることにより動きを表現します。

以下では Visual Studio 2008 SP1 (.NET Framework の バージョンは 3.5 SP1) を用いて、サンプル アプリケーションを作成しながら、アニメーションの記述方法を解説していきます。なお Visual Studio 2008 でも WPF アプリケーションのデザインや実装は可能ですが、SP1 ではデザイナーの強化や、WPF アプリケーションのパフォーマンス向上などの改善が行われています。

ページのトップへ


2. サンプル アプリケーションの画面

ここで作成するサンプル アプリケーションは、以下のような画面のアプリケーションです。この画像だけでは分かりませんが、背景色は黄色から緑色への変化を繰り返し、同時に赤いボールがウィンドウ内をはね回ります (下図の赤い矢印はボールの動きを説明するために後から追加したものです)。

図 1 サンプル アプリケーションの実行画面

このアプリケーションでは、色の値を変化させるアニメーションと、ボールの座標の値を変化させるアニメーションの 2 種類のアニメーションを使用しています。

以降では、開発の準備、背景色のアニメーションの作成、ボールのアニメーションの作成の順に解説していきます。

ページのトップへ


3. WPF アプリケーションの開発準備

まず Visual Studio を起動して、[ファイル] メニューの [新規作成] から [プロジェクト] をクリックし、[新しいプロジェクト] ダイアログを開きます。そして [プロジェクトの種類] で [Windows] を、[テンプレート] では [WPF アプリケーション] を選択します。[プロジェクト名] は任意の名前を指定でき、ここでは「WpfAnimation」としています。

図 2 [新しいプロジェクト] ダイアログで WPF アプリケーションのプロジェクトを新規作成

[OK] ボタンをクリックすると、次の画面のように WPF デザイナーが開きます。

図 3 プロジェクト新規作成後に開く WPF デザイナーの画面

以下では、画面下部分に表示されている XAML コードを編集していきます (ちなみに今回は VB のコードは一切記述しません)。

最初に、ボールが動き回る領域として、Canvas パネル (<Canvas> 要素) を配置し、背景色を緑色のブラシで塗ります。ブラシには「myBrush」という名前を付けています。後でこのブラシの色をアニメーションにより変化させます。

 

Visual Basic
<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="370" Width="450">

    <Grid>
        <Canvas Width="400" Height="300">

            <!-- 背景色の設定 -->
            <Canvas.Background>
                <SolidColorBrush x:Name="myBrush" Color="Green" />
            </Canvas.Background>

        </Canvas>
    </Grid>
</Window>
 

併せて、ウィンドウも適当なサイズに設定しています。

ページのトップへ


4. ストーリーボードによるアニメーションの定義

それではアニメーションを記述していきましょう。

特定個所の色を変化させたい場合には、<ColorAnimation> 要素を使用します (ほかにどのような種類のアニメーションが利用可能かは、System.Windows.Media.Animation 名前空間のクラス一覧 を見てください。DoubleAnimation や PointAnimation などの、クラス名が「Animation」で終わるものが利用可能なアニメーションです)。 

色を変化させるアニメーション自体の定義はシンプルで、次のようになります。

Visual Basic
<ColorAnimation From="Green" To="Yellow" Duration="0:0:2" />
 

これは Duration="0:0:2" で設定している 2 秒の間に、From="Green" と To="Yellow" の設定により、色を緑色から黄色に変化させるアニメーションの定義です。

このようにして定義したアニメーションは、次のようにして <Storyboard> 要素により「ストーリーボード」に並べて使用します。ここでは 1 つだけですが、ストーリーボードには複数のアニメーションを記述でき、複数の動きを組み合わせることができます。

 

<Storyboard AutoReverse="True" RepeatBehavior="Forever" />

   <ColorAnimation From="Green" To="Yellow" Duration="0:0:2"

                   Storyboard.TargetName="myBrush"

                   Storyboard.TargetProperty="Color" />

</Storyboard>

<Storyboard> 要素には 2 つの属性を指定していますが、AutoReverse="True" の設定により、緑色から黄色に変化した色は、黄色から緑色に戻ります。また、RepeatBehavior="Forever" の設定により、そのアニメーションが永久に続きます。

またここでは、Storyboard.TargetName 属性と、Storyboard.TargetProperty 属性により、アニメーションを適用するコントロールとプロパティの指定が必要となります。このコードでは、キャンバスの背景色に使用するブラシの Color 属性 (Color プロパティ) がターゲットとなります (ブラシに名前を付けておいたのは、ここで指定するためです)。

ページのトップへ


5. イベント トリガによるストーリーボードの開始

続いては、いま定義したストーリーボードを操作して、アニメーションを開始します。

アニメーションを開始するにはいくつか方法がありますが、アプリケーション開始時からアニメーションを開始させるような場合には、イベント トリガを使用し、そのトリガ アクションとして、<BeginStoryboard> 要素を記述するのが一般的です。

アプリケーションの <Window> 要素に対してこれを記述する場合には、イベント トリガの記述は次のようになります。

Visual Basic
<Window.Triggers>
    <EventTrigger RoutedEvent="Window.Loaded">

        <BeginStoryboard>
            (ストーリーボードの定義)
        </BeginStoryboard>

    </EventTrigger>
</Window.Triggers>
 

このイベント トリガの定義では、<Window> 要素がロードされたとき (つまりはアプリケーション開始時) に、指定したストーリーボードを開始します。

ページのトップへ


6. 背景色のアニメーション

以上のコードを組み合わせると、コード全体は次のようになります。

Visual Basic
<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="370" Width="450">

    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">

            <!-- 背景色のアニメーション -->
            <BeginStoryboard>
                <Storyboard AutoReverse="True" RepeatBehavior="Forever">
                    <ColorAnimation From="Green" To="Yellow" Duration="0:0:2"
                                    Storyboard.TargetName="myBrush"
                                    Storyboard.TargetProperty="Color" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>

    <Grid>
        <Canvas Width="400" Height="300">

            <!-- 背景色の設定 -->
            <Canvas.Background>
                <SolidColorBrush x:Name="myBrush" Color="Green" />
            </Canvas.Background>

        </Canvas>
    </Grid>
</Window>
 

Visual Studio で [F5] キーを押して実行してください。うまくキャンバスの背景色が変わり続けているでしょうか。

ページのトップへ


7. ボールのアニメーション

続いては、ここまでに説明した内容の応用として、キャンバス上にボール (赤い円) を描き、その位置をアニメーションさせてみます。

ボールを描くには、<Ellipse> 要素を記述します。次の定義では、直径 40 ピクセルの円を Canvas パネル内の左上隅に描きます。

Visual Basic
<!-- 赤いボールの記述 -->
<Ellipse x:Name="myEllipse" Fill="Red"
         Width="40" Height="40"
         Canvas.Left="0" Canvas.Top="0" />
 

ボールの位置をアニメーションにより変化させるには、Canvas.Left 属性と Canvas.Top 属性の値を変化させるわけですが、これらの属性値は Double 型ですので、アニメーションは <DoubleAnimation> 要素を用いて定義します。

この定義は次のようになります。横位置をキャンバスの左端から右端まで、縦位置を上端から下端まで変化させる 2 つのアニメーションを同時に記述しています。なお、それぞれの To 属性の値は、キャンバスのサイズである 300 × 400 から、ボールのサイズ (40 ピクセル) を引いた値です。

Visual Basic
<Storyboard>
    <!-- 縦方向の移動 -->
    <DoubleAnimation From="0" To="260" Duration="0:0:0.7"
                     Storyboard.TargetName="myEllipse"
                     Storyboard.TargetProperty="(Canvas.Top)"
                     AutoReverse="True" RepeatBehavior="Forever" />

    <!-- 横方向の移動 -->
    <DoubleAnimation From="0" To="360" Duration="0:0:1"
                     Storyboard.TargetName="myEllipse"
                     Storyboard.TargetProperty="(Canvas.Left)"
                     AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
 

Canvas パネルのサイズの縦横比は 4 : 3 ですが、Duration の値も 4 : 3 にしてしまうと、対角線上を行き来するだけのものになってしまうため、若干ずらしている点がポイントといえます。また、それぞれの DoubleAnimation を独立して繰り返すために、AutoReverse 属性と RepeatBehavior 属性は、それぞれの <DoubleAnimation> 要素に記述する必要があります。

なお、Storyboard.TargetProperty 属性の指定では、<Ellipse> 要素のプロパティではなく、Canvas パネルの添付プロパティを指定するので、Canvas.Top や Canvas.Left をカッコで囲む必要があります。これは PropertyPath 構文と呼ばれるものですが、これについての詳細は「PropertyPath の XMAL 構文」をご覧ください。

上記のストーリーボードを、Canvas パネルがロードされたときに開始するようにしたコードは次のようになります。

Visual Basic
<Window x:Class="WpfAnimation.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="370" Width="450">

    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">

            <!-- 背景色のアニメーション -->
            <BeginStoryboard>
                <Storyboard AutoReverse="True" RepeatBehavior="Forever">
                    <ColorAnimation From="Green" To="Yellow" Duration="0:0:2"
                                    Storyboard.TargetName="myBrush"
                                    Storyboard.TargetProperty="Color" />
                </Storyboard>
            </BeginStoryboard>

        </EventTrigger>
    </Window.Triggers>

    <Grid>
        <Canvas Width="400" Height="300">

            <!-- 背景色の設定 -->
            <Canvas.Background>
                <SolidColorBrush x:Name="myBrush" Color="Green" />
            </Canvas.Background>

            <Canvas.Triggers>
                <EventTrigger RoutedEvent="Canvas.Loaded">

                    <!-- ボールのアニメーション -->
                    <BeginStoryboard x:Name="myBoard">
                        <Storyboard>
                            <!-- 縦方向の移動 -->
                            <DoubleAnimation From="0" To="260" Duration="0:0:0.7"
                                             Storyboard.TargetName="myEllipse"
                                             Storyboard.TargetProperty="(Canvas.Top)"
                                             AutoReverse="True" RepeatBehavior="Forever" />

                            <!-- 横方向の移動 -->
                            <DoubleAnimation From="0" To="360" Duration="0:0:1"
                                             Storyboard.TargetName="myEllipse"
                                             Storyboard.TargetProperty="(Canvas.Left)"
                                             AutoReverse="True" RepeatBehavior="Forever" />
                        </Storyboard>
                    </BeginStoryboard>

                </EventTrigger>
            </Canvas.Triggers>

            <!-- 赤いボールの記述 -->
            <Ellipse x:Name="myEllipse" Fill="Red"
                     Width="40" Height="40"
                     Canvas.Left="0" Canvas.Top="0" />
        </Canvas>
    </Grid>
</Window>
 

それでは Visual Studio で [F5] キーを押して実行してみてください。実際にどのくらいの頻度でボールが描画されるかは、実行している PC 環境によります。当然ながら、高性能な PC ほどアニメーションは滑らかになります。

ページのトップへ


8. トリガ アクションの追加

上記では、BeginStoryboard というトリガ アクションを使用してストーリーボードの開始を指示しましたが、動作中のストーリーボードに対して、一時停止、再開、速度の変更などの制御を行うトリガ アクションも用意されています。

ここでは最後に、Canvas パネル内にマウス カーソルが入ったときにボールの動きを一時停止し、マウス カーソルが Canvas パネルの外側に出たときにボールの動きを再開するような処理を追加してみましょう。この処理は、次のようにして <Canvas.Triggers> 要素にイベント トリガを追加するだけです(コードの太字部分)。

 

           <Canvas.Triggers>

               <EventTrigger RoutedEvent="Canvas.Loaded">

                   <!-- ボールのアニメーション-->

                   <BeginStoryboard x:Name="myBoard">

                      (省略)

                   </BeginStoryboard>

               </EventTrigger>

               <!-- ボールの一時停止 -->

               <EventTrigger RoutedEvent="Mouse.MouseEnter">

                   <PauseStoryboard BeginStoryboardName="myBoard" />

               </EventTrigger>

               <!-- ボールの再開 -->

               <EventTrigger RoutedEvent="Mouse.MouseLeave">

                   <ResumeStoryboard BeginStoryboardName="myBoard" />

               </EventTrigger>

           </Canvas.Triggers>

<PauseStoryboard> 要素や <ResumeStoryboard> 要素の記述時には <BeginStoryboard> 要素を名前で指定する必要がありますので、<BeginStoryboard> 要素の定義時に名前を付けています。

ページのトップへ


Code Recipe Windows デベロッパー センター

ページのトップへ