import 'dart:math'; import 'package:flutter/material.dart'; import 'package:sport/application.dart'; class WavePainter extends CustomPainter { int waveCount; int crestCount; double waveHeight; List waveColors; double circleWidth; Color circleColor; Color circleBackgroundColor; bool showProgressText; TextStyle textStyle; Animation _xAnimation; Animation _yAnimation; set XAnimation(Animation value) { _xAnimation = value; } set YAnimation(Animation value) { _yAnimation = value; } Animation get YAnimation => _yAnimation; Animation get XAnimation => _xAnimation; WavePainter( {this.waveCount = 1, this.crestCount = 2, this.waveHeight, this.waveColors, this.circleColor = Colors.grey, this.circleBackgroundColor = Colors.white, this.circleWidth = 5.0, this.showProgressText = false, this.textStyle = const TextStyle( fontSize: 60.0, color: Colors.blue, fontWeight: FontWeight.bold, shadows: [Shadow(color: Colors.grey, offset: Offset(5.0, 5.0), blurRadius: 5.0)], )}); @override void paint(Canvas canvas, Size size) { double width = size.width; double height = size.height; if (waveHeight == null) { waveHeight = height / 8; height = height + waveHeight; } if (waveColors == null) { waveColors = [Color.fromARGB(100, Colors.blue.red, Colors.blue.green, Colors.blue.blue)]; } Offset center = new Offset(width / 2, height / 2); double xMove = width * XAnimation.value; double yAnimValue = 0.0; if (YAnimation != null) { yAnimValue = YAnimation.value; } double yMove = height * (1.0 - yAnimValue); Offset waveCenter = new Offset(xMove, yMove); var paintCircle = new Paint() ..color = Colors.grey ..style = PaintingStyle.fill ..strokeWidth = circleWidth ..maskFilter = MaskFilter.blur(BlurStyle.inner, 5.0); canvas.drawCircle(center, min(width, height) / 2, paintCircle); List wavePaths = []; for (int index = 0; index < waveCount; index++) { double direction = pow(-1.0, index); Path path = new Path() ..moveTo(waveCenter.dx - width, waveCenter.dy) ..lineTo(waveCenter.dx - width, center.dy + height / 2) ..lineTo(waveCenter.dx + width, center.dy + height / 2) ..lineTo(waveCenter.dx + width, waveCenter.dy); for (int i = 0; i < 2; i++) { for (int j = 0; j < crestCount; j++) { double a = pow(-1.0, j); path ..quadraticBezierTo(waveCenter.dx + width * (1 - i - (1 + 2 * j) / (2 * crestCount)), waveCenter.dy + waveHeight * a * direction, waveCenter.dx + width * (1 - i - (2 + 2 * j) / (2 * crestCount)), waveCenter.dy); } } path..close(); wavePaths.add(path); } var paint = new Paint() ..color = circleBackgroundColor ..style = PaintingStyle.fill ..maskFilter = MaskFilter.blur(BlurStyle.inner, 5.0); canvas.saveLayer(Rect.fromCircle(center: center, radius: min(width, height) / 2), paint); canvas.drawCircle(center, min(width, height) / 2, paint); Rect rect = Rect.fromLTRB(0, 0, size.width, 180); paint ..blendMode = BlendMode.srcATop ..style = PaintingStyle.fill ..strokeWidth = 2.0 ..maskFilter = MaskFilter.blur(BlurStyle.inner, 10.0); for (int i = 0; i < wavePaths.length; i++) { if (waveColors.length >= wavePaths.length) { if (i == 0) { paint.shader = LinearGradient( begin: Alignment.bottomCenter, end: Alignment.topCenter, colors: [Color(0xffFF7700), Color(0x44FFD014)], ).createShader(rect); } else { paint.shader = LinearGradient( begin: Alignment.bottomCenter, end: Alignment.topCenter, colors: [Color(0x99FF7700), Color(0x99FFD014)], ).createShader(rect); } } else { paint.shader = LinearGradient( begin: Alignment.bottomCenter, end: Alignment.topCenter, colors: [Color(0xffFFE600), Color(0xffFF9100)], ).createShader(rect); } canvas.drawPath(wavePaths[i], paint); } // paint.blendMode = BlendMode.srcATop; if (showProgressText) { TextPainter tp = TextPainter(text: TextSpan(text: '${(yAnimValue * 100.0).toStringAsFixed(0)}%', style: textStyle), textDirection: TextDirection.rtl) ..layout(); tp.paint(canvas, Offset(center.dx - tp.width / 2, center.dy - tp.height / 2)); } canvas.restore(); } @override bool shouldRepaint(CustomPainter oldDelegate) { return oldDelegate != this; } } class ProgressManager extends StatefulWidget { final double progress; ProgressManager(this.progress); @override _ProgressManagerState createState() => new _ProgressManagerState() .._factory = WavePainter( waveCount: 2, waveColors: [ Color.fromARGB(100, Colors.pink.red, Colors.pink.green, Colors.pink.blue), Color.fromARGB(150, Colors.pink.red, Colors.pink.green, Colors.pink.blue), ], circleBackgroundColor: Color(0xffffffff), circleWidth: 2.0); } class _ProgressManagerState extends State with TickerProviderStateMixin { AnimationController xController; AnimationController yController; Animation xAnimation; Animation yAnimation; List _progressList = []; double curProgress = 0; WavePainter _factory; set painter(WavePainter factory) { _factory = factory; } setProgress(double progress) { _progressList.add(progress); onProgressChange(); } onProgressChange() { if (yController == null) return; if (_progressList.length > 0) { if (yController != null && yController.isAnimating) { return; } double nextProgress = _progressList[0]; _progressList.removeAt(0); final double begin = curProgress; yController = new AnimationController(vsync: this, duration: Duration(milliseconds: 3000)); yAnimation = AlwaysStoppedAnimation(widget.progress); yAnimation.addListener(_onProgressChange); yAnimation.addStatusListener(_onProgressStatusChange); yController.forward(); } } @override void initState() { super.initState(); xController = new AnimationController(vsync: this, duration: Duration(milliseconds: 3000)); xAnimation = new Tween(begin: 0.0, end: 1.0).animate(xController); xAnimation.addListener(_change); // xAnimation.addStatusListener((status) { // if (status == AnimationStatus.completed) { // xController.reverse(); // } else if (status == AnimationStatus.dismissed) { // xController.forward(); // } // }); // yController = new AnimationController( // vsync: this, duration: Duration(milliseconds: 500)); yAnimation = AlwaysStoppedAnimation(widget.progress); // yAnimation.addListener(_onProgressChange); // yAnimation.addStatusListener(_onProgressStatusChange); doDelay(xController, 0); } @override Widget build(BuildContext context) { return Container( width: double.infinity, height: double.infinity, child: CustomPaint( painter: _factory ..XAnimation = xAnimation ..YAnimation = AlwaysStoppedAnimation(widget.progress), child: Container( child: Text( "${xAnimation.value}", style: TextStyle(color: Colors.transparent), ), ), ), ); } void _change() { if(Application.currentPage == 0) { // print("222222222 ${xAnimation.value}"); // print("${Application.currentPage}"); setProgress(xAnimation.value); setState(() {}); } } void _onProgressChange() { setState(() { // curProgress = yAnimation.value; }); } void _onProgressStatusChange(status) { if (status == AnimationStatus.completed) { onProgressChange(); } } void doDelay(AnimationController controller, int delay) async { Future.delayed(Duration(milliseconds: delay), () { controller..repeat(); }); } @override void dispose() { xController.dispose(); if (yController != null) yController.dispose(); xAnimation.removeListener(_change); yAnimation.removeListener(_onProgressChange); yAnimation.removeStatusListener(_onProgressStatusChange); super.dispose(); } }