Futterステップアップによる動画効果(二)


前の記事では、Futterステップ―アニメーション効果を実現する(一)の最後に、我々は、プロセスの混乱を処理するための概念が必要と述べた。この論文では補間を導入します。これはアニメーションコードを構築するための非常に簡単な概念で、主な役割は対象に向かう方法で代替する前のプロセスの方法です。tweenは、他の値の空間における2つの点の間の経路を記述する値であり、例えば、棒グラフのアニメーション値が0から1まで実行される。
補間はDartでTweenの対象を表します。

abstract class Tween<T> {
 final T begin;
 final T end;

 Tween(this.begin, this.end);

 T lerp(double t);
}
用語lerpはコンピュータグラフィックスの分野から来ており、線形補間(名詞として)と線形内挿(動詞として)の略語である。パラメータtは動画値であり、補間はbegin(tが0の場合)からend(tが1の場合)になるべきです。
FutterSDKのTween類はDartと非常に似ていますが、beginとendをサポートする具体的なクラスです。シングルTweenを使ってコードを整理できます。棒グラフの高さを処理できます。

import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'dart:math';

void main() {
 runApp(new MyApp());
}

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
  return new MaterialApp(
    title: 'Flutter Demo',
    home: new MyHomePage(),
  );
 }
}

class MyHomePage extends StatefulWidget {
 @override
 _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
 final random = new Random();
 int dataSet = 50;
 AnimationController animation;
 Tween<double> tween;

 @override
 void initState() {
  super.initState();
  animation = new AnimationController(
    duration: const Duration(milliseconds: 300),
    vsync: this
  );
  // Tween({T begin, T end }):  tween(  )
  tween = new Tween<double>(begin: 0.0, end: dataSet.toDouble());
  animation.forward();
 }

 @override
 void dispose() {
  animation.dispose();
  super.dispose();
 }

 void changeData() {
  setState(() {
   dataSet = random.nextInt(100);
   tween = new Tween<double>(
    /*
    @override
    T evaluate(
     Animation<double> animation
    )
                  
           0.0 1.0 ,     begin end
     */
    begin: tween.evaluate(animation),
    end: dataSet.toDouble()
   );
   animation.forward(from: 0.0);
  });
 }

 @override
 Widget build(BuildContext context) {
  return new Scaffold(
    body: new Center(
     child: new CustomPaint(
      size: new Size(200.0, 100.0),
      /*
      Animation<T> animate(
       Animation<double> parent
      )
                     ,            
       */
      painter: new BarChartPainter(tween.animate(animation))
     )
    ),
    floatingActionButton: new FloatingActionButton(
      onPressed: changeData,
      child: new Icon(Icons.refresh),
    ),
  );
 }
}

class BarChartPainter extends CustomPainter {
 static const barWidth = 10.0;

 BarChartPainter(Animation<double> animation)
   : animation = animation,
    super(repaint: animation);

 final Animation<double> animation;

 @override
 void paint(Canvas canvas, Size size) {
  final barHeight = animation.value;
  final paint = new Paint()
   ..color = Colors.blue[400]
   ..style = PaintingStyle.fill;
  canvas.drawRect(
    new Rect.fromLTWH(
      size.width-barWidth/2.0,
      size.height-barHeight,
      barWidth,
      barHeight
    ),
    paint
  );
 }

 @override
 bool shouldRepaint(BarChartPainter old) => false;
}
Tweenを使用して、アニメーションの終着点を一つの値に包装します。これは完全にAnimation ControllerとCutomPainterとインターフェースしています。Futterフレームは現在各アニメーションの時間点にCustoomPaintをマークして再構成、再配置、再描画するのではなく、再構成としてマークします。これらは改善を示していますが、補間の概念はこれだけではなく、私たちの考えとコードを組織する構造を提供しています。
コードを返すと、BarタイプとBarTweenアニメ化が必要です。私たちはbarに関するクラスをbar.dartファイルに抽出して、main.dartの同級ディレクトリの下に置く。

import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'dart:ui' show lerpDouble;

class Bar {
 Bar(this.height);
 final double height;

 static Bar lerp(Bar begin, Bar end, double t) {
  return new Bar(lerpDouble(begin.height, end.height, t));
 }
}

class BarTween extends Tween<Bar> {
 BarTween(Bar begin, Bar end) : super(begin: begin, end: end);

 @override
 Bar lerp(double t) => Bar.lerp(begin, end, t);
}

class BarChartPainter extends CustomPainter {
 static const barWidth = 10.0;

 BarChartPainter(Animation<Bar> animation)
   : animation = animation,
    super(repaint: animation);

 final Animation<Bar> animation;

 @override
 void paint(Canvas canvas, Size size) {
  final bar = animation.value;
  final paint = new Paint()
   ..color = Colors.blue[400]
   ..style = PaintingStyle.fill;
  canvas.drawRect(
    new Rect.fromLTWH(
      size.width-barWidth/2.0,
      size.height-bar.height,
      barWidth,
      bar.height
    ),
    paint
  );
 }

 @override
 bool shouldRepaint(BarChartPainter old) => false;
}
FutterSDKの慣例に従ってBarクラスの静的方法BarTween.lerpを定義した。DartSDKにはdoub.lerpがありませんので、dart:uiカバンのlerpDouble関数を使って同じ効果を達成します。
今私たちのアプリケーションは棒グラフで再表示できます。

import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'dart:math';
import 'bar.dart';

void main() {
 runApp(new MyApp());
}

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
  return new MaterialApp(
    title: 'Flutter Demo',
    home: new MyHomePage(),
  );
 }
}

class MyHomePage extends StatefulWidget {
 @override
 _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
 final random = new Random();
 AnimationController animation;
 BarTween tween;

 @override
 void initState() {
  super.initState();
  animation = new AnimationController(
    duration: const Duration(milliseconds: 300),
    vsync: this
  );
  tween = new BarTween(new Bar(0.0), new Bar(50.0));
  animation.forward();
 }

 @override
 void dispose() {
  animation.dispose();
  super.dispose();
 }

 void changeData() {
  setState(() {
   tween = new BarTween(
    tween.evaluate(animation),
    new Bar(100.0 * random.nextDouble()),
   );
   animation.forward(from: 0.0);
  });
 }

 @override
 Widget build(BuildContext context) {
  return new Scaffold(
    body: new Center(
     child: new CustomPaint(
      size: new Size(200.0, 100.0),
      painter: new BarChartPainter(tween.animate(animation))
     )
    ),
    floatingActionButton: new FloatingActionButton(
      onPressed: changeData,
      child: new Icon(Icons.refresh),
    ),
  );
 }
}
次号に続く。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。