wave_painter.dart 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. import 'dart:math';
  2. import 'package:flutter/material.dart';
  3. import 'package:sport/application.dart';
  4. class WavePainter extends CustomPainter {
  5. int waveCount;
  6. int crestCount;
  7. double waveHeight;
  8. List<Color> waveColors;
  9. double circleWidth;
  10. Color circleColor;
  11. Color circleBackgroundColor;
  12. bool showProgressText;
  13. TextStyle textStyle;
  14. Animation<double> _xAnimation;
  15. Animation<double> _yAnimation;
  16. set XAnimation(Animation<double> value) {
  17. _xAnimation = value;
  18. }
  19. set YAnimation(Animation<double> value) {
  20. _yAnimation = value;
  21. }
  22. Animation<double> get YAnimation => _yAnimation;
  23. Animation<double> get XAnimation => _xAnimation;
  24. WavePainter(
  25. {this.waveCount = 1,
  26. this.crestCount = 2,
  27. this.waveHeight,
  28. this.waveColors,
  29. this.circleColor = Colors.grey,
  30. this.circleBackgroundColor = Colors.white,
  31. this.circleWidth = 5.0,
  32. this.showProgressText = false,
  33. this.textStyle = const TextStyle(
  34. fontSize: 60.0,
  35. color: Colors.blue,
  36. fontWeight: FontWeight.bold,
  37. shadows: [Shadow(color: Colors.grey, offset: Offset(5.0, 5.0), blurRadius: 5.0)],
  38. )});
  39. @override
  40. void paint(Canvas canvas, Size size) {
  41. double width = size.width;
  42. double height = size.height;
  43. if (waveHeight == null) {
  44. waveHeight = height / 8;
  45. height = height + waveHeight;
  46. }
  47. if (waveColors == null) {
  48. waveColors = [Color.fromARGB(100, Colors.blue.red, Colors.blue.green, Colors.blue.blue)];
  49. }
  50. Offset center = new Offset(width / 2, height / 2);
  51. double xMove = width * XAnimation.value;
  52. double yAnimValue = 0.0;
  53. if (YAnimation != null) {
  54. yAnimValue = YAnimation.value;
  55. }
  56. double yMove = height * (1.0 - yAnimValue);
  57. Offset waveCenter = new Offset(xMove, yMove);
  58. var paintCircle = new Paint()
  59. ..color = Colors.grey
  60. ..style = PaintingStyle.fill
  61. ..strokeWidth = circleWidth
  62. ..maskFilter = MaskFilter.blur(BlurStyle.inner, 5.0);
  63. canvas.drawCircle(center, min(width, height) / 2, paintCircle);
  64. List<Path> wavePaths = [];
  65. for (int index = 0; index < waveCount; index++) {
  66. double direction = pow(-1.0, index);
  67. Path path = new Path()
  68. ..moveTo(waveCenter.dx - width, waveCenter.dy)
  69. ..lineTo(waveCenter.dx - width, center.dy + height / 2)
  70. ..lineTo(waveCenter.dx + width, center.dy + height / 2)
  71. ..lineTo(waveCenter.dx + width, waveCenter.dy);
  72. for (int i = 0; i < 2; i++) {
  73. for (int j = 0; j < crestCount; j++) {
  74. double a = pow(-1.0, j);
  75. path
  76. ..quadraticBezierTo(waveCenter.dx + width * (1 - i - (1 + 2 * j) / (2 * crestCount)), waveCenter.dy + waveHeight * a * direction,
  77. waveCenter.dx + width * (1 - i - (2 + 2 * j) / (2 * crestCount)), waveCenter.dy);
  78. }
  79. }
  80. path..close();
  81. wavePaths.add(path);
  82. }
  83. var paint = new Paint()
  84. ..color = circleBackgroundColor
  85. ..style = PaintingStyle.fill
  86. ..maskFilter = MaskFilter.blur(BlurStyle.inner, 5.0);
  87. canvas.saveLayer(Rect.fromCircle(center: center, radius: min(width, height) / 2), paint);
  88. canvas.drawCircle(center, min(width, height) / 2, paint);
  89. Rect rect = Rect.fromLTRB(0, 0, size.width, 180);
  90. paint
  91. ..blendMode = BlendMode.srcATop
  92. ..style = PaintingStyle.fill
  93. ..strokeWidth = 2.0
  94. ..maskFilter = MaskFilter.blur(BlurStyle.inner, 10.0);
  95. for (int i = 0; i < wavePaths.length; i++) {
  96. if (waveColors.length >= wavePaths.length) {
  97. if (i == 0) {
  98. paint.shader = LinearGradient(
  99. begin: Alignment.bottomCenter,
  100. end: Alignment.topCenter,
  101. colors: <Color>[Color(0xffFF7700), Color(0x44FFD014)],
  102. ).createShader(rect);
  103. } else {
  104. paint.shader = LinearGradient(
  105. begin: Alignment.bottomCenter,
  106. end: Alignment.topCenter,
  107. colors: <Color>[Color(0x99FF7700), Color(0x99FFD014)],
  108. ).createShader(rect);
  109. }
  110. } else {
  111. paint.shader = LinearGradient(
  112. begin: Alignment.bottomCenter,
  113. end: Alignment.topCenter,
  114. colors: <Color>[Color(0xffFFE600), Color(0xffFF9100)],
  115. ).createShader(rect);
  116. }
  117. canvas.drawPath(wavePaths[i], paint);
  118. }
  119. // paint.blendMode = BlendMode.srcATop;
  120. if (showProgressText) {
  121. TextPainter tp = TextPainter(text: TextSpan(text: '${(yAnimValue * 100.0).toStringAsFixed(0)}%', style: textStyle), textDirection: TextDirection.rtl)
  122. ..layout();
  123. tp.paint(canvas, Offset(center.dx - tp.width / 2, center.dy - tp.height / 2));
  124. }
  125. canvas.restore();
  126. }
  127. @override
  128. bool shouldRepaint(CustomPainter oldDelegate) {
  129. return oldDelegate != this;
  130. }
  131. }
  132. class ProgressManager extends StatefulWidget {
  133. final double progress;
  134. ProgressManager(this.progress);
  135. @override
  136. _ProgressManagerState createState() => new _ProgressManagerState()
  137. .._factory = WavePainter(
  138. waveCount: 2,
  139. waveColors: [
  140. Color.fromARGB(100, Colors.pink.red, Colors.pink.green, Colors.pink.blue),
  141. Color.fromARGB(150, Colors.pink.red, Colors.pink.green, Colors.pink.blue),
  142. ],
  143. circleBackgroundColor: Color(0xffffffff),
  144. circleWidth: 2.0);
  145. }
  146. class _ProgressManagerState extends State<ProgressManager> with TickerProviderStateMixin {
  147. AnimationController xController;
  148. AnimationController yController;
  149. Animation<double> xAnimation;
  150. Animation<double> yAnimation;
  151. List<double> _progressList = [];
  152. double curProgress = 0;
  153. WavePainter _factory;
  154. set painter(WavePainter factory) {
  155. _factory = factory;
  156. }
  157. setProgress(double progress) {
  158. _progressList.add(progress);
  159. onProgressChange();
  160. }
  161. onProgressChange() {
  162. if (yController == null) return;
  163. if (_progressList.length > 0) {
  164. if (yController != null && yController.isAnimating) {
  165. return;
  166. }
  167. double nextProgress = _progressList[0];
  168. _progressList.removeAt(0);
  169. final double begin = curProgress;
  170. yController = new AnimationController(vsync: this, duration: Duration(milliseconds: 3000));
  171. yAnimation = AlwaysStoppedAnimation(widget.progress);
  172. yAnimation.addListener(_onProgressChange);
  173. yAnimation.addStatusListener(_onProgressStatusChange);
  174. yController.forward();
  175. }
  176. }
  177. @override
  178. void initState() {
  179. super.initState();
  180. xController = new AnimationController(vsync: this, duration: Duration(milliseconds: 3000));
  181. xAnimation = new Tween(begin: 0.0, end: 1.0).animate(xController);
  182. xAnimation.addListener(_change);
  183. // xAnimation.addStatusListener((status) {
  184. // if (status == AnimationStatus.completed) {
  185. // xController.reverse();
  186. // } else if (status == AnimationStatus.dismissed) {
  187. // xController.forward();
  188. // }
  189. // });
  190. // yController = new AnimationController(
  191. // vsync: this, duration: Duration(milliseconds: 500));
  192. yAnimation = AlwaysStoppedAnimation(widget.progress);
  193. // yAnimation.addListener(_onProgressChange);
  194. // yAnimation.addStatusListener(_onProgressStatusChange);
  195. doDelay(xController, 0);
  196. }
  197. @override
  198. Widget build(BuildContext context) {
  199. return Container(
  200. width: double.infinity,
  201. height: double.infinity,
  202. child: CustomPaint(
  203. painter: _factory
  204. ..XAnimation = xAnimation
  205. ..YAnimation = AlwaysStoppedAnimation(widget.progress),
  206. child: Container(
  207. child: Text(
  208. "${xAnimation.value}",
  209. style: TextStyle(color: Colors.transparent),
  210. ),
  211. ),
  212. ),
  213. );
  214. }
  215. void _change() {
  216. if(Application.currentPage == 0) {
  217. // print("222222222 ${xAnimation.value}");
  218. // print("${Application.currentPage}");
  219. setProgress(xAnimation.value);
  220. setState(() {});
  221. }
  222. }
  223. void _onProgressChange() {
  224. setState(() {
  225. // curProgress = yAnimation.value;
  226. });
  227. }
  228. void _onProgressStatusChange(status) {
  229. if (status == AnimationStatus.completed) {
  230. onProgressChange();
  231. }
  232. }
  233. void doDelay(AnimationController controller, int delay) async {
  234. Future.delayed(Duration(milliseconds: delay), () {
  235. controller..repeat();
  236. });
  237. }
  238. @override
  239. void dispose() {
  240. xController.dispose();
  241. if (yController != null) yController.dispose();
  242. xAnimation.removeListener(_change);
  243. yAnimation.removeListener(_onProgressChange);
  244. yAnimation.removeStatusListener(_onProgressStatusChange);
  245. super.dispose();
  246. }
  247. }