本节目标

[1] 认识动画器【曲线速率】的作用 [2] 绘制出Flutter内置的所有曲线效果常量 [3] 了解动画器的常用方法 [4] 了解动画器的状态,以及状态变化监听

一、动画速率曲线

动画曲线描述了动画运动过程中的速度变化曲率,比如开始运动很快,然后慢慢变慢。这样可以实现丰富的运动视觉效果。

动画曲线的核心是4个数字,他的本身是一个贝塞尔曲线。起止点固定。也就是说动画曲线在形式上速度表现就是两个控制点。FLUTTER中使用Curve类来表述。

1. 认识的使用

Curve是一个抽象类。它有很多实现子类。最通用的是Cubic。传入4个值。下面来看一下。如何使用CurveTeen来让动画的变化速率更加的具有曲线效果。

Curve --- 抽象类

|--- FlippedCurve 翻转曲线

|--- SawTooth 翻转曲线

|--- Threshold 0~阈值 曲线

案例实现如下效果:红色小球在圈上运动。绿色小球向下运动。通过改变动画的速率曲线,查看效果。我们可以发现,通过添加曲线可以让运动在首尾慢,中间快。

代码实现

class MyApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return MaterialApp(

title: 'Flutter Demo',

debugShowCheckedModeBanner: false,

theme: ThemeData(

primarySwatch: Colors.blue,

),

home: Scaffold(

body: Center(

child: CurveBox(curve: Cubic(1, -0.06, 0.1, 1.2),),

),

));

}

}

class CurveBox extends StatefulWidget {

final Color color;

final Curve curve;

CurveBox({Key? key, this.color = Colors.lightBlue, this.curve = Curves.linear})

: super(key: key);

@override

_CurveBoxState createState() => _CurveBoxState();

}

class _CurveBoxState extends State

with SingleTickerProviderStateMixin {

late AnimationController _controller;

late Animation _angleAnimation;

@override

void initState() {

super.initState();

_controller = AnimationController(

duration: const Duration(seconds: 3),

vsync: this,

);

_angleAnimation = CurveTween(curve: widget.curve).animate(_controller);

_controller.repeat();

}

@override

void dispose() {

_controller.dispose();

super.dispose();

}

@override

Widget build(BuildContext context) {

return CustomPaint(

size: Size(100, 100),

painter: CurveBoxPainter(_controller, _angleAnimation), // 背景

);

}

}

class CurveBoxPainter extends CustomPainter {

final Animation repaint; //

Animation angleAnimation;

Paint _paint = Paint();

CurveBoxPainter(this.repaint, this.angleAnimation) : super(repaint: repaint) {}

@override

void paint(Canvas canvas, Size size) {

canvas.clipRect(Offset.zero & size);

canvas.translate(size.width / 2, size.height / 2);

_drawRing(canvas, size);

_drawRedCircle(canvas, size);

_drawGreenCircle(canvas, size);

}

//绘制环

void _drawRing(Canvas canvas, Size size) {

final double strokeWidth = 5;

_paint

..color = Colors.blue

..style = PaintingStyle.stroke

..strokeWidth = strokeWidth;

canvas.drawCircle(Offset.zero, size.width / 2 - strokeWidth, _paint);

}

// 绘制红球

void _drawRedCircle(Canvas canvas, Size size) {

canvas.save();

canvas.rotate(angleAnimation.value * 2 * pi);

_paint

..color = Colors.red

..style = PaintingStyle.fill;

canvas.drawCircle(

Offset.zero.translate(0, -(size.width / 2 - 5)), 5, _paint);

canvas.restore();

}

// 绘制绿球

void _drawGreenCircle(Canvas canvas, Size size) {

canvas.save();

canvas.translate(0,angleAnimation.value * (size.height-10));

_paint

..color = Colors.green

..style = PaintingStyle.fill;

canvas.drawCircle(

Offset.zero.translate(0, -(size.width / 2 - 5)), 5, _paint);

canvas.restore();

}

@override

bool shouldRepaint(covariant CurveBoxPainter oldDelegate) =>

oldDelegate.repaint != repaint;

}

2. Flutter所有内置的曲线效果

当我们将曲线效果颜色封装成一个组件之后,就可以非常轻松的实现下面的效果。这就是Flutter的魅力。一共41个曲线效果。

