返回

深入探讨 Flutter 中的自定义 UI 系列(六):栩栩如生的写轮眼动画

前端

前言

Flutter 的自定义 UI 系列专栏致力于探索 CustomPainter 的强大功能,让开发者能够突破默认 UI 组件的限制,创建独一无二的视觉体验。继上一篇关于水波纹动效的文章后,本篇将展示一个更加复杂的动画:写轮眼的绘制。

写轮眼动画

写轮眼是火影忍者中宇智波一族标志性的能力,其特征是眼睛中带有旋转的花纹。使用 Flutter 的 CustomPainter 和 AnimationController,我们可以轻松地实现写轮眼的动画效果。

步骤 1:创建画布

首先,我们需要创建一个画布,使用 CustomPainter 来绘制写轮眼。创建一个新的类,继承自 CustomPainter:

import 'package:flutter/material.dart';

class SharinganPainter extends CustomPainter {
  // ...
}

步骤 2:绘制写轮眼

在 CustomPainter 的 paint() 方法中,使用 drawPath() 方法绘制写轮眼的形状。写轮眼的图案可以分解成多个圆圈,每个圆圈有不同的半径和颜色。

@override
void paint(Canvas canvas, Size size) {
  // ...
  canvas.drawPath(path, paint);
  // ...
}

步骤 3:添加动画

接下来,使用 AnimationController 来控制写轮眼的旋转。在 initState() 方法中,创建一个 AnimationController:

@override
void initState() {
  super.initState();
  _controller = AnimationController(
    duration: Duration(seconds: 2),
    vsync: this,
  );
}

然后,在 paint() 方法中,使用 AnimationController 的 value 属性来更新写轮眼的旋转角度:

@override
void paint(Canvas canvas, Size size) {
  // ...
  canvas.rotate(_controller.value * 2 * pi);
  // ...
}

步骤 4:启动动画

最后,在 build() 方法中,使用 AnimationController 的 addListener() 方法监听动画的变化,并在动画完成时停止动画:

Widget build(BuildContext context) {
  // ...
  _controller.addListener(() => setState(() {}));
  if (_controller.status == AnimationStatus.completed) {
    _controller.stop();
  }
  // ...
}

代码示例

完整的代码示例如下:

import 'package:flutter/material.dart';

class SharinganPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    double angle = pi / 12;
    double radius = size.width / 4;
    for (int i = 0; i < 3; i++) {
      Paint paint = Paint()
        ..color = Color.fromARGB(255, 240, 200, 0)
        ..style = PaintingStyle.stroke
        ..strokeWidth = 3;
      canvas.drawCircle(Offset(size.width / 2, size.height / 2), radius, paint);
      canvas.rotate(angle);
      radius -= size.width / 16;
    }
    Paint paint = Paint()
      ..color = Colors.black
      ..style = PaintingStyle.fill;
    canvas.drawCircle(Offset(size.width / 2, size.height / 2), size.width / 12, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

class SharinganPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _SharinganPageState();
}

class _SharinganPageState extends State<SharinganPage> with TickerProviderStateMixin {
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 2),
      vsync: this,
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('写轮眼动画'),
      ),
      body: Center(
        child: CustomPaint(
          size: Size(200, 200),
          painter: SharinganPainter(),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (_controller.status == AnimationStatus.completed) {
            _controller.reverse();
          } else {
            _controller.forward();
          }
        },
        child: Icon(Icons.play_arrow),
      ),
    );
  }
}

结语

通过这篇文章,我们深入探讨了 Flutter 中的自定义 UI 系列,并展示了如何使用 CustomPainter 和 AnimationController 实现一个栩栩如生的写轮眼动效。掌握这些技术,开发者可以为应用程序注入活力,创造出令人惊叹的视觉体验。