コンテンツにスキップ

アニメーションを付ける

画面の一部を、ふわっと出したり点滅させたりするには、AnimationController と FadeTransition で、子の不透明度を時間で変えます。フレームごとに SetState() を呼ぶ必要はありません。この手順を終えると、HMD の中で四角がフェードインとフェードアウトを繰り返します。片道は 1.5 秒です。

この手順で扱うのは、不透明度を変えるアニメーションです。移動や拡大に使える専用のウィジェットは、まだありません(追跡: #219)。目的が移動や拡大の場合は、できないこと・まだ使えないもので、今の範囲を確かめます。

  • StatefulWidget と SetState() で値を変えたことがあること。なければ、最初のオーバーレイを作るに戻る
  • 動かしたい部分が、ウィジェットとして書けていること

手順1: アニメーションを動かす State を作る

Section titled “手順1: アニメーションを動かす State を作る”

アニメーションを動かす State は、State<T> の代わりに TickerProviderState<T> を継承します。TickerProviderState<T> は、フレームごとの時刻の知らせを、アニメーションに渡す役目を持ちます。

public record BlinkBox : StatefulWidget<BlinkBox>
{
public override State<BlinkBox> CreateState() => new BlinkBoxState();
}
public class BlinkBoxState : TickerProviderState<BlinkBox>
{
public override Widget Build(IBuildContext context) => new Align
{
Alignment = Alignment.Center,
Child = new SizedBox
{
Width = 200,
Height = 200,
Child = new ColoredBox { Color = SKColors.MediumSlateBlue },
},
};
}

using には、FloatSoda.Animation、FloatSoda.Elements、FloatSoda.Geometrics、FloatSoda.Widgets、FloatSoda.Widgets.Animation、FloatSoda.Widgets.Layout、FloatSoda.Widgets.Paint、SkiaSharp を足します。

起動のコードで、ウィンドウの Child を new BlinkBox() に置き換えます。

できた? コンパイルが通れば、手順1は完了です。

手順2: AnimationController を作って動かす

Section titled “手順2: AnimationController を作って動かす”

AnimationController は、InitState() で作ります。Vsync には this を、Duration には片道にかける時間を渡します。作ったあとに Forward() を呼ぶと、動き始めます。

private AnimationController? _controller;
public override void InitState()
{
_controller = new AnimationController
{
Vsync = this,
Duration = TimeSpan.FromSeconds(1.5),
};
_controller.Forward();
}

変化の速さを変えたいときは、Curve に Curves.EaseInOut のような値を渡します。次のコードは、InitState() にある _controller を作る部分を置き換えます。

_controller = new AnimationController
{
Vsync = this,
Duration = TimeSpan.FromSeconds(1.5),
Curve = Curves.EaseInOut,
};

AnimationController の解放の条件は、次のとおりです。

  • 作成した AnimationController は、State の Dispose() で解放すること

State の Dispose() に書くと、ウィジェットが画面から外れるときに解放されます。

public override void Dispose()
{
_controller?.Dispose();
base.Dispose();
}

できた? 実行して、例外が出なければ、手順2は完了です。この段階では画面は変わりません。コントローラーが動いているかは、手順3のフェードインで確かめます。

できなかったら

Vsync や Duration を書き忘れると、コンパイルが通りません。どちらも必須です。例外が出るときは、エラーを読んで直すで原因を切り分けます。

手順3: FadeTransition で子に反映する

Section titled “手順3: FadeTransition で子に反映する”

動かしたい部分を FadeTransition で包み、Opacity にコントローラーを渡します。FadeTransition は、SetState() なしで、描画だけを更新します。

public override Widget Build(IBuildContext context) => new FadeTransition
{
Opacity = _controller!,
Child = new Align
{
Alignment = Alignment.Center,
Child = new SizedBox
{
Width = 200,
Height = 200,
Child = new ColoredBox { Color = SKColors.MediumSlateBlue },
},
},
};

不透明度を変えない固定値だけでよい場合は、Opacity ウィジェットを使います。

できた? HMD の中で、四角が1.5秒かけてフェードインすれば、手順3は完了です。フェードインのあとは、そのまま止まります。

往復させるには、コントローラーの StatusChanged で、終わりに着いたら戻し、始めに戻ったら進め直します。Completed なら Reverse()、Dismissed なら Forward() を呼びます。

次のコードは、手順2の InitState() にある _controller.Forward(); の1行を置き換えます。

_controller.StatusChanged += status =>
{
switch (status)
{
case AnimationStatus.Completed:
_controller.Reverse();
break;
case AnimationStatus.Dismissed:
_controller.Forward();
break;
}
};
_controller.Forward();

StatusChanged の購読は、Forward() を呼ぶ前に書きます。書き終えた InitState() と Dispose() は、サンプルの PulseWidget.cs と同じ形です。

できた? フェードインとフェードアウトが、止まらずに続けば、手順4は完了です。

HMD で、次の2点を見ます。

  • 四角が、薄くなったり濃くなったりを、繰り返している
  • しばらく見ていても、途中で止まらない

HMD を被らずに確かめたいときは、HMD を被らずに確かめるに進みます。作った部品を押せるようにするには、ボタンやトグルを組み立てるに進みます。

動かない、または途中で止まるときは、症状に合うページに進みます。画面が反応しない場合は反応しないときに切り分ける、動作が重い場合は負荷を抑えるです。