void main() {

// 确定初始化

WidgetsFlutterBinding.ensureInitialized();

//横屏

SystemChrome.setPreferredOrientations(

[DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);

//全屏显示

SystemChrome.setEnabledSystemUIOverlays([]);

runApp(MyApp());

}

class MyApp extends StatelessWidget {

final curvesMap = {

"linear": Curves.linear,

"decelerate": Curves.decelerate,

"fastLinearToSlowEaseIn": Curves.fastLinearToSlowEaseIn,

"ease": Curves.ease,

"easeIn": Curves.easeIn,

"easeInToLinear": Curves.easeInToLinear,

"easeInSine": Curves.easeInSine,

"easeInQuad": Curves.easeInCubic,

"easeInCubic": Curves.easeInCubic,

"easeInQuart": Curves.easeInQuart,

"easeInQuint": Curves.easeInQuint,

"easeInExpo": Curves.easeInExpo,

"easeInCirc": Curves.easeInCirc,

"easeInBack": Curves.easeInBack,

"easeOut": Curves.easeOut,

"linearToEaseOut": Curves.linearToEaseOut,

"easeOutSine": Curves.easeOutSine,

"easeOutQuad": Curves.easeOutQuad,

"easeOutCubic": Curves.easeOutCubic,

"easeOutQuart": Curves.easeOutQuart,

"easeOutQuint": Curves.easeOutQuint,

"easeOutExpo": Curves.easeOutExpo,

"easeOutCirc": Curves.easeOutCirc,

"easeOutBack": Curves.easeOutBack,

"easeInOut": Curves.easeInOut,

"easeInOutSine": Curves.easeInOutSine,

"easeInOutQuad": Curves.easeInOutQuad,

"easeInOutCubic": Curves.easeInOutCubic,

"easeInOutQuart": Curves.easeInOutQuart,

"easeInOutQuint": Curves.easeInOutQuint,

"easeInOutExpo": Curves.easeInOutExpo,

"easeInOutCirc": Curves.easeInOutCirc,

"easeInOutBack": Curves.easeInOutBack,

"fastOutSlowIn": Curves.fastOutSlowIn,

"slowMiddle": Curves.slowMiddle,

"bounceIn": Curves.bounceIn,

"bounceOut": Curves.bounceOut,

"bounceInOut": Curves.bounceInOut,

"elasticIn": Curves.elasticIn,

"elasticInOut": Curves.elasticInOut,

"elasticOut": Curves.elasticOut,

};

@override

Widget build(BuildContext context) {

return MaterialApp(

title: 'Flutter Demo',

debugShowCheckedModeBanner: false,

theme: ThemeData(

primarySwatch: Colors.blue,

),

home: Scaffold(

body: Center(

child:

Wrap(

runSpacing: 10,

children: curvesMap.keys.map((e) => Column(

mainAxisSize: MainAxisSize.min,

children: [

CurveBox(curve: curvesMap[e]!,),

SizedBox(height: 3,),

Text(e,style: TextStyle(fontSize: 10),)

],

)).toList(),

),

),

));

}

}

class CurveBox extends StatefulWidget {

final Color color;

final Curve curve;

CurveBox({Key? key, this.color = Colors.lightBlue, this.curve = Curves.linear})

: super(key: key);

@override

_CurveBoxState createState() => _CurveBoxState();

}

class _CurveBoxState extends State

with SingleTickerProviderStateMixin {

late AnimationController _controller;

late Animation _angleAnimation;

@override

void initState() {

super.initState();

_controller = AnimationController(

duration: const Duration(seconds: 3),

vsync: this,

);

_angleAnimation = CurveTween(curve: widget.curve).animate(_controller);

_controller.repeat();

}

@override

void dispose() {

_controller.dispose();

super.dispose();

}

@override

Widget build(BuildContext context) {

return CustomPaint(

size: Size(100, 100),

painter: CurveBoxPainter(_controller, _angleAnimation), // 背景

);

}

}

class CurveBoxPainter extends CustomPainter {

final Animation repaint; //

Animation angleAnimation;

Paint _paint = Paint();

CurveBoxPainter(this.repaint, this.angleAnimation) : super(repaint: repaint) {}

@override

void paint(Canvas canvas, Size size) {

canvas.clipRect(Offset.zero & size);

canvas.translate(size.width / 2, size.height / 2);

_drawRing(canvas, size);

_drawRedCircle(canvas, size);

_drawGreenCircle(canvas, size);

}

//绘制环

void _drawRing(Canvas canvas, Size size) {

final double strokeWidth = 5;

_paint

..color = Colors.blue

..style = PaintingStyle.stroke

..strokeWidth = strokeWidth;

canvas.drawCircle(Offset.zero, size.width / 2 - strokeWidth, _paint);

}

// 绘制红球

void _drawRedCircle(Canvas canvas, Size size) {

canvas.save();

canvas.rotate(angleAnimation.value * 2 * pi);

_paint

..color = Colors.red

..style = PaintingStyle.fill;

canvas.drawCircle(

Offset.zero.translate(0, -(size.width / 2 - 5)), 5, _paint);

canvas.restore();

}

// 绘制绿球

void _drawGreenCircle(Canvas canvas, Size size) {

canvas.save();

canvas.translate(0,angleAnimation.value * (size.height-10));

_paint

..color = Colors.green

..style = PaintingStyle.fill;

canvas.drawCircle(

Offset.zero.translate(0, -(size.width / 2 - 5)), 5, _paint);

canvas.restore();

}

@override

bool shouldRepaint(covariant CurveBoxPainter oldDelegate) =>

oldDelegate.repaint != repaint;

}

二、动画器的方法

1.forward和reverse方法

|— forward({double from}) 执行运动直到上界。可指定初始值。(执行完毕就会停止) |— reverse({double from}) 执行运动到下界。可以指定初始值。(执行完毕之后就会停止)

2.repeat重复执行

repeat

|--- double?min,

|--- double? max

|--- bool reverse=false // 是否反转

|--- Duration? period // 周期

3. fling方法

fling也就是猛冲。可以给一个速度。默认为1

4. stop和reset

stop方法是让_ticker停止。这样动画也就停止了。可以传入一个bool值。reset方法也很简单。就是将当前值设置为下界。

void stop({bool canceld=true}){

_simukation=null;

_lastElapsedDuration=null;

_ticker.stop(canceld:canceled)

}

void reset(){

value=lowerBound;

}

参考文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: