CustomPainter画音乐跳动动画

248 阅读1分钟

先放张效果图

music.gif

练习使用CustomPainter和Animation,对初学者也许有点帮助。 直接上代码:

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

//paint区域大小
double sizeWidth = 20; 

class Music_lvdong extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _state();
  }
}

class _state extends State<Music_lvdong> with SingleTickerProviderStateMixin {
  AnimationController spread;
  List _list;  //存放随机数
  @override
  void initState() {
    super.initState();
    var rng = new Random();
    _list = [
      rng.nextDouble(),
      rng.nextDouble(),
      rng.nextDouble(),
      rng.nextDouble(),
      rng.nextDouble(),
    ];
    spread =
        AnimationController(vsync: this, duration: Duration(milliseconds: 300));
    spread.addStatusListener((status) {
      //动画结束后反转
      if (status == AnimationStatus.completed) {
        spread.reverse();
      }
      //反转后重置随机值,继续播放
      if (status == AnimationStatus.dismissed) {
        var rng = new Random();
        _list = [
          rng.nextDouble(),
          rng.nextDouble(),
          rng.nextDouble(),
          rng.nextDouble(),
          rng.nextDouble(),
        ];
        print(_list);
        setState(() {});
        spread.forward();
      }
    });
    spread.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text(""),
        elevation: 0,
      ),
      body: Center(
        child: CustomPaint(
          size: Size(sizeWidth, sizeWidth),
          painter: ShapePainter(spread, _list),
        ),
      ),
    );
  }
}

class ShapePainter extends CustomPainter {
  final Animation<double> spread;
  final List _list;

  ShapePainter(this.spread, this._list) : super(repaint: spread);

  @override
  void paint(Canvas canvas, Size size) {

    Paint paint = Paint()
      ..color = Colors.green
      ..strokeWidth = 3;
    var shader = LinearGradient(
            begin: Alignment.bottomLeft,
            end: Alignment.topRight,
            tileMode: TileMode.clamp,
            colors: [Colors.red, Colors.amber])
        .createShader(Rect.fromLTRB(0, 0, 30, 30));
    paint.shader = shader;

    //平移到左下角
    canvas.translate(0, size.height);

    //画5根线
    canvas.drawLine(
        Offset(0, 0), Offset(0, -sizeWidth * (spread.value) * _list[0]), paint);
    canvas.drawLine(
        Offset(5, 0),
        Offset(5, -sizeWidth * (spread.value) * _list[1] * _list[3] - 4),
        paint);
    canvas.drawLine(Offset(10, 0),
        Offset(10, -sizeWidth * (spread.value) * _list[2] - 1), paint);
    canvas.drawLine(
        Offset(15, 0),
        Offset(15, -sizeWidth * (spread.value) * _list[3] * _list[1] - 2),
        paint);
    canvas.drawLine(Offset(20, 0),
        Offset(20, -sizeWidth * (spread.value) * _list[4] - 3), paint);
  }

  @override
  bool shouldRepaint(covariant ShapePainter oldDelegate) {
    return oldDelegate.spread != spread;
  }
}