diff --git a/example/lib/main.dart b/example/lib/main.dart index 3c14cc3..0e66e6b 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:url_launcher/url_launcher.dart'; -import 'package:wave/config.dart'; import 'package:wave/wave.dart'; void main() => runApp(WaveDemoApp()); diff --git a/lib/config.dart b/lib/src/config.dart similarity index 99% rename from lib/config.dart rename to lib/src/config.dart index 4b160ca..09fc5f5 100644 --- a/lib/config.dart +++ b/lib/src/config.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/widgets.dart'; enum ColorMode { diff --git a/lib/src/widget.dart b/lib/src/widget.dart new file mode 100644 index 0000000..13ec321 --- /dev/null +++ b/lib/src/widget.dart @@ -0,0 +1,483 @@ +// Apache License +// Version 2.0, January 2004 +// http://www.apache.org/licenses/ +// +// TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +// +// 1. Definitions. +// +// "License" shall mean the terms and conditions for use, reproduction, +// and distribution as defined by Sections 1 through 9 of this document. +// +// "Licensor" shall mean the copyright owner or entity authorized by +// the copyright owner that is granting the License. +// +// "Legal Entity" shall mean the union of the acting entity and all +// other entities that control, are controlled by, or are under common +// control with that entity. For the purposes of this definition, +// "control" means (i) the power, direct or indirect, to cause the +// direction or management of such entity, whether by contract or +// otherwise, or (ii) ownership of fifty percent (50%) or more of the +// outstanding shares, or (iii) beneficial ownership of such entity. +// +// "You" (or "Your") shall mean an individual or Legal Entity +// exercising permissions granted by this License. +// +// "Source" form shall mean the preferred form for making modifications, +// including but not limited to software source code, documentation +// source, and configuration files. +// +// "Object" form shall mean any form resulting from mechanical +// transformation or translation of a Source form, including but +// not limited to compiled object code, generated documentation, +// and conversions to other media types. +// +// "Work" shall mean the work of authorship, whether in Source or +// Object form, made available under the License, as indicated by a +// copyright notice that is included in or attached to the work +// (an example is provided in the Appendix below). +// +// "Derivative Works" shall mean any work, whether in Source or Object +// form, that is based on (or derived from) the Work and for which the +// editorial revisions, annotations, elaborations, or other modifications +// represent, as a whole, an original work of authorship. For the purposes +// of this License, Derivative Works shall not include works that remain +// separable from, or merely link (or bind by name) to the interfaces of, +// the Work and Derivative Works thereof. +// +// "Contribution" shall mean any work of authorship, including +// the original version of the Work and any modifications or additions +// to that Work or Derivative Works thereof, that is intentionally +// submitted to Licensor for inclusion in the Work by the copyright owner +// or by an individual or Legal Entity authorized to submit on behalf of +// the copyright owner. For the purposes of this definition, "submitted" +// means any form of electronic, verbal, or written communication sent +// to the Licensor or its representatives, including but not limited to +// communication on electronic mailing lists, source code control systems, +// and issue tracking systems that are managed by, or on behalf of, the +// Licensor for the purpose of discussing and improving the Work, but +// excluding communication that is conspicuously marked or otherwise +// designated in writing by the copyright owner as "Not a Contribution." +// +// "Contributor" shall mean Licensor and any individual or Legal Entity +// on behalf of whom a Contribution has been received by Licensor and +// subsequently incorporated within the Work. +// +// 2. Grant of Copyright License. Subject to the terms and conditions of +// this License, each Contributor hereby grants to You a perpetual, +// worldwide, non-exclusive, no-charge, royalty-free, irrevocable +// copyright license to reproduce, prepare Derivative Works of, +// publicly display, publicly perform, sublicense, and distribute the +// Work and such Derivative Works in Source or Object form. +// +// 3. Grant of Patent License. Subject to the terms and conditions of +// this License, each Contributor hereby grants to You a perpetual, +// worldwide, non-exclusive, no-charge, royalty-free, irrevocable +// (except as stated in this section) patent license to make, have made, +// use, offer to sell, sell, import, and otherwise transfer the Work, +// where such license applies only to those patent claims licensable +// by such Contributor that are necessarily infringed by their +// Contribution(s) alone or by combination of their Contribution(s) +// with the Work to which such Contribution(s) was submitted. If You +// institute patent litigation against any entity (including a +// cross-claim or counterclaim in a lawsuit) alleging that the Work +// or a Contribution incorporated within the Work constitutes direct +// or contributory patent infringement, then any patent licenses +// granted to You under this License for that Work shall terminate +// as of the date such litigation is filed. +// +// 4. Redistribution. You may reproduce and distribute copies of the +// Work or Derivative Works thereof in any medium, with or without +// modifications, and in Source or Object form, provided that You +// meet the following conditions: +// +// (a) You must give any other recipients of the Work or +// Derivative Works a copy of this License; and +// +// (b) You must cause any modified files to carry prominent notices +// stating that You changed the files; and +// +// (c) You must retain, in the Source form of any Derivative Works +// that You distribute, all copyright, patent, trademark, and +// attribution notices from the Source form of the Work, +// excluding those notices that do not pertain to any part of +// the Derivative Works; and +// +// (d) If the Work includes a "NOTICE" text file as part of its +// distribution, then any Derivative Works that You distribute must +// include a readable copy of the attribution notices contained +// within such NOTICE file, excluding those notices that do not +// pertain to any part of the Derivative Works, in at least one +// of the following places: within a NOTICE text file distributed +// as part of the Derivative Works; within the Source form or +// documentation, if provided along with the Derivative Works; or, +// within a display generated by the Derivative Works, if and +// wherever such third-party notices normally appear. The contents +// of the NOTICE file are for informational purposes only and +// do not modify the License. You may add Your own attribution +// notices within Derivative Works that You distribute, alongside +// or as an addendum to the NOTICE text from the Work, provided +// that such additional attribution notices cannot be construed +// as modifying the License. +// +// You may add Your own copyright statement to Your modifications and +// may provide additional or different license terms and conditions +// for use, reproduction, or distribution of Your modifications, or +// for any such Derivative Works as a whole, provided Your use, +// reproduction, and distribution of the Work otherwise complies with +// the conditions stated in this License. +// +// 5. Submission of Contributions. Unless You explicitly state otherwise, +// any Contribution intentionally submitted for inclusion in the Work +// by You to the Licensor shall be under the terms and conditions of +// this License, without any additional terms or conditions. +// Notwithstanding the above, nothing herein shall supersede or modify +// the terms of any separate license agreement you may have executed +// with Licensor regarding such Contributions. +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor, +// except as required for reasonable and customary use in describing the +// origin of the Work and reproducing the content of the NOTICE file. +// +// 7. Disclaimer of Warranty. Unless required by applicable law or +// agreed to in writing, Licensor provides the Work (and each +// Contributor provides its Contributions) on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied, including, without limitation, any warranties or conditions +// of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +// PARTICULAR PURPOSE. You are solely responsible for determining the +// appropriateness of using or redistributing the Work and assume any +// risks associated with Your exercise of permissions under this License. +// +// 8. Limitation of Liability. In no event and under no legal theory, +// whether in tort (including negligence), contract, or otherwise, +// unless required by applicable law (such as deliberate and grossly +// negligent acts) or agreed to in writing, shall any Contributor be +// liable to You for damages, including any direct, indirect, special, +// incidental, or consequential damages of any character arising as a +// result of this License or out of the use or inability to use the +// Work (including but not limited to damages for loss of goodwill, +// work stoppage, computer failure or malfunction, or any and all +// other commercial damages or losses), even if such Contributor +// has been advised of the possibility of such damages. +// +// 9. Accepting Warranty or Additional Liability. While redistributing +// the Work or Derivative Works thereof, You may choose to offer, +// and charge a fee for, acceptance of support, warranty, indemnity, +// or other liability obligations and/or rights consistent with this +// License. However, in accepting such obligations, You may act only +// on Your own behalf and on Your sole responsibility, not on behalf +// of any other Contributor, and only if You agree to indemnify, +// defend, and hold each Contributor harmless for any liability +// incurred by, or claims asserted against, such Contributor by reason +// of your accepting any such warranty or additional liability. +// +// END OF TERMS AND CONDITIONS +// +// APPENDIX: How to apply the Apache License to your work. +// +// To apply the Apache License to your work, attach the following +// boilerplate notice, with the fields enclosed by brackets "[]" +// replaced with your own identifying information. (Don't include +// the brackets!) The text should be enclosed in the appropriate +// comment syntax for the file format. We also recommend that a +// file or class name and description of purpose be included on the +// same "printed page" as the copyright notice for easier +// identification within third-party archives. +// +// Copyright [2018] [While1true] +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:async'; +import 'dart:math'; + +import 'package:flutter/widgets.dart'; +import 'package:wave/wave.dart'; + +class WaveWidget extends StatefulWidget { + final Config config; + final Size size; + final double waveAmplitude; + final double wavePhase; + final double waveFrequency; + final double heightPercentage; + final int? duration; + final Color? backgroundColor; + final DecorationImage? backgroundImage; + final bool isLoop; + + WaveWidget({ + required this.config, + required this.size, + this.waveAmplitude = 20.0, + this.wavePhase = 10.0, + this.waveFrequency = 1.6, + this.heightPercentage = 0.2, + this.duration = 6000, + this.backgroundColor, + this.backgroundImage, + this.isLoop = true, + }); + + @override + State createState() => _WaveWidgetState(); +} + +class _WaveWidgetState extends State with TickerProviderStateMixin { + late List _waveControllers; + late List> _wavePhaseValues; + + List _waveAmplitudes = []; + Map, AnimationController>? valueList; + Timer? _endAnimationTimer; + + _initAnimations() { + if (widget.config.colorMode == ColorMode.custom) { + _waveControllers = + (widget.config as CustomConfig).durations!.map((duration) { + _waveAmplitudes.add(widget.waveAmplitude + 10); + return AnimationController( + vsync: this, duration: Duration(milliseconds: duration)); + }).toList(); + + _wavePhaseValues = _waveControllers.map((controller) { + CurvedAnimation _curve = + CurvedAnimation(parent: controller, curve: Curves.easeInOut); + Animation value = Tween( + begin: widget.wavePhase, + end: 360 + widget.wavePhase, + ).animate( + _curve, + ); + value.addStatusListener((status) { + switch (status) { + case AnimationStatus.completed: + controller.reverse(); + break; + case AnimationStatus.dismissed: + controller.forward(); + break; + default: + break; + } + }); + controller.forward(); + return value; + }).toList(); + + // If isLoop is false, stop the animation after the specified duration. + if (!widget.isLoop) { + _endAnimationTimer = + Timer(Duration(milliseconds: widget.duration!), () { + for (AnimationController waveController in _waveControllers) { + waveController.stop(); + } + }); + } + } + } + + _buildPaints() { + List paints = []; + if (widget.config.colorMode == ColorMode.custom) { + List? _colors = (widget.config as CustomConfig).colors; + List>? _gradients = (widget.config as CustomConfig).gradients; + Alignment? begin = (widget.config as CustomConfig).gradientBegin; + Alignment? end = (widget.config as CustomConfig).gradientEnd; + for (int i = 0; i < _wavePhaseValues.length; i++) { + paints.add( + Container( + child: CustomPaint( + painter: _CustomWavePainter( + color: _colors == null ? null : _colors[i], + gradient: _gradients == null ? null : _gradients[i], + gradientBegin: begin, + gradientEnd: end, + heightPercentage: + (widget.config as CustomConfig).heightPercentages![i], + repaint: _waveControllers[i], + waveFrequency: widget.waveFrequency, + wavePhaseValue: _wavePhaseValues[i], + waveAmplitude: _waveAmplitudes[i], + blur: (widget.config as CustomConfig).blur, + ), + size: widget.size, + ), + ), + ); + } + } + return paints; + } + + _disposeAnimations() { + _waveControllers.forEach((controller) { + controller.dispose(); + }); + } + + @override + void initState() { + super.initState(); + _initAnimations(); + } + + @override + void dispose() { + _disposeAnimations(); + _endAnimationTimer?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: widget.backgroundColor, + image: widget.backgroundImage, + ), + child: Stack( + children: _buildPaints(), + ), + ); + } +} + +/// Meta data of layer +class Layer { + final Color? color; + final List? gradient; + final MaskFilter? blur; + final Path? path; + final double? amplitude; + final double? phase; + + Layer({ + this.color, + this.gradient, + this.blur, + this.path, + this.amplitude, + this.phase, + }); +} + +class _CustomWavePainter extends CustomPainter { + final ColorMode? colorMode; + final Color? color; + final List? gradient; + final Alignment? gradientBegin; + final Alignment? gradientEnd; + final MaskFilter? blur; + + double? waveAmplitude; + + Animation? wavePhaseValue; + + double? waveFrequency; + + double? heightPercentage; + + double _tempA = 0.0; + double _tempB = 0.0; + double viewWidth = 0.0; + Paint _paint = Paint(); + + _CustomWavePainter( + {this.colorMode, + this.color, + this.gradient, + this.gradientBegin, + this.gradientEnd, + this.blur, + this.heightPercentage, + this.waveFrequency, + this.wavePhaseValue, + this.waveAmplitude, + Listenable? repaint}) + : super(repaint: repaint); + + _setPaths(double viewCenterY, Size size, Canvas canvas) { + Layer _layer = Layer( + path: Path(), + color: color, + gradient: gradient, + blur: blur, + amplitude: (-1.6 + 0.8) * waveAmplitude!, + phase: wavePhaseValue!.value * 2 + 30, + ); + + _layer.path!.reset(); + _layer.path!.moveTo( + 0.0, + viewCenterY + + _layer.amplitude! * _getSinY(_layer.phase!, waveFrequency!, -1)); + for (int i = 1; i < size.width + 1; i++) { + _layer.path!.lineTo( + i.toDouble(), + viewCenterY + + _layer.amplitude! * _getSinY(_layer.phase!, waveFrequency!, i)); + } + + _layer.path!.lineTo(size.width, size.height); + _layer.path!.lineTo(0.0, size.height); + _layer.path!.close(); + if (_layer.color != null) { + _paint.color = _layer.color!; + } + if (_layer.gradient != null) { + var rect = Offset.zero & + Size(size.width, size.height - viewCenterY * heightPercentage!); + _paint.shader = LinearGradient( + begin: gradientBegin == null + ? Alignment.bottomCenter + : gradientBegin!, + end: gradientEnd == null ? Alignment.topCenter : gradientEnd!, + colors: _layer.gradient!) + .createShader(rect); + } + if (_layer.blur != null) { + _paint.maskFilter = _layer.blur; + } + + _paint.style = PaintingStyle.fill; + canvas.drawPath(_layer.path!, _paint); + } + + @override + void paint(Canvas canvas, Size size) { + double viewCenterY = size.height * (heightPercentage! + 0.1); + viewWidth = size.width; + _setPaths(viewCenterY, size, canvas); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return false; + } + + double _getSinY( + double startradius, double waveFrequency, int currentposition) { + if (_tempA == 0) { + _tempA = pi / viewWidth; + } + if (_tempB == 0) { + _tempB = 2 * pi / 360.0; + } + + return (sin( + _tempA * waveFrequency * (currentposition + 1) + startradius * _tempB)); + } +} diff --git a/lib/wave.dart b/lib/wave.dart index cb98ad2..3e82d71 100644 --- a/lib/wave.dart +++ b/lib/wave.dart @@ -1,483 +1,2 @@ -// Apache License -// Version 2.0, January 2004 -// http://www.apache.org/licenses/ -// -// TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -// -// 1. Definitions. -// -// "License" shall mean the terms and conditions for use, reproduction, -// and distribution as defined by Sections 1 through 9 of this document. -// -// "Licensor" shall mean the copyright owner or entity authorized by -// the copyright owner that is granting the License. -// -// "Legal Entity" shall mean the union of the acting entity and all -// other entities that control, are controlled by, or are under common -// control with that entity. For the purposes of this definition, -// "control" means (i) the power, direct or indirect, to cause the -// direction or management of such entity, whether by contract or -// otherwise, or (ii) ownership of fifty percent (50%) or more of the -// outstanding shares, or (iii) beneficial ownership of such entity. -// -// "You" (or "Your") shall mean an individual or Legal Entity -// exercising permissions granted by this License. -// -// "Source" form shall mean the preferred form for making modifications, -// including but not limited to software source code, documentation -// source, and configuration files. -// -// "Object" form shall mean any form resulting from mechanical -// transformation or translation of a Source form, including but -// not limited to compiled object code, generated documentation, -// and conversions to other media types. -// -// "Work" shall mean the work of authorship, whether in Source or -// Object form, made available under the License, as indicated by a -// copyright notice that is included in or attached to the work -// (an example is provided in the Appendix below). -// -// "Derivative Works" shall mean any work, whether in Source or Object -// form, that is based on (or derived from) the Work and for which the -// editorial revisions, annotations, elaborations, or other modifications -// represent, as a whole, an original work of authorship. For the purposes -// of this License, Derivative Works shall not include works that remain -// separable from, or merely link (or bind by name) to the interfaces of, -// the Work and Derivative Works thereof. -// -// "Contribution" shall mean any work of authorship, including -// the original version of the Work and any modifications or additions -// to that Work or Derivative Works thereof, that is intentionally -// submitted to Licensor for inclusion in the Work by the copyright owner -// or by an individual or Legal Entity authorized to submit on behalf of -// the copyright owner. For the purposes of this definition, "submitted" -// means any form of electronic, verbal, or written communication sent -// to the Licensor or its representatives, including but not limited to -// communication on electronic mailing lists, source code control systems, -// and issue tracking systems that are managed by, or on behalf of, the -// Licensor for the purpose of discussing and improving the Work, but -// excluding communication that is conspicuously marked or otherwise -// designated in writing by the copyright owner as "Not a Contribution." -// -// "Contributor" shall mean Licensor and any individual or Legal Entity -// on behalf of whom a Contribution has been received by Licensor and -// subsequently incorporated within the Work. -// -// 2. Grant of Copyright License. Subject to the terms and conditions of -// this License, each Contributor hereby grants to You a perpetual, -// worldwide, non-exclusive, no-charge, royalty-free, irrevocable -// copyright license to reproduce, prepare Derivative Works of, -// publicly display, publicly perform, sublicense, and distribute the -// Work and such Derivative Works in Source or Object form. -// -// 3. Grant of Patent License. Subject to the terms and conditions of -// this License, each Contributor hereby grants to You a perpetual, -// worldwide, non-exclusive, no-charge, royalty-free, irrevocable -// (except as stated in this section) patent license to make, have made, -// use, offer to sell, sell, import, and otherwise transfer the Work, -// where such license applies only to those patent claims licensable -// by such Contributor that are necessarily infringed by their -// Contribution(s) alone or by combination of their Contribution(s) -// with the Work to which such Contribution(s) was submitted. If You -// institute patent litigation against any entity (including a -// cross-claim or counterclaim in a lawsuit) alleging that the Work -// or a Contribution incorporated within the Work constitutes direct -// or contributory patent infringement, then any patent licenses -// granted to You under this License for that Work shall terminate -// as of the date such litigation is filed. -// -// 4. Redistribution. You may reproduce and distribute copies of the -// Work or Derivative Works thereof in any medium, with or without -// modifications, and in Source or Object form, provided that You -// meet the following conditions: -// -// (a) You must give any other recipients of the Work or -// Derivative Works a copy of this License; and -// -// (b) You must cause any modified files to carry prominent notices -// stating that You changed the files; and -// -// (c) You must retain, in the Source form of any Derivative Works -// that You distribute, all copyright, patent, trademark, and -// attribution notices from the Source form of the Work, -// excluding those notices that do not pertain to any part of -// the Derivative Works; and -// -// (d) If the Work includes a "NOTICE" text file as part of its -// distribution, then any Derivative Works that You distribute must -// include a readable copy of the attribution notices contained -// within such NOTICE file, excluding those notices that do not -// pertain to any part of the Derivative Works, in at least one -// of the following places: within a NOTICE text file distributed -// as part of the Derivative Works; within the Source form or -// documentation, if provided along with the Derivative Works; or, -// within a display generated by the Derivative Works, if and -// wherever such third-party notices normally appear. The contents -// of the NOTICE file are for informational purposes only and -// do not modify the License. You may add Your own attribution -// notices within Derivative Works that You distribute, alongside -// or as an addendum to the NOTICE text from the Work, provided -// that such additional attribution notices cannot be construed -// as modifying the License. -// -// You may add Your own copyright statement to Your modifications and -// may provide additional or different license terms and conditions -// for use, reproduction, or distribution of Your modifications, or -// for any such Derivative Works as a whole, provided Your use, -// reproduction, and distribution of the Work otherwise complies with -// the conditions stated in this License. -// -// 5. Submission of Contributions. Unless You explicitly state otherwise, -// any Contribution intentionally submitted for inclusion in the Work -// by You to the Licensor shall be under the terms and conditions of -// this License, without any additional terms or conditions. -// Notwithstanding the above, nothing herein shall supersede or modify -// the terms of any separate license agreement you may have executed -// with Licensor regarding such Contributions. -// -// 6. Trademarks. This License does not grant permission to use the trade -// names, trademarks, service marks, or product names of the Licensor, -// except as required for reasonable and customary use in describing the -// origin of the Work and reproducing the content of the NOTICE file. -// -// 7. Disclaimer of Warranty. Unless required by applicable law or -// agreed to in writing, Licensor provides the Work (and each -// Contributor provides its Contributions) on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -// implied, including, without limitation, any warranties or conditions -// of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A -// PARTICULAR PURPOSE. You are solely responsible for determining the -// appropriateness of using or redistributing the Work and assume any -// risks associated with Your exercise of permissions under this License. -// -// 8. Limitation of Liability. In no event and under no legal theory, -// whether in tort (including negligence), contract, or otherwise, -// unless required by applicable law (such as deliberate and grossly -// negligent acts) or agreed to in writing, shall any Contributor be -// liable to You for damages, including any direct, indirect, special, -// incidental, or consequential damages of any character arising as a -// result of this License or out of the use or inability to use the -// Work (including but not limited to damages for loss of goodwill, -// work stoppage, computer failure or malfunction, or any and all -// other commercial damages or losses), even if such Contributor -// has been advised of the possibility of such damages. -// -// 9. Accepting Warranty or Additional Liability. While redistributing -// the Work or Derivative Works thereof, You may choose to offer, -// and charge a fee for, acceptance of support, warranty, indemnity, -// or other liability obligations and/or rights consistent with this -// License. However, in accepting such obligations, You may act only -// on Your own behalf and on Your sole responsibility, not on behalf -// of any other Contributor, and only if You agree to indemnify, -// defend, and hold each Contributor harmless for any liability -// incurred by, or claims asserted against, such Contributor by reason -// of your accepting any such warranty or additional liability. -// -// END OF TERMS AND CONDITIONS -// -// APPENDIX: How to apply the Apache License to your work. -// -// To apply the Apache License to your work, attach the following -// boilerplate notice, with the fields enclosed by brackets "[]" -// replaced with your own identifying information. (Don't include -// the brackets!) The text should be enclosed in the appropriate -// comment syntax for the file format. We also recommend that a -// file or class name and description of purpose be included on the -// same "printed page" as the copyright notice for easier -// identification within third-party archives. -// -// Copyright [2018] [While1true] -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:async'; -import 'dart:math'; - -import 'package:flutter/widgets.dart'; -import 'package:wave/config.dart'; - -class WaveWidget extends StatefulWidget { - final Config config; - final Size size; - final double waveAmplitude; - final double wavePhase; - final double waveFrequency; - final double heightPercentage; - final int? duration; - final Color? backgroundColor; - final DecorationImage? backgroundImage; - final bool isLoop; - - WaveWidget({ - required this.config, - required this.size, - this.waveAmplitude = 20.0, - this.wavePhase = 10.0, - this.waveFrequency = 1.6, - this.heightPercentage = 0.2, - this.duration = 6000, - this.backgroundColor, - this.backgroundImage, - this.isLoop = true, - }); - - @override - State createState() => _WaveWidgetState(); -} - -class _WaveWidgetState extends State with TickerProviderStateMixin { - late List _waveControllers; - late List> _wavePhaseValues; - - List _waveAmplitudes = []; - Map, AnimationController>? valueList; - Timer? _endAnimationTimer; - - _initAnimations() { - if (widget.config.colorMode == ColorMode.custom) { - _waveControllers = - (widget.config as CustomConfig).durations!.map((duration) { - _waveAmplitudes.add(widget.waveAmplitude + 10); - return AnimationController( - vsync: this, duration: Duration(milliseconds: duration)); - }).toList(); - - _wavePhaseValues = _waveControllers.map((controller) { - CurvedAnimation _curve = - CurvedAnimation(parent: controller, curve: Curves.easeInOut); - Animation value = Tween( - begin: widget.wavePhase, - end: 360 + widget.wavePhase, - ).animate( - _curve, - ); - value.addStatusListener((status) { - switch (status) { - case AnimationStatus.completed: - controller.reverse(); - break; - case AnimationStatus.dismissed: - controller.forward(); - break; - default: - break; - } - }); - controller.forward(); - return value; - }).toList(); - - // If isLoop is false, stop the animation after the specified duration. - if (!widget.isLoop) { - _endAnimationTimer = - Timer(Duration(milliseconds: widget.duration!), () { - for (AnimationController waveController in _waveControllers) { - waveController.stop(); - } - }); - } - } - } - - _buildPaints() { - List paints = []; - if (widget.config.colorMode == ColorMode.custom) { - List? _colors = (widget.config as CustomConfig).colors; - List>? _gradients = (widget.config as CustomConfig).gradients; - Alignment? begin = (widget.config as CustomConfig).gradientBegin; - Alignment? end = (widget.config as CustomConfig).gradientEnd; - for (int i = 0; i < _wavePhaseValues.length; i++) { - paints.add( - Container( - child: CustomPaint( - painter: _CustomWavePainter( - color: _colors == null ? null : _colors[i], - gradient: _gradients == null ? null : _gradients[i], - gradientBegin: begin, - gradientEnd: end, - heightPercentage: - (widget.config as CustomConfig).heightPercentages![i], - repaint: _waveControllers[i], - waveFrequency: widget.waveFrequency, - wavePhaseValue: _wavePhaseValues[i], - waveAmplitude: _waveAmplitudes[i], - blur: (widget.config as CustomConfig).blur, - ), - size: widget.size, - ), - ), - ); - } - } - return paints; - } - - _disposeAnimations() { - _waveControllers.forEach((controller) { - controller.dispose(); - }); - } - - @override - void initState() { - super.initState(); - _initAnimations(); - } - - @override - void dispose() { - _disposeAnimations(); - _endAnimationTimer?.cancel(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - color: widget.backgroundColor, - image: widget.backgroundImage, - ), - child: Stack( - children: _buildPaints(), - ), - ); - } -} - -/// Meta data of layer -class Layer { - final Color? color; - final List? gradient; - final MaskFilter? blur; - final Path? path; - final double? amplitude; - final double? phase; - - Layer({ - this.color, - this.gradient, - this.blur, - this.path, - this.amplitude, - this.phase, - }); -} - -class _CustomWavePainter extends CustomPainter { - final ColorMode? colorMode; - final Color? color; - final List? gradient; - final Alignment? gradientBegin; - final Alignment? gradientEnd; - final MaskFilter? blur; - - double? waveAmplitude; - - Animation? wavePhaseValue; - - double? waveFrequency; - - double? heightPercentage; - - double _tempA = 0.0; - double _tempB = 0.0; - double viewWidth = 0.0; - Paint _paint = Paint(); - - _CustomWavePainter( - {this.colorMode, - this.color, - this.gradient, - this.gradientBegin, - this.gradientEnd, - this.blur, - this.heightPercentage, - this.waveFrequency, - this.wavePhaseValue, - this.waveAmplitude, - Listenable? repaint}) - : super(repaint: repaint); - - _setPaths(double viewCenterY, Size size, Canvas canvas) { - Layer _layer = Layer( - path: Path(), - color: color, - gradient: gradient, - blur: blur, - amplitude: (-1.6 + 0.8) * waveAmplitude!, - phase: wavePhaseValue!.value * 2 + 30, - ); - - _layer.path!.reset(); - _layer.path!.moveTo( - 0.0, - viewCenterY + - _layer.amplitude! * _getSinY(_layer.phase!, waveFrequency!, -1)); - for (int i = 1; i < size.width + 1; i++) { - _layer.path!.lineTo( - i.toDouble(), - viewCenterY + - _layer.amplitude! * _getSinY(_layer.phase!, waveFrequency!, i)); - } - - _layer.path!.lineTo(size.width, size.height); - _layer.path!.lineTo(0.0, size.height); - _layer.path!.close(); - if (_layer.color != null) { - _paint.color = _layer.color!; - } - if (_layer.gradient != null) { - var rect = Offset.zero & - Size(size.width, size.height - viewCenterY * heightPercentage!); - _paint.shader = LinearGradient( - begin: gradientBegin == null - ? Alignment.bottomCenter - : gradientBegin!, - end: gradientEnd == null ? Alignment.topCenter : gradientEnd!, - colors: _layer.gradient!) - .createShader(rect); - } - if (_layer.blur != null) { - _paint.maskFilter = _layer.blur; - } - - _paint.style = PaintingStyle.fill; - canvas.drawPath(_layer.path!, _paint); - } - - @override - void paint(Canvas canvas, Size size) { - double viewCenterY = size.height * (heightPercentage! + 0.1); - viewWidth = size.width; - _setPaths(viewCenterY, size, canvas); - } - - @override - bool shouldRepaint(CustomPainter oldDelegate) { - return false; - } - - double _getSinY( - double startradius, double waveFrequency, int currentposition) { - if (_tempA == 0) { - _tempA = pi / viewWidth; - } - if (_tempB == 0) { - _tempB = 2 * pi / 360.0; - } - - return (sin( - _tempA * waveFrequency * (currentposition + 1) + startradius * _tempB)); - } -} +export 'src/config.dart'; +export 'src/widget.dart'; diff --git a/test/wave_test.dart b/test/wave_test.dart index c62ab85..db46d30 100644 --- a/test/wave_test.dart +++ b/test/wave_test.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:wave/config.dart'; import 'package:wave/wave.dart'; void main() {