在〈隱式動畫 Widget〉中談過,在 Curves 文件,你可以看到各種不同的變化曲線,其中也有標示各曲線大致的效果展示。
這邊留意到曲線的橫軸為 t
,縱軸為 x
,t
是從 0.0 到 1.0,也就是特性起始值與目標值間的差距被標準化為 0.0 到 1.0,而對應的 x
會作為後續插值的依據(根據後續文件中會談到的 Tween
)。
如果 Curves 文件 中內建的曲線都不符合你的需求,而想要自訂曲線,將是根據 t
建立對應的 x
值,方式是繼承 Curve 類別,並重新定義其 transformInternal
方法,例如 Curves.linear
的實現,就僅僅是單純地將傳入的 t
值傳回罷了:
class _Linear extends Curve {
const _Linear._();
@override
double transformInternal(double t) => t;
}
transformInternal
收到的 t
必然是在 0.0 與 1.0 之間,因為 Curve
的 transform
就這麼限制了,super.transform(t)
中會呼叫 transformInternal
:
@immutable
abstract class Curve extends ParametricCurve<double> {
...
@override
double transform(double t) {
if (t == 0.0 || t == 1.0) {
return t;
}
return super.transform(t);
}
...
}
因此若要定義正弦曲線,可以如下:
class SineCurve extends Curve {
double period = 1;
SineCurve({this.period});
@override
double transformInternal(double t) {
return sin(period * 2 * pi * t);
}
}
這個正弦曲線可以定義週期,如果想套用在位移上,為了目標值剛好是在曲線的正峰值(不然最後 t
為 1.0 時會有劇烈變化),可以選擇週期為 1.5,例如:
import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
home: Caterpillar(),
)
);
class Caterpillar extends StatefulWidget {
@override
State<StatefulWidget> createState() => _CaterpillarState();
}
class _CaterpillarState extends State<Caterpillar> {
var forward = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('openhome.cc'),
),
body: Center(
child: AnimatedContainer(
transform: Matrix4.translationValues(forward ? -150: 150, 0, 0),
width: 150,
child: Image.network('https://openhome.cc/Gossip/images/caterpillar.jpg'),
duration: Duration(seconds: 1),
curve: SineCurve(period: 1.25),
)
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() {
forward = !forward;
}), // 註冊 onPressed 處理器
tooltip: forward ? 'forward' : 'back',
child: Icon(forward ? Icons.arrow_forward : Icons.arrow_back),
),
);
}
}
class SineCurve extends Curve {
double period = 1;
SineCurve({this.period});
@override
double transformInternal(double t) {
return sin(period * 2 * pi * t);
}
}
曲線在 t
為 0.0 時,通常 x
也是 0.0,t
為 1.0 時通常 x
也就是 1.0,當然,實際上還是要看你想要什麼效果,來看一下操作的成果: