├── image_sequence_animator ├── example │ ├── test │ │ └── example_test.dart │ ├── web │ │ ├── favicon.png │ │ ├── icons │ │ │ ├── Icon-192.png │ │ │ └── Icon-512.png │ │ ├── manifest.json │ │ └── index.html │ ├── assets │ │ └── ImageSequence │ │ │ ├── Frame_00000.png │ │ │ ├── Frame_00001.png │ │ │ ├── Frame_00002.png │ │ │ ├── Frame_00003.png │ │ │ ├── Frame_00004.png │ │ │ ├── Frame_00005.png │ │ │ ├── Frame_00006.png │ │ │ ├── Frame_00007.png │ │ │ ├── Frame_00008.png │ │ │ ├── Frame_00009.png │ │ │ ├── Frame_00010.png │ │ │ ├── Frame_00011.png │ │ │ ├── Frame_00012.png │ │ │ ├── Frame_00013.png │ │ │ ├── Frame_00014.png │ │ │ ├── Frame_00015.png │ │ │ ├── Frame_00016.png │ │ │ ├── Frame_00017.png │ │ │ ├── Frame_00018.png │ │ │ ├── Frame_00019.png │ │ │ ├── Frame_00020.png │ │ │ ├── Frame_00021.png │ │ │ ├── Frame_00022.png │ │ │ ├── Frame_00023.png │ │ │ ├── Frame_00024.png │ │ │ ├── Frame_00025.png │ │ │ ├── Frame_00026.png │ │ │ ├── Frame_00027.png │ │ │ ├── Frame_00028.png │ │ │ ├── Frame_00029.png │ │ │ ├── Frame_00030.png │ │ │ ├── Frame_00031.png │ │ │ ├── Frame_00032.png │ │ │ ├── Frame_00033.png │ │ │ ├── Frame_00034.png │ │ │ ├── Frame_00035.png │ │ │ ├── Frame_00036.png │ │ │ ├── Frame_00037.png │ │ │ ├── Frame_00038.png │ │ │ ├── Frame_00039.png │ │ │ ├── Frame_00040.png │ │ │ ├── Frame_00041.png │ │ │ ├── Frame_00042.png │ │ │ ├── Frame_00043.png │ │ │ ├── Frame_00044.png │ │ │ ├── Frame_00045.png │ │ │ ├── Frame_00046.png │ │ │ ├── Frame_00047.png │ │ │ ├── Frame_00048.png │ │ │ ├── Frame_00049.png │ │ │ ├── Frame_00050.png │ │ │ ├── Frame_00051.png │ │ │ ├── Frame_00052.png │ │ │ ├── Frame_00053.png │ │ │ ├── Frame_00054.png │ │ │ ├── Frame_00055.png │ │ │ ├── Frame_00056.png │ │ │ ├── Frame_00057.png │ │ │ ├── Frame_00058.png │ │ │ └── Frame_00059.png │ ├── .metadata │ ├── pubspec.yaml │ ├── .gitignore │ ├── LICENSE │ ├── CHANGELOG.md │ ├── README.md │ ├── pubspec.lock │ └── lib │ │ └── main.dart ├── test │ └── image_sequence_animator_test.dart ├── .metadata ├── pubspec.yaml ├── LICENSE ├── .gitignore ├── CHANGELOG.md ├── README.md ├── pubspec.lock └── lib │ └── image_sequence_animator.dart ├── LICENSE ├── .gitignore └── README.md /image_sequence_animator/example/test/example_test.dart: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /image_sequence_animator/test/image_sequence_animator_test.dart: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /image_sequence_animator/example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/web/favicon.png -------------------------------------------------------------------------------- /image_sequence_animator/example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /image_sequence_animator/example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00000.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00001.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00002.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00003.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00004.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00005.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00006.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00007.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00008.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00009.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00010.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00010.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00011.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00011.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00012.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00012.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00013.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00013.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00014.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00015.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00016.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00016.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00017.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00017.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00018.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00018.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00019.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00019.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00020.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00021.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00022.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00023.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00023.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00024.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00025.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00025.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00026.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00026.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00027.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00027.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00028.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00028.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00029.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00029.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00030.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00030.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00031.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00031.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00032.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00032.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00033.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00033.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00034.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00034.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00035.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00035.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00036.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00036.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00037.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00037.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00038.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00038.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00039.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00039.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00040.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00040.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00041.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00041.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00042.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00042.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00043.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00044.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00044.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00045.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00045.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00046.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00046.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00047.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00047.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00048.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00049.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00049.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00050.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00050.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00051.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00051.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00052.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00052.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00053.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00053.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00054.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00054.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00055.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00055.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00056.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00056.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00057.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00057.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00058.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00058.png -------------------------------------------------------------------------------- /image_sequence_animator/example/assets/ImageSequence/Frame_00059.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-image-sequence-animator/HEAD/image_sequence_animator/example/assets/ImageSequence/Frame_00059.png -------------------------------------------------------------------------------- /image_sequence_animator/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 20e59316b8b8474554b38493b8ca888794b0234a 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /image_sequence_animator/example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 1a9d635f64d1cf5bf237d5754b2f7f164ca584ee 8 | channel: master 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /image_sequence_animator/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name : image_sequence_animator 2 | description : A simple widget for animating a set of images with full custom controls as an alternative to using a GIF file. 3 | version : 2.0.0 4 | author : Ali Yigit Bireroglu 5 | repository : https://github.com/aliyigitbireroglu/flutter-image-sequence-animator 6 | homepage : https://www.cosmossoftware.coffee 7 | 8 | environment : 9 | sdk: '>=2.12.0 <3.0.0' 10 | 11 | dependencies : 12 | flutter: 13 | sdk: flutter 14 | cached_network_image: ^3.0.0 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | 20 | flutter : 21 | -------------------------------------------------------------------------------- /image_sequence_animator/example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /image_sequence_animator/example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name : example 2 | description : Example project for image_sequence_animator. 3 | version : 2.0.0 4 | author : Ali Yigit Bireroglu 5 | repository : https://github.com/aliyigitbireroglu/flutter-image-sequence-animator 6 | homepage : https://www.cosmossoftware.coffee 7 | 8 | environment : 9 | sdk: '>=2.12.0 <3.0.0' 10 | 11 | dependencies : 12 | flutter : 13 | sdk: flutter 14 | image_sequence_animator: 15 | path: ../ 16 | spring_button : ^2.0.0 17 | 18 | dev_dependencies: 19 | flutter_test: 20 | sdk: flutter 21 | 22 | flutter : 23 | uses-material-design: true 24 | 25 | assets : 26 | - assets/ImageSequence/ 27 | -------------------------------------------------------------------------------- /image_sequence_animator/example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ali Yigit Bireroglu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /image_sequence_animator/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ali Yigit Bireroglu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /image_sequence_animator/example/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ali Yigit Bireroglu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /gitignore 2 | /android 3 | /build 4 | /ios 5 | .notes.md 6 | .notes.txt 7 | 8 | # Miscellaneous 9 | *.class 10 | *.log 11 | *.pyc 12 | *.swp 13 | .DS_Store 14 | .atom/ 15 | .buildlog/ 16 | .history 17 | .svn/ 18 | 19 | # IntelliJ related 20 | *.iml 21 | *.ipr 22 | *.iws 23 | .idea/ 24 | 25 | # The .vscode folder contains launch configuration and tasks you configure in 26 | # VS Code which you may wish to be included in version control, so this line 27 | # is commented out by default. 28 | #.vscode/ 29 | 30 | # Flutter/Dart/Pub related 31 | **/doc/api/ 32 | .dart_tool/ 33 | .flutter-plugins 34 | .packages 35 | .pub-cache/ 36 | .pub/ 37 | build/ 38 | 39 | # Android related 40 | **/android/**/gradle-wrapper.jar 41 | **/android/.gradle 42 | **/android/captures/ 43 | **/android/gradlew 44 | **/android/gradlew.bat 45 | **/android/local.properties 46 | **/android/**/GeneratedPluginRegistrant.java 47 | 48 | # iOS/XCode related 49 | **/ios/**/*.mode1v3 50 | **/ios/**/*.mode2v3 51 | **/ios/**/*.moved-aside 52 | **/ios/**/*.pbxuser 53 | **/ios/**/*.perspectivev3 54 | **/ios/**/*sync/ 55 | **/ios/**/.sconsign.dblite 56 | **/ios/**/.tags* 57 | **/ios/**/.vagrant/ 58 | **/ios/**/DerivedData/ 59 | **/ios/**/Icon? 60 | **/ios/**/Pods/ 61 | **/ios/**/.symlinks/ 62 | **/ios/**/profile 63 | **/ios/**/xcuserdata 64 | **/ios/.generated/ 65 | **/ios/Flutter/App.framework 66 | **/ios/Flutter/Flutter.framework 67 | **/ios/Flutter/Generated.xcconfig 68 | **/ios/Flutter/app.flx 69 | **/ios/Flutter/app.zip 70 | **/ios/Flutter/flutter_assets/ 71 | **/ios/ServiceDefinitions.json 72 | **/ios/Runner/GeneratedPluginRegistrant.* 73 | 74 | # Exceptions to above rules. 75 | !**/ios/**/default.mode1v3 76 | !**/ios/**/default.mode2v3 77 | !**/ios/**/default.pbxuser 78 | !**/ios/**/default.perspectivev3 79 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 80 | -------------------------------------------------------------------------------- /image_sequence_animator/.gitignore: -------------------------------------------------------------------------------- 1 | /gitignore 2 | /android 3 | /build 4 | /ios 5 | .notes.md 6 | .notes.txt 7 | 8 | # Miscellaneous 9 | *.class 10 | *.log 11 | *.pyc 12 | *.swp 13 | .DS_Store 14 | .atom/ 15 | .buildlog/ 16 | .history 17 | .svn/ 18 | 19 | # IntelliJ related 20 | *.iml 21 | *.ipr 22 | *.iws 23 | .idea/ 24 | 25 | # The .vscode folder contains launch configuration and tasks you configure in 26 | # VS Code which you may wish to be included in version control, so this line 27 | # is commented out by default. 28 | #.vscode/ 29 | 30 | # Flutter/Dart/Pub related 31 | **/doc/api/ 32 | .dart_tool/ 33 | .flutter-plugins 34 | .packages 35 | .pub-cache/ 36 | .pub/ 37 | build/ 38 | 39 | # Android related 40 | **/android/**/gradle-wrapper.jar 41 | **/android/.gradle 42 | **/android/captures/ 43 | **/android/gradlew 44 | **/android/gradlew.bat 45 | **/android/local.properties 46 | **/android/**/GeneratedPluginRegistrant.java 47 | 48 | # iOS/XCode related 49 | **/ios/**/*.mode1v3 50 | **/ios/**/*.mode2v3 51 | **/ios/**/*.moved-aside 52 | **/ios/**/*.pbxuser 53 | **/ios/**/*.perspectivev3 54 | **/ios/**/*sync/ 55 | **/ios/**/.sconsign.dblite 56 | **/ios/**/.tags* 57 | **/ios/**/.vagrant/ 58 | **/ios/**/DerivedData/ 59 | **/ios/**/Icon? 60 | **/ios/**/Pods/ 61 | **/ios/**/.symlinks/ 62 | **/ios/**/profile 63 | **/ios/**/xcuserdata 64 | **/ios/.generated/ 65 | **/ios/Flutter/App.framework 66 | **/ios/Flutter/Flutter.framework 67 | **/ios/Flutter/Generated.xcconfig 68 | **/ios/Flutter/app.flx 69 | **/ios/Flutter/app.zip 70 | **/ios/Flutter/flutter_assets/ 71 | **/ios/ServiceDefinitions.json 72 | **/ios/Runner/GeneratedPluginRegistrant.* 73 | 74 | # Exceptions to above rules. 75 | !**/ios/**/default.mode1v3 76 | !**/ios/**/default.mode2v3 77 | !**/ios/**/default.pbxuser 78 | !**/ios/**/default.perspectivev3 79 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 80 | -------------------------------------------------------------------------------- /image_sequence_animator/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [2.0.0] - 04.05.2021 2 | 3 | * Migrated to Null Safety. 4 | 5 | ## [1.0.10] - 18.12.2020 6 | 7 | * [fullPaths] is added. If you would like to specify a list of endpoints for the frames in your image sequence animator, use this value. If set, values for 8 | [folderName], [fileName], [suffixStart], [suffixCount], [fileFormat] and [frameCount] will be ignored. 9 | 10 | ## [1.0.9] - 16.10.2020 11 | 12 | * Minor changes. 13 | 14 | ## [1.0.8] - 16.10.2020 15 | 16 | * [isOnline] is added. If your [folderName] is an online path, this value should be set to true. 17 | 18 | * [waitUntilCacheIsComplete] is added. If you want the [ImageSequenceAnimator] to wait until the entire image sequence is cached, this value should be set 19 | to true i. Otherwise, the [ImageSequenceAnimator] will invoke [onReadyToPlay] and start playing if [isAutoPlay] is set to true when it approximates that the 20 | remaining caching can be completed without causing stutters. This value is only used if [isOnline] is set to true. 21 | 22 | * [cacheProgressIndicatorBuilder] is added. If you want to display a widget until the [ImageSequenceAnimator] is ready to be played, use this function. 23 | 24 | * Improved documentation. 25 | 26 | ## [1.0.7] - 11.10.2020 27 | 28 | * Regular maintenance. 29 | 30 | ## [1.0.6] - 21.11.2019 31 | 32 | * Minor changes. 33 | 34 | ## [1.0.5] - 30.08.2019 35 | 36 | * Minor changes. 37 | 38 | * Improved code style. 39 | 40 | * [1.0.5+1] Updated README. 41 | 42 | ## [1.0.4] - 23.08.2019 43 | 44 | * Minor changes. 45 | 46 | * Improved code style with trailing commas. 47 | 48 | * [1.0.4+1] Minor changes. 49 | 50 | ## [1.0.3] - 21.08.2019 51 | 52 | * Minor changes. 53 | 54 | * Updated README. 55 | 56 | ## [1.0.2] - 20.08.2019 57 | 58 | * Improved code style. 59 | 60 | * Code excerpt added to the README. 61 | 62 | ## [1.0.1] - 18.08.2019 63 | 64 | * Improved documentation. 65 | 66 | ## [1.0.0] - 17.08.2019 67 | 68 | * Initial release. 69 | -------------------------------------------------------------------------------- /image_sequence_animator/example/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [2.0.0] - 04.05.2021 2 | 3 | * Migrated to Null Safety. 4 | 5 | ## [1.0.10] - 18.12.2020 6 | 7 | * [fullPaths] is added. If you would like to specify a list of endpoints for the frames in your image sequence animator, use this value. If set, values for 8 | [folderName], [fileName], [suffixStart], [suffixCount], [fileFormat] and [frameCount] will be ignored. 9 | 10 | ## [1.0.9] - 16.10.2020 11 | 12 | * Minor changes. 13 | 14 | ## [1.0.8] - 16.10.2020 15 | 16 | * [isOnline] is added. If your [folderName] is an online path, this value should be set to true. 17 | 18 | * [waitUntilCacheIsComplete] is added. If you want the [ImageSequenceAnimator] to wait until the entire image sequence is cached, this value should be set 19 | to true i. Otherwise, the [ImageSequenceAnimator] will invoke [onReadyToPlay] and start playing if [isAutoPlay] is set to true when it approximates that the 20 | remaining caching can be completed without causing stutters. This value is only used if [isOnline] is set to true. 21 | 22 | * [cacheProgressIndicatorBuilder] is added. If you want to display a widget until the [ImageSequenceAnimator] is ready to be played, use this function. 23 | 24 | * Improved documentation. 25 | 26 | ## [1.0.7] - 11.10.2020 27 | 28 | * Regular maintenance. 29 | 30 | ## [1.0.6] - 21.11.2019 31 | 32 | * Minor changes. 33 | 34 | ## [1.0.5] - 30.08.2019 35 | 36 | * Minor changes. 37 | 38 | * Improved code style. 39 | 40 | * [1.0.5+1] Updated README. 41 | 42 | ## [1.0.4] - 23.08.2019 43 | 44 | * Minor changes. 45 | 46 | * Improved code style with trailing commas. 47 | 48 | * [1.0.4+1] Minor changes. 49 | 50 | ## [1.0.3] - 21.08.2019 51 | 52 | * Minor changes. 53 | 54 | * Updated README. 55 | 56 | ## [1.0.2] - 20.08.2019 57 | 58 | * Improved code style. 59 | 60 | * Code excerpt added to the README. 61 | 62 | ## [1.0.1] - 18.08.2019 63 | 64 | * Improved documentation. 65 | 66 | ## [1.0.0] - 17.08.2019 67 | 68 | * Initial release. 69 | -------------------------------------------------------------------------------- /image_sequence_animator/example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | example 27 | 28 | 29 | 30 | 33 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # image_sequence_animator 2 | 3 | [comment]: <> (Badges) 4 | 5 | Cosmos Software 6 | 7 | 8 | [![Pub](https://img.shields.io/pub/v/image_sequence_animator?color=g)](https://pub.dev/packages/image_sequence_animator) 9 | [![License](https://img.shields.io/github/license/aliyigitbireroglu/flutter-image-sequence-animator?color=blue)](https://github.com/aliyigitbireroglu/flutter-image-sequence-animator/blob/master/LICENSE) 10 | 11 | [comment]: <> (Introduction) 12 | A simple widget for animating a set of images with full custom controls as an alternative to using a GIF file. 13 | 14 | **If you have a GIF file you would like to use with this package, I recommend [EZGIF](https://ezgif.com/split) to convert your GIF file to an image 15 | sequence.** 16 | 17 | **It is highly recommended to read the documentation and run the example project on a real device to fully understand and inspect the full range 18 | of capabilities.** 19 | 20 | [comment]: <> (ToC) 21 | [Media](#media) | [Description](#description) | [How-to-Use](#howtouse) 22 | 23 | [comment]: <> (Recent) 24 | ## Recent 25 | * **[isOnline] is added. If your [folderName] is an online path, this value should be set to true.** 26 | 27 | * **[waitUntilCacheIsComplete] is added. If you want the [ImageSequenceAnimator] to wait until the entire image sequence is cached, this value should be set 28 | to true i. Otherwise, the [ImageSequenceAnimator] will invoke [onReadyToPlay] and start playing if [isAutoPlay] is set to true when it approximates that the 29 | remaining caching can be completed without causing stutters. This value is only used if [isOnline] is set to true.** 30 | 31 | * **[cacheProgressIndicatorBuilder] is added. If you want to display a widget until the [ImageSequenceAnimator] is ready to be played, use this function.** 32 | * * * 33 | 34 | 35 | [comment]: <> (Media) 36 | 37 | ## Media 38 | 39 | Watch on **Youtube**: 40 | 41 | 42 | Image Sequence Animator 43 | 44 | 45 | 46 | [comment]: <> (Description) 47 | 48 | ## Description 49 | This simple widget for animating a set of images **(a.k.a an image sequence)** with full custom controls as an alternative to using a GIF file. 50 | 51 | GIF files are, as far as I know, not possible to control. With this package, you will have full control over your image sequence like controlling a 52 | video. You can loop, boomerang, change the color, play, pause, stop, skip, rewind, restart and more. 53 | 54 | 55 | [comment]: <> (How-to-Use) 56 | 57 | ## How-to-Use 58 | First, add your image sequence to your assets and update the "pubspec.yaml" accordingly. 59 | 60 | Then create an ImageSequenceAnimator widget as shown in the example: 61 | 62 | ``` 63 | ImageSequenceAnimator( 64 | "assets/ImageSequences/MyImageSequence", //folderName 65 | "Frame_", //fileName 66 | 0, //suffixStart 67 | 5, //suffixCount 68 | "png", //fileFormat 69 | 60, //frameCount 70 | {Key key, 71 | fps : 60, 72 | isLooping : false, 73 | isBoomerang : false, 74 | isAutoPlay : true, 75 | color : Colors.white, 76 | onReadyToPlay : _onReadyToPlay, 77 | onStartPlaying : _onStartPlaying, 78 | onPlaying : _onPlaying, 79 | onFinishPlaying : _onFinishPlaying}) 80 | 81 | ImageSequenceAnimator( 82 | "https://www.domain.com/ImageSequences/MyImageSequence", //folderName 83 | "Frame_", //fileName 84 | 0, //suffixStart 85 | 5, //suffixCount 86 | "png", //fileFormat 87 | 60, //frameCount 88 | {Key key, 89 | fps : 60, 90 | isLooping : false, 91 | isBoomerang : false, 92 | isAutoPlay: true, 93 | isOnline: true, 94 | waitUntilCacheIsComplete: true, 95 | cacheProgressIndicatorBuilder: _cacheProgressIndicatorBuilder, 96 | color : Colors.white, 97 | onReadyToPlay : _onReadyToPlay, 98 | onStartPlaying : _onStartPlaying, 99 | onPlaying : _onPlaying, 100 | onFinishPlaying : _onFinishPlaying}) 101 | 102 | Widget _cacheProgressIndicatorBuilder(BuildContext _context , double _progress); 103 | void _onReadyToPlay(ImageSequenceAnimatorState _imageSequenceAnimator); 104 | void _onStartPlaying(ImageSequenceAnimatorState _imageSequenceAnimator); 105 | void _onPlaying(ImageSequenceAnimatorState _imageSequenceAnimator); 106 | void _onFinishPlaying(ImageSequenceAnimatorState _imageSequenceAnimator); 107 | ``` 108 | 109 | **Further Explanations:** 110 | 111 | *For a complete set of descriptions for all parameters and methods, see the [documentation](https://pub.dev/documentation/image_sequence_animator/latest/).* 112 | 113 | * [isLooping] will override [isBoomerang] if both are set to true. 114 | * All [ImageSequenceProcessCallback] callbacks will return a reference to the created [ImageSequenceAnimator] state. You can save this instance for 115 | further actions. 116 | * Use [ImageSequenceAnimatorState]'s 117 | [void setIsLooping(bool isLooping)], [void setIsBoomerang(bool isBoomerang)], [void setColor(Color color)], [void play({double from: -1.0})], 118 | [void rewind({double from: -1.0})], [void pause()], [void skip(double value, {double percentage: -1.0})], [void restart()], [void stop()] 119 | methods for the corresponding actions. 120 | * Use [ImageSequenceAnimatorState]'s [bool get isLooping], [bool get isBoomerang], [double get currentProgress], [double get totalProgress], 121 | [double get currentTime] and [double get totalTime] methods to get the respective values. 122 | 123 | 124 | [comment]: <> (Notes) 125 | ## Notes 126 | I started using and learning Flutter only some weeks ago so this package might have some parts that don't make sense, that should be completely 127 | different, that could be much better, etc. Please let me know! Nicely! 128 | 129 | Any help, suggestion or criticism is appreciated! 130 | 131 | Cheers. 132 | 133 | [comment]: <> (CosmosSoftware) 134 |

135 | 136 |

137 | -------------------------------------------------------------------------------- /image_sequence_animator/README.md: -------------------------------------------------------------------------------- 1 | # image_sequence_animator 2 | 3 | [comment]: <> (Badges) 4 | 5 | Cosmos Software 6 | 7 | 8 | [![Pub](https://img.shields.io/pub/v/image_sequence_animator?color=g)](https://pub.dev/packages/image_sequence_animator) 9 | [![License](https://img.shields.io/github/license/aliyigitbireroglu/flutter-image-sequence-animator?color=blue)](https://github.com/aliyigitbireroglu/flutter-image-sequence-animator/blob/master/LICENSE) 10 | 11 | [comment]: <> (Introduction) 12 | A simple widget for animating a set of images with full custom controls as an alternative to using a GIF file. 13 | 14 | **If you have a GIF file you would like to use with this package, I recommend [EZGIF](https://ezgif.com/split) to convert your GIF file to an image 15 | sequence.** 16 | 17 | **It is highly recommended to read the documentation and run the example project on a real device to fully understand and inspect the full range 18 | of capabilities.** 19 | 20 | [comment]: <> (ToC) 21 | [Media](#media) | [Description](#description) | [How-to-Use](#howtouse) 22 | 23 | [comment]: <> (Recent) 24 | ## Recent 25 | * **[fullPaths] is added. If you would like to specify a list of endpoints for the frames in your image sequence animator, use this value. If set, values for 26 | [folderName], [fileName], [suffixStart], [suffixCount], [fileFormat] and [frameCount] will be ignored.** 27 | 28 | * **[isOnline] is added. If your [folderName] is an online path, this value should be set to true.** 29 | 30 | * **[waitUntilCacheIsComplete] is added. If you want the [ImageSequenceAnimator] to wait until the entire image sequence is cached, this value should be set 31 | to true i. Otherwise, the [ImageSequenceAnimator] will invoke [onReadyToPlay] and start playing if [isAutoPlay] is set to true when it approximates that the 32 | remaining caching can be completed without causing stutters. This value is only used if [isOnline] is set to true.** 33 | 34 | * **[cacheProgressIndicatorBuilder] is added. If you want to display a widget until the [ImageSequenceAnimator] is ready to be played, use this function.** 35 | * * * 36 | 37 | 38 | [comment]: <> (Media) 39 | 40 | ## Media 41 | 42 | Watch on **Youtube**: 43 | 44 | 45 | Image Sequence Animator 46 | 47 | 48 | 49 | [comment]: <> (Description) 50 | 51 | ## Description 52 | This simple widget for animating a set of images **(a.k.a an image sequence)** with full custom controls as an alternative to using a GIF file. 53 | 54 | GIF files are, as far as I know, not possible to control. With this package, you will have full control over your image sequence like controlling a 55 | video. You can loop, boomerang, change the color, play, pause, stop, skip, rewind, restart and more. 56 | 57 | 58 | [comment]: <> (How-to-Use) 59 | 60 | ## How-to-Use 61 | First, add your image sequence to your assets and update the "pubspec.yaml" accordingly. 62 | 63 | Then create an ImageSequenceAnimator widget as shown in the example: 64 | 65 | ``` 66 | ImageSequenceAnimator( 67 | "assets/ImageSequences/MyImageSequence", //folderName 68 | "Frame_", //fileName 69 | 0, //suffixStart 70 | 5, //suffixCount 71 | "png", //fileFormat 72 | 60, //frameCount 73 | {Key key, 74 | fps : 60, 75 | isLooping : false, 76 | isBoomerang : false, 77 | isAutoPlay : true, 78 | color : Colors.white, 79 | onReadyToPlay : _onReadyToPlay, 80 | onStartPlaying : _onStartPlaying, 81 | onPlaying : _onPlaying, 82 | onFinishPlaying : _onFinishPlaying}) 83 | 84 | ImageSequenceAnimator( 85 | "https://www.domain.com/ImageSequences/MyImageSequence", //folderName 86 | "Frame_", //fileName 87 | 0, //suffixStart 88 | 5, //suffixCount 89 | "png", //fileFormat 90 | 60, //frameCount 91 | {Key key, 92 | fullPahts : [], 93 | fps : 60, 94 | isLooping : false, 95 | isBoomerang : false, 96 | isAutoPlay: true, 97 | isOnline: true, 98 | waitUntilCacheIsComplete: true, 99 | cacheProgressIndicatorBuilder: _cacheProgressIndicatorBuilder, 100 | color : Colors.white, 101 | onReadyToPlay : _onReadyToPlay, 102 | onStartPlaying : _onStartPlaying, 103 | onPlaying : _onPlaying, 104 | onFinishPlaying : _onFinishPlaying}) 105 | 106 | Widget _cacheProgressIndicatorBuilder(BuildContext _context , double _progress); 107 | void _onReadyToPlay(ImageSequenceAnimatorState _imageSequenceAnimator); 108 | void _onStartPlaying(ImageSequenceAnimatorState _imageSequenceAnimator); 109 | void _onPlaying(ImageSequenceAnimatorState _imageSequenceAnimator); 110 | void _onFinishPlaying(ImageSequenceAnimatorState _imageSequenceAnimator); 111 | ``` 112 | 113 | **Further Explanations:** 114 | 115 | *For a complete set of descriptions for all parameters and methods, see the [documentation](https://pub.dev/documentation/image_sequence_animator/latest/).* 116 | 117 | * [isLooping] will override [isBoomerang] if both are set to true. 118 | * All [ImageSequenceProcessCallback] callbacks will return a reference to the created [ImageSequenceAnimator] state. You can save this instance for 119 | further actions. 120 | * Use [ImageSequenceAnimatorState]'s 121 | [void setIsLooping(bool isLooping)], [void setIsBoomerang(bool isBoomerang)], [void setColor(Color color)], [void play({double from: -1.0})], 122 | [void rewind({double from: -1.0})], [void pause()], [void skip(double value, {double percentage: -1.0})], [void restart()], [void stop()] 123 | methods for the corresponding actions. 124 | * Use [ImageSequenceAnimatorState]'s [bool get isLooping], [bool get isBoomerang], [double get currentProgress], [double get totalProgress], 125 | [double get currentTime] and [double get totalTime] methods to get the respective values. 126 | 127 | 128 | [comment]: <> (Notes) 129 | ## Notes 130 | I started using and learning Flutter only some weeks ago so this package might have some parts that don't make sense, that should be completely 131 | different, that could be much better, etc. Please let me know! Nicely! 132 | 133 | Any help, suggestion or criticism is appreciated! 134 | 135 | Cheers. 136 | 137 | [comment]: <> (CosmosSoftware) 138 |

139 | 140 |

141 | -------------------------------------------------------------------------------- /image_sequence_animator/example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | Example Project for image_sequence_animator. 4 | 5 | 6 | # image_sequence_animator 7 | 8 | [comment]: <> (Badges) 9 | 10 | Cosmos Software 11 | 12 | 13 | [![Pub](https://img.shields.io/pub/v/image_sequence_animator?color=g)](https://pub.dev/packages/image_sequence_animator) 14 | [![License](https://img.shields.io/github/license/aliyigitbireroglu/flutter-image-sequence-animator?color=blue)](https://github.com/aliyigitbireroglu/flutter-image-sequence-animator/blob/master/LICENSE) 15 | 16 | [comment]: <> (Introduction) 17 | A simple widget for animating a set of images with full custom controls as an alternative to using a GIF file. 18 | 19 | **If you have a GIF file you would like to use with this package, I recommend [EZGIF](https://ezgif.com/split) to convert your GIF file to an image 20 | sequence.** 21 | 22 | **It is highly recommended to read the documentation and run the example project on a real device to fully understand and inspect the full range 23 | of capabilities.** 24 | 25 | [comment]: <> (ToC) 26 | [Media](#media) | [Description](#description) | [How-to-Use](#howtouse) 27 | 28 | [comment]: <> (Recent) 29 | ## Recent 30 | * **[fullPaths] is added. If you would like to specify a list of endpoints for the frames in your image sequence animator, use this value. If set, values for 31 | [folderName], [fileName], [suffixStart], [suffixCount], [fileFormat] and [frameCount] will be ignored.** 32 | 33 | * **[isOnline] is added. If your [folderName] is an online path, this value should be set to true.** 34 | 35 | * **[waitUntilCacheIsComplete] is added. If you want the [ImageSequenceAnimator] to wait until the entire image sequence is cached, this value should be set 36 | to true i. Otherwise, the [ImageSequenceAnimator] will invoke [onReadyToPlay] and start playing if [isAutoPlay] is set to true when it approximates that the 37 | remaining caching can be completed without causing stutters. This value is only used if [isOnline] is set to true.** 38 | 39 | * **[cacheProgressIndicatorBuilder] is added. If you want to display a widget until the [ImageSequenceAnimator] is ready to be played, use this function.** 40 | * * * 41 | 42 | 43 | [comment]: <> (Media) 44 | 45 | ## Media 46 | 47 | Watch on **Youtube**: 48 | 49 | 50 | Image Sequence Animator 51 | 52 | 53 | 54 | [comment]: <> (Description) 55 | 56 | ## Description 57 | This simple widget for animating a set of images **(a.k.a an image sequence)** with full custom controls as an alternative to using a GIF file. 58 | 59 | GIF files are, as far as I know, not possible to control. With this package, you will have full control over your image sequence like controlling a 60 | video. You can loop, boomerang, change the color, play, pause, stop, skip, rewind, restart and more. 61 | 62 | 63 | [comment]: <> (How-to-Use) 64 | 65 | ## How-to-Use 66 | First, add your image sequence to your assets and update the "pubspec.yaml" accordingly. 67 | 68 | Then create an ImageSequenceAnimator widget as shown in the example: 69 | 70 | ``` 71 | ImageSequenceAnimator( 72 | "assets/ImageSequences/MyImageSequence", //folderName 73 | "Frame_", //fileName 74 | 0, //suffixStart 75 | 5, //suffixCount 76 | "png", //fileFormat 77 | 60, //frameCount 78 | {Key key, 79 | fps : 60, 80 | isLooping : false, 81 | isBoomerang : false, 82 | isAutoPlay : true, 83 | color : Colors.white, 84 | onReadyToPlay : _onReadyToPlay, 85 | onStartPlaying : _onStartPlaying, 86 | onPlaying : _onPlaying, 87 | onFinishPlaying : _onFinishPlaying}) 88 | 89 | ImageSequenceAnimator( 90 | "https://www.domain.com/ImageSequences/MyImageSequence", //folderName 91 | "Frame_", //fileName 92 | 0, //suffixStart 93 | 5, //suffixCount 94 | "png", //fileFormat 95 | 60, //frameCount 96 | {Key key, 97 | fullPahts : [], 98 | fps : 60, 99 | isLooping : false, 100 | isBoomerang : false, 101 | isAutoPlay: true, 102 | isOnline: true, 103 | waitUntilCacheIsComplete: true, 104 | cacheProgressIndicatorBuilder: _cacheProgressIndicatorBuilder, 105 | color : Colors.white, 106 | onReadyToPlay : _onReadyToPlay, 107 | onStartPlaying : _onStartPlaying, 108 | onPlaying : _onPlaying, 109 | onFinishPlaying : _onFinishPlaying}) 110 | 111 | Widget _cacheProgressIndicatorBuilder(BuildContext _context , double _progress); 112 | void _onReadyToPlay(ImageSequenceAnimatorState _imageSequenceAnimator); 113 | void _onStartPlaying(ImageSequenceAnimatorState _imageSequenceAnimator); 114 | void _onPlaying(ImageSequenceAnimatorState _imageSequenceAnimator); 115 | void _onFinishPlaying(ImageSequenceAnimatorState _imageSequenceAnimator); 116 | ``` 117 | 118 | **Further Explanations:** 119 | 120 | *For a complete set of descriptions for all parameters and methods, see the [documentation](https://pub.dev/documentation/image_sequence_animator/latest/).* 121 | 122 | * [isLooping] will override [isBoomerang] if both are set to true. 123 | * All [ImageSequenceProcessCallback] callbacks will return a reference to the created [ImageSequenceAnimator] state. You can save this instance for 124 | further actions. 125 | * Use [ImageSequenceAnimatorState]'s 126 | [void setIsLooping(bool isLooping)], [void setIsBoomerang(bool isBoomerang)], [void setColor(Color color)], [void play({double from: -1.0})], 127 | [void rewind({double from: -1.0})], [void pause()], [void skip(double value, {double percentage: -1.0})], [void restart()], [void stop()] 128 | methods for the corresponding actions. 129 | * Use [ImageSequenceAnimatorState]'s [bool get isLooping], [bool get isBoomerang], [double get currentProgress], [double get totalProgress], 130 | [double get currentTime] and [double get totalTime] methods to get the respective values. 131 | 132 | 133 | [comment]: <> (Notes) 134 | ## Notes 135 | I started using and learning Flutter only some weeks ago so this package might have some parts that don't make sense, that should be completely 136 | different, that could be much better, etc. Please let me know! Nicely! 137 | 138 | Any help, suggestion or criticism is appreciated! 139 | 140 | Cheers. 141 | 142 | [comment]: <> (CosmosSoftware) 143 |

144 | 145 |

146 | -------------------------------------------------------------------------------- /image_sequence_animator/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "3.1.2" 11 | async: 12 | dependency: transitive 13 | description: 14 | name: async 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.6.0" 18 | boolean_selector: 19 | dependency: transitive 20 | description: 21 | name: boolean_selector 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.1.0" 25 | cached_network_image: 26 | dependency: "direct main" 27 | description: 28 | name: cached_network_image 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "3.0.0" 32 | characters: 33 | dependency: transitive 34 | description: 35 | name: characters 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | charcode: 40 | dependency: transitive 41 | description: 42 | name: charcode 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.2.0" 46 | clock: 47 | dependency: transitive 48 | description: 49 | name: clock 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.1.0" 53 | collection: 54 | dependency: transitive 55 | description: 56 | name: collection 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.15.0" 60 | crypto: 61 | dependency: transitive 62 | description: 63 | name: crypto 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "3.0.1" 67 | fake_async: 68 | dependency: transitive 69 | description: 70 | name: fake_async 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.2.0" 74 | ffi: 75 | dependency: transitive 76 | description: 77 | name: ffi 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "1.0.0" 81 | file: 82 | dependency: transitive 83 | description: 84 | name: file 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "6.1.0" 88 | flutter: 89 | dependency: "direct main" 90 | description: flutter 91 | source: sdk 92 | version: "0.0.0" 93 | flutter_blurhash: 94 | dependency: transitive 95 | description: 96 | name: flutter_blurhash 97 | url: "https://pub.dartlang.org" 98 | source: hosted 99 | version: "0.6.0" 100 | flutter_cache_manager: 101 | dependency: transitive 102 | description: 103 | name: flutter_cache_manager 104 | url: "https://pub.dartlang.org" 105 | source: hosted 106 | version: "3.0.1" 107 | flutter_test: 108 | dependency: "direct dev" 109 | description: flutter 110 | source: sdk 111 | version: "0.0.0" 112 | http: 113 | dependency: transitive 114 | description: 115 | name: http 116 | url: "https://pub.dartlang.org" 117 | source: hosted 118 | version: "0.13.3" 119 | http_parser: 120 | dependency: transitive 121 | description: 122 | name: http_parser 123 | url: "https://pub.dartlang.org" 124 | source: hosted 125 | version: "4.0.0" 126 | image: 127 | dependency: transitive 128 | description: 129 | name: image 130 | url: "https://pub.dartlang.org" 131 | source: hosted 132 | version: "3.0.2" 133 | matcher: 134 | dependency: transitive 135 | description: 136 | name: matcher 137 | url: "https://pub.dartlang.org" 138 | source: hosted 139 | version: "0.12.10" 140 | meta: 141 | dependency: transitive 142 | description: 143 | name: meta 144 | url: "https://pub.dartlang.org" 145 | source: hosted 146 | version: "1.3.0" 147 | octo_image: 148 | dependency: transitive 149 | description: 150 | name: octo_image 151 | url: "https://pub.dartlang.org" 152 | source: hosted 153 | version: "1.0.0+1" 154 | path: 155 | dependency: transitive 156 | description: 157 | name: path 158 | url: "https://pub.dartlang.org" 159 | source: hosted 160 | version: "1.8.0" 161 | path_provider: 162 | dependency: transitive 163 | description: 164 | name: path_provider 165 | url: "https://pub.dartlang.org" 166 | source: hosted 167 | version: "2.0.1" 168 | path_provider_linux: 169 | dependency: transitive 170 | description: 171 | name: path_provider_linux 172 | url: "https://pub.dartlang.org" 173 | source: hosted 174 | version: "2.0.0" 175 | path_provider_macos: 176 | dependency: transitive 177 | description: 178 | name: path_provider_macos 179 | url: "https://pub.dartlang.org" 180 | source: hosted 181 | version: "2.0.0" 182 | path_provider_platform_interface: 183 | dependency: transitive 184 | description: 185 | name: path_provider_platform_interface 186 | url: "https://pub.dartlang.org" 187 | source: hosted 188 | version: "2.0.1" 189 | path_provider_windows: 190 | dependency: transitive 191 | description: 192 | name: path_provider_windows 193 | url: "https://pub.dartlang.org" 194 | source: hosted 195 | version: "2.0.1" 196 | pedantic: 197 | dependency: transitive 198 | description: 199 | name: pedantic 200 | url: "https://pub.dartlang.org" 201 | source: hosted 202 | version: "1.11.0" 203 | petitparser: 204 | dependency: transitive 205 | description: 206 | name: petitparser 207 | url: "https://pub.dartlang.org" 208 | source: hosted 209 | version: "4.1.0" 210 | platform: 211 | dependency: transitive 212 | description: 213 | name: platform 214 | url: "https://pub.dartlang.org" 215 | source: hosted 216 | version: "3.0.0" 217 | plugin_platform_interface: 218 | dependency: transitive 219 | description: 220 | name: plugin_platform_interface 221 | url: "https://pub.dartlang.org" 222 | source: hosted 223 | version: "2.0.0" 224 | process: 225 | dependency: transitive 226 | description: 227 | name: process 228 | url: "https://pub.dartlang.org" 229 | source: hosted 230 | version: "4.2.1" 231 | rxdart: 232 | dependency: transitive 233 | description: 234 | name: rxdart 235 | url: "https://pub.dartlang.org" 236 | source: hosted 237 | version: "0.26.0" 238 | sky_engine: 239 | dependency: transitive 240 | description: flutter 241 | source: sdk 242 | version: "0.0.99" 243 | source_span: 244 | dependency: transitive 245 | description: 246 | name: source_span 247 | url: "https://pub.dartlang.org" 248 | source: hosted 249 | version: "1.8.1" 250 | sqflite: 251 | dependency: transitive 252 | description: 253 | name: sqflite 254 | url: "https://pub.dartlang.org" 255 | source: hosted 256 | version: "2.0.0+3" 257 | sqflite_common: 258 | dependency: transitive 259 | description: 260 | name: sqflite_common 261 | url: "https://pub.dartlang.org" 262 | source: hosted 263 | version: "2.0.0+2" 264 | stack_trace: 265 | dependency: transitive 266 | description: 267 | name: stack_trace 268 | url: "https://pub.dartlang.org" 269 | source: hosted 270 | version: "1.10.0" 271 | stream_channel: 272 | dependency: transitive 273 | description: 274 | name: stream_channel 275 | url: "https://pub.dartlang.org" 276 | source: hosted 277 | version: "2.1.0" 278 | string_scanner: 279 | dependency: transitive 280 | description: 281 | name: string_scanner 282 | url: "https://pub.dartlang.org" 283 | source: hosted 284 | version: "1.1.0" 285 | synchronized: 286 | dependency: transitive 287 | description: 288 | name: synchronized 289 | url: "https://pub.dartlang.org" 290 | source: hosted 291 | version: "3.0.0" 292 | term_glyph: 293 | dependency: transitive 294 | description: 295 | name: term_glyph 296 | url: "https://pub.dartlang.org" 297 | source: hosted 298 | version: "1.2.0" 299 | test_api: 300 | dependency: transitive 301 | description: 302 | name: test_api 303 | url: "https://pub.dartlang.org" 304 | source: hosted 305 | version: "0.3.0" 306 | typed_data: 307 | dependency: transitive 308 | description: 309 | name: typed_data 310 | url: "https://pub.dartlang.org" 311 | source: hosted 312 | version: "1.3.0" 313 | uuid: 314 | dependency: transitive 315 | description: 316 | name: uuid 317 | url: "https://pub.dartlang.org" 318 | source: hosted 319 | version: "3.0.4" 320 | vector_math: 321 | dependency: transitive 322 | description: 323 | name: vector_math 324 | url: "https://pub.dartlang.org" 325 | source: hosted 326 | version: "2.1.0" 327 | win32: 328 | dependency: transitive 329 | description: 330 | name: win32 331 | url: "https://pub.dartlang.org" 332 | source: hosted 333 | version: "2.0.5" 334 | xdg_directories: 335 | dependency: transitive 336 | description: 337 | name: xdg_directories 338 | url: "https://pub.dartlang.org" 339 | source: hosted 340 | version: "0.2.0" 341 | xml: 342 | dependency: transitive 343 | description: 344 | name: xml 345 | url: "https://pub.dartlang.org" 346 | source: hosted 347 | version: "5.1.0" 348 | sdks: 349 | dart: ">=2.12.0 <3.0.0" 350 | flutter: ">=1.24.0-10.2.pre" 351 | -------------------------------------------------------------------------------- /image_sequence_animator/example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "3.1.2" 11 | async: 12 | dependency: transitive 13 | description: 14 | name: async 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.6.0" 18 | boolean_selector: 19 | dependency: transitive 20 | description: 21 | name: boolean_selector 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.1.0" 25 | cached_network_image: 26 | dependency: transitive 27 | description: 28 | name: cached_network_image 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "3.0.0" 32 | characters: 33 | dependency: transitive 34 | description: 35 | name: characters 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | charcode: 40 | dependency: transitive 41 | description: 42 | name: charcode 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.2.0" 46 | clock: 47 | dependency: transitive 48 | description: 49 | name: clock 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.1.0" 53 | collection: 54 | dependency: transitive 55 | description: 56 | name: collection 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.15.0" 60 | crypto: 61 | dependency: transitive 62 | description: 63 | name: crypto 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "3.0.1" 67 | fake_async: 68 | dependency: transitive 69 | description: 70 | name: fake_async 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.2.0" 74 | ffi: 75 | dependency: transitive 76 | description: 77 | name: ffi 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "1.0.0" 81 | file: 82 | dependency: transitive 83 | description: 84 | name: file 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "6.1.0" 88 | flutter: 89 | dependency: "direct main" 90 | description: flutter 91 | source: sdk 92 | version: "0.0.0" 93 | flutter_blurhash: 94 | dependency: transitive 95 | description: 96 | name: flutter_blurhash 97 | url: "https://pub.dartlang.org" 98 | source: hosted 99 | version: "0.6.0" 100 | flutter_cache_manager: 101 | dependency: transitive 102 | description: 103 | name: flutter_cache_manager 104 | url: "https://pub.dartlang.org" 105 | source: hosted 106 | version: "3.0.1" 107 | flutter_test: 108 | dependency: "direct dev" 109 | description: flutter 110 | source: sdk 111 | version: "0.0.0" 112 | http: 113 | dependency: transitive 114 | description: 115 | name: http 116 | url: "https://pub.dartlang.org" 117 | source: hosted 118 | version: "0.13.3" 119 | http_parser: 120 | dependency: transitive 121 | description: 122 | name: http_parser 123 | url: "https://pub.dartlang.org" 124 | source: hosted 125 | version: "4.0.0" 126 | image: 127 | dependency: transitive 128 | description: 129 | name: image 130 | url: "https://pub.dartlang.org" 131 | source: hosted 132 | version: "3.0.2" 133 | image_sequence_animator: 134 | dependency: "direct main" 135 | description: 136 | path: ".." 137 | relative: true 138 | source: path 139 | version: "2.0.0" 140 | matcher: 141 | dependency: transitive 142 | description: 143 | name: matcher 144 | url: "https://pub.dartlang.org" 145 | source: hosted 146 | version: "0.12.10" 147 | meta: 148 | dependency: transitive 149 | description: 150 | name: meta 151 | url: "https://pub.dartlang.org" 152 | source: hosted 153 | version: "1.3.0" 154 | octo_image: 155 | dependency: transitive 156 | description: 157 | name: octo_image 158 | url: "https://pub.dartlang.org" 159 | source: hosted 160 | version: "1.0.0+1" 161 | path: 162 | dependency: transitive 163 | description: 164 | name: path 165 | url: "https://pub.dartlang.org" 166 | source: hosted 167 | version: "1.8.0" 168 | path_provider: 169 | dependency: transitive 170 | description: 171 | name: path_provider 172 | url: "https://pub.dartlang.org" 173 | source: hosted 174 | version: "2.0.1" 175 | path_provider_linux: 176 | dependency: transitive 177 | description: 178 | name: path_provider_linux 179 | url: "https://pub.dartlang.org" 180 | source: hosted 181 | version: "2.0.0" 182 | path_provider_macos: 183 | dependency: transitive 184 | description: 185 | name: path_provider_macos 186 | url: "https://pub.dartlang.org" 187 | source: hosted 188 | version: "2.0.0" 189 | path_provider_platform_interface: 190 | dependency: transitive 191 | description: 192 | name: path_provider_platform_interface 193 | url: "https://pub.dartlang.org" 194 | source: hosted 195 | version: "2.0.1" 196 | path_provider_windows: 197 | dependency: transitive 198 | description: 199 | name: path_provider_windows 200 | url: "https://pub.dartlang.org" 201 | source: hosted 202 | version: "2.0.1" 203 | pedantic: 204 | dependency: transitive 205 | description: 206 | name: pedantic 207 | url: "https://pub.dartlang.org" 208 | source: hosted 209 | version: "1.11.0" 210 | petitparser: 211 | dependency: transitive 212 | description: 213 | name: petitparser 214 | url: "https://pub.dartlang.org" 215 | source: hosted 216 | version: "4.1.0" 217 | platform: 218 | dependency: transitive 219 | description: 220 | name: platform 221 | url: "https://pub.dartlang.org" 222 | source: hosted 223 | version: "3.0.0" 224 | plugin_platform_interface: 225 | dependency: transitive 226 | description: 227 | name: plugin_platform_interface 228 | url: "https://pub.dartlang.org" 229 | source: hosted 230 | version: "2.0.0" 231 | process: 232 | dependency: transitive 233 | description: 234 | name: process 235 | url: "https://pub.dartlang.org" 236 | source: hosted 237 | version: "4.2.1" 238 | rxdart: 239 | dependency: transitive 240 | description: 241 | name: rxdart 242 | url: "https://pub.dartlang.org" 243 | source: hosted 244 | version: "0.26.0" 245 | sky_engine: 246 | dependency: transitive 247 | description: flutter 248 | source: sdk 249 | version: "0.0.99" 250 | source_span: 251 | dependency: transitive 252 | description: 253 | name: source_span 254 | url: "https://pub.dartlang.org" 255 | source: hosted 256 | version: "1.8.1" 257 | spring_button: 258 | dependency: "direct main" 259 | description: 260 | name: spring_button 261 | url: "https://pub.dartlang.org" 262 | source: hosted 263 | version: "2.0.0" 264 | sqflite: 265 | dependency: transitive 266 | description: 267 | name: sqflite 268 | url: "https://pub.dartlang.org" 269 | source: hosted 270 | version: "2.0.0+3" 271 | sqflite_common: 272 | dependency: transitive 273 | description: 274 | name: sqflite_common 275 | url: "https://pub.dartlang.org" 276 | source: hosted 277 | version: "2.0.0+2" 278 | stack_trace: 279 | dependency: transitive 280 | description: 281 | name: stack_trace 282 | url: "https://pub.dartlang.org" 283 | source: hosted 284 | version: "1.10.0" 285 | stream_channel: 286 | dependency: transitive 287 | description: 288 | name: stream_channel 289 | url: "https://pub.dartlang.org" 290 | source: hosted 291 | version: "2.1.0" 292 | string_scanner: 293 | dependency: transitive 294 | description: 295 | name: string_scanner 296 | url: "https://pub.dartlang.org" 297 | source: hosted 298 | version: "1.1.0" 299 | synchronized: 300 | dependency: transitive 301 | description: 302 | name: synchronized 303 | url: "https://pub.dartlang.org" 304 | source: hosted 305 | version: "3.0.0" 306 | term_glyph: 307 | dependency: transitive 308 | description: 309 | name: term_glyph 310 | url: "https://pub.dartlang.org" 311 | source: hosted 312 | version: "1.2.0" 313 | test_api: 314 | dependency: transitive 315 | description: 316 | name: test_api 317 | url: "https://pub.dartlang.org" 318 | source: hosted 319 | version: "0.3.0" 320 | typed_data: 321 | dependency: transitive 322 | description: 323 | name: typed_data 324 | url: "https://pub.dartlang.org" 325 | source: hosted 326 | version: "1.3.0" 327 | uuid: 328 | dependency: transitive 329 | description: 330 | name: uuid 331 | url: "https://pub.dartlang.org" 332 | source: hosted 333 | version: "3.0.4" 334 | vector_math: 335 | dependency: transitive 336 | description: 337 | name: vector_math 338 | url: "https://pub.dartlang.org" 339 | source: hosted 340 | version: "2.1.0" 341 | win32: 342 | dependency: transitive 343 | description: 344 | name: win32 345 | url: "https://pub.dartlang.org" 346 | source: hosted 347 | version: "2.0.5" 348 | xdg_directories: 349 | dependency: transitive 350 | description: 351 | name: xdg_directories 352 | url: "https://pub.dartlang.org" 353 | source: hosted 354 | version: "0.2.0" 355 | xml: 356 | dependency: transitive 357 | description: 358 | name: xml 359 | url: "https://pub.dartlang.org" 360 | source: hosted 361 | version: "5.1.0" 362 | sdks: 363 | dart: ">=2.12.0 <3.0.0" 364 | flutter: ">=1.24.0-10.2.pre" 365 | -------------------------------------------------------------------------------- /image_sequence_animator/example/lib/main.dart: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // © Cosmos Software | Ali Yigit Bireroglu / 3 | // All material used in the making of this code, project, program, application, software et cetera (the "Intellectual Property") / 4 | // belongs completely and solely to Ali Yigit Bireroglu. This includes but is not limited to the source code, the multimedia and / 5 | // other asset files. If you were granted this Intellectual Property for personal use, you are obligated to include this copyright / 6 | // text at all times. / 7 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | //@formatter:off 9 | 10 | import 'package:flutter/cupertino.dart'; 11 | import 'package:flutter/material.dart'; 12 | 13 | import 'package:spring_button/spring_button.dart'; 14 | import 'package:image_sequence_animator/image_sequence_animator.dart'; 15 | 16 | void main() => runApp(MyApp()); 17 | 18 | class MyApp extends StatelessWidget { 19 | @override 20 | Widget build(BuildContext context) { 21 | return MaterialApp( 22 | title: 'Image Sequence Animator Demo', 23 | theme: ThemeData(primarySwatch: Colors.blue), 24 | home: MyHomePage(title: 'Image Sequence Animator Demo'), 25 | ); 26 | } 27 | } 28 | 29 | class MyHomePage extends StatefulWidget { 30 | MyHomePage({Key? key, this.title}) : super(key: key); 31 | 32 | final String? title; 33 | 34 | @override 35 | _MyHomePageState createState() => _MyHomePageState(); 36 | } 37 | 38 | class _MyHomePageState extends State { 39 | ImageSequenceAnimatorState? get imageSequenceAnimator => isOnline ? onlineImageSequenceAnimator : offlineImageSequenceAnimator; 40 | ImageSequenceAnimatorState? offlineImageSequenceAnimator; 41 | ImageSequenceAnimatorState? onlineImageSequenceAnimator; 42 | 43 | bool isOnline = false; 44 | bool wasPlaying = false; 45 | 46 | Color color1 = Colors.greenAccent; 47 | Color color2 = Colors.indigo; 48 | 49 | String onlineOfflineText = "Use Online"; 50 | String loopText = "Start Loop"; 51 | String boomerangText = "Start Boomerang"; 52 | 53 | bool _useFullPaths = false; 54 | List? _fullPathsOffline; 55 | List? _fullPathsOnline; 56 | 57 | void onOfflineReadyToPlay(ImageSequenceAnimatorState _imageSequenceAnimator) { 58 | offlineImageSequenceAnimator = _imageSequenceAnimator; 59 | } 60 | 61 | void onOfflinePlaying(ImageSequenceAnimatorState _imageSequenceAnimator) { 62 | setState(() {}); 63 | } 64 | 65 | void onOnlineReadyToPlay(ImageSequenceAnimatorState _imageSequenceAnimator) { 66 | onlineImageSequenceAnimator = _imageSequenceAnimator; 67 | } 68 | 69 | void onOnlinePlaying(ImageSequenceAnimatorState _imageSequenceAnimator) { 70 | setState(() {}); 71 | } 72 | 73 | Widget row(String text, Color color) { 74 | return Padding( 75 | padding: EdgeInsets.all(3.125), 76 | child: Container( 77 | decoration: BoxDecoration( 78 | color: color, 79 | borderRadius: const BorderRadius.all(const Radius.circular(10.0)), 80 | ), 81 | child: Center( 82 | child: Text( 83 | text, 84 | style: const TextStyle( 85 | color: Colors.white, 86 | fontWeight: FontWeight.bold, 87 | fontSize: 12.5, 88 | ), 89 | ), 90 | ), 91 | ), 92 | ); 93 | } 94 | 95 | @override 96 | Widget build(BuildContext context) { 97 | if (_fullPathsOffline == null && _fullPathsOnline == null) { 98 | _fullPathsOffline = []; 99 | _fullPathsOnline = []; 100 | for (int i = 0; i < 60; i++) { 101 | String _value = i.toString(); 102 | while (_value.length < 5) _value = "0" + _value; 103 | _fullPathsOffline!.add("assets/ImageSequence/Frame_" + _value + ".png"); 104 | _fullPathsOnline!.add("https://www.cosmossoftware.coffee/AppData/ImageSequenceAnimator/ImageSequence/Frame_" + _value + ".png"); 105 | } 106 | } 107 | return Scaffold( 108 | appBar: AppBar(title: Text(widget.title!)), 109 | body: Column( 110 | children: [ 111 | Expanded( 112 | flex: 4, 113 | child: Padding( 114 | padding: EdgeInsets.all(25), 115 | child: isOnline 116 | ? ImageSequenceAnimator( 117 | "https://www.cosmossoftware.coffee/AppData/ImageSequenceAnimator/ImageSequence", 118 | "Frame_", 119 | 0, 120 | 5, 121 | "png", 122 | 60, 123 | key: Key("online"), 124 | fullPaths: _useFullPaths ? _fullPathsOffline : null, 125 | isAutoPlay: true, 126 | isOnline: true, 127 | // waitUntilCacheIsComplete: true, 128 | // cacheProgressIndicatorBuilder: (context, progress) { 129 | // return CircularProgressIndicator( 130 | // value: progress, 131 | // backgroundColor: color1, 132 | // ); 133 | // }, 134 | color: color1, 135 | onReadyToPlay: onOnlineReadyToPlay, 136 | onPlaying: onOnlinePlaying, 137 | ) 138 | : ImageSequenceAnimator( 139 | "assets/ImageSequence", 140 | "Frame_", 141 | 0, 142 | 5, 143 | "png", 144 | 60, 145 | key: Key("offline"), 146 | fullPaths: _useFullPaths ? _fullPathsOffline : null, 147 | color: color1, 148 | onReadyToPlay: onOfflineReadyToPlay, 149 | onPlaying: onOfflinePlaying, 150 | ), 151 | ), 152 | ), 153 | Expanded( 154 | child: Row( 155 | children: [ 156 | Expanded( 157 | flex: 4, 158 | child: CupertinoSlider( 159 | value: imageSequenceAnimator == null ? 0.0 : imageSequenceAnimator!.currentProgress, 160 | min: 0.0, 161 | max: imageSequenceAnimator == null ? 100.0 : imageSequenceAnimator!.totalProgress, 162 | onChangeStart: (double value) { 163 | wasPlaying = imageSequenceAnimator!.isPlaying; 164 | imageSequenceAnimator!.pause(); 165 | }, 166 | onChanged: (double value) { 167 | imageSequenceAnimator!.skip(value); 168 | }, 169 | onChangeEnd: (double value) { 170 | if (wasPlaying) imageSequenceAnimator!.play(); 171 | }, 172 | ), 173 | ), 174 | Expanded( 175 | child: Center( 176 | child: Text( 177 | imageSequenceAnimator == null ? "0.0" : ((imageSequenceAnimator!.currentTime.floor()).toString() + "/" + (imageSequenceAnimator!.totalTime.floor()).toString()), 178 | textAlign: TextAlign.center, 179 | ), 180 | ), 181 | ), 182 | ], 183 | ), 184 | ), 185 | Expanded( 186 | child: Row( 187 | children: [ 188 | Expanded( 189 | child: SpringButton( 190 | SpringButtonType.OnlyScale, 191 | row( 192 | loopText, 193 | Colors.cyan, 194 | ), 195 | useCache: false, 196 | onTap: () { 197 | setState(() { 198 | loopText = imageSequenceAnimator!.isLooping ? "Start Loop" : "Stop Loop"; 199 | boomerangText = "Start Boomerang"; 200 | imageSequenceAnimator!.setIsLooping(!imageSequenceAnimator!.isLooping); 201 | }); 202 | }, 203 | ), 204 | ), 205 | Expanded( 206 | child: SpringButton( 207 | SpringButtonType.OnlyScale, 208 | row( 209 | boomerangText, 210 | Colors.deepPurpleAccent, 211 | ), 212 | useCache: false, 213 | onTap: () { 214 | setState(() { 215 | loopText = "Start Loop"; 216 | boomerangText = imageSequenceAnimator!.isBoomerang ? "Start Boomerang" : "Stop Boomerang"; 217 | imageSequenceAnimator!.setIsBoomerang(!imageSequenceAnimator!.isBoomerang); 218 | }); 219 | }, 220 | ), 221 | ), 222 | ], 223 | ), 224 | ), 225 | Expanded( 226 | child: Row( 227 | children: [ 228 | Expanded( 229 | child: SpringButton( 230 | SpringButtonType.OnlyScale, 231 | row( 232 | onlineOfflineText, 233 | Colors.orangeAccent, 234 | ), 235 | useCache: false, 236 | onTap: () { 237 | setState(() { 238 | imageSequenceAnimator!.stop(); 239 | isOnline = !isOnline; 240 | loopText = imageSequenceAnimator == null || imageSequenceAnimator!.isLooping ? "Start Loop" : "Stop Loop"; 241 | boomerangText = imageSequenceAnimator == null || imageSequenceAnimator!.isBoomerang ? "Start Boomerang" : "Stop Boomerang"; 242 | onlineOfflineText = isOnline ? "Use Offline" : "Use Onfline"; 243 | }); 244 | }, 245 | ), 246 | ), 247 | Expanded( 248 | child: SpringButton( 249 | SpringButtonType.OnlyScale, 250 | row( 251 | "Change Colour", 252 | Colors.redAccent, 253 | ), 254 | onTap: () { 255 | imageSequenceAnimator!.changeColor(imageSequenceAnimator!.color == color1 ? color2 : color1); 256 | }, 257 | ), 258 | ), 259 | ], 260 | ), 261 | ), 262 | Expanded( 263 | child: Row( 264 | children: [ 265 | Expanded( 266 | child: SpringButton( 267 | SpringButtonType.OnlyScale, 268 | row( 269 | "Play/Pause", 270 | Colors.deepOrangeAccent, 271 | ), 272 | onTap: () { 273 | setState(() { 274 | imageSequenceAnimator!.isPlaying ? imageSequenceAnimator!.pause() : imageSequenceAnimator!.play(); 275 | }); 276 | }, 277 | ), 278 | ), 279 | Expanded( 280 | child: SpringButton( 281 | SpringButtonType.OnlyScale, 282 | row( 283 | "Stop", 284 | Colors.green, 285 | ), 286 | onTap: () { 287 | imageSequenceAnimator!.stop(); 288 | }, 289 | ), 290 | ), 291 | ], 292 | ), 293 | ), 294 | Expanded( 295 | child: Row( 296 | children: [ 297 | Expanded( 298 | child: SpringButton( 299 | SpringButtonType.OnlyScale, 300 | row( 301 | "Restart", 302 | Colors.teal, 303 | ), 304 | onTap: () { 305 | imageSequenceAnimator!.restart(); 306 | }, 307 | ), 308 | ), 309 | Expanded( 310 | child: SpringButton( 311 | SpringButtonType.OnlyScale, 312 | row( 313 | "Rewind", 314 | Colors.indigoAccent, 315 | ), 316 | onTap: () { 317 | imageSequenceAnimator!.rewind(); 318 | }, 319 | ), 320 | ), 321 | ], 322 | ), 323 | ), 324 | ], 325 | ), 326 | ); 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /image_sequence_animator/lib/image_sequence_animator.dart: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // © Cosmos Software | Ali Yigit Bireroglu / 3 | // All material used in the making of this code, project, program, application, software et cetera (the "Intellectual Property") / 4 | // belongs completely and solely to Ali Yigit Bireroglu. This includes but is not limited to the source code, the multimedia and / 5 | // other asset files. If you were granted this Intellectual Property for personal use, you are obligated to include this copyright / 6 | // text at all times. / 7 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | //@formatter:off 9 | 10 | import 'dart:async'; 11 | 12 | import 'package:flutter/material.dart'; 13 | 14 | import 'package:cached_network_image/cached_network_image.dart'; 15 | 16 | typedef CacheProgressIndicatorBuilder = Widget Function(BuildContext context, double progress); 17 | typedef ImageSequenceProcessCallback = void Function(ImageSequenceAnimatorState _imageSequenceAnimator); 18 | 19 | class ImageSequenceAnimator extends StatefulWidget { 20 | ///The directory of your image sequence. 21 | ///If [isOnline] is set to false and, for example, if you add your image sequence to 22 | ///'assets/ImageSequences/MyImageSequence' 23 | ///then the [folderName] should be 'assets/ImageSequences/MyImageSequence'. 24 | ///If [isOnline] is set to true and, for example, if you add your image sequence to 25 | ///'https://www.domain.com/ImageSequences/MyImageSequence' 26 | ///then the [folderName] should be 'https://www.domain.com/ImageSequences/MyImageSequence'. 27 | ///[folderName] should be the same for all the images in your image sequence. 28 | final String folderName; 29 | 30 | ///The file name for each image in your image sequence excluding the suffix. For example, if the images in your image sequence are named as 31 | ///'Frame_00000.png', 'Frame_00001.png', 'Frame_00002.png', 'Frame_00003.png' ... 32 | ///then the [fileName] should be 'Frame_'. This should be the same for all the images in your image sequence. 33 | final String fileName; 34 | 35 | ///The suffix for the first image in your image sequence. For example, if the first image in your image sequence is named as 36 | ///'Frame_00001.png' 37 | ///then [suffixStart] should be 1. 38 | final int suffixStart; 39 | 40 | ///The suffix length for each image in your image sequence. Most software such as Adobe After Effects export image sequences with a suffix. For 41 | ///example, if the images in your image sequence are named as 42 | ///'Frame_00000.png', 'Frame_00001.png', 'Frame_00002.png', 'Frame_00003.png' ... 43 | ///then the [suffixCount] should be 5. This should be the same for all the images in your image sequence. 44 | final int suffixCount; 45 | 46 | ///The file format for each image in your image sequence. For example, if the images in your image sequence are named as 47 | ///'Frame_00000.png', 'Frame_00001.png', 'Frame_00002.png', 'Frame_00003.png' ... 48 | ///then the [fileFormat] should be 'png'. This should be the same for all the images in your image sequence. 49 | final String fileFormat; 50 | 51 | ///The total number of images in your image sequence. 52 | final double frameCount; 53 | 54 | ///Use this value if you would like to specify a list of endpoints for the frames in your image sequence animator. If set, values for [folderName], 55 | ///[fileName], [suffixStart], [suffixCount], [fileFormat] and [frameCount] will be ignored. 56 | final List? fullPaths; 57 | 58 | ///The FPS for your image sequence. For example, if your [frameCount] is 60 and the animation is meant to run in 1 second, then your [fps] should 59 | /// be 60. 60 | final double fps; 61 | 62 | ///Use this value to determine whether your image sequence should loop or not. This will override [isBoomerang] if both are set to true. 63 | final bool isLooping; 64 | 65 | ///Use this value to determine whether your image sequence should boomerang or not. 66 | final bool isBoomerang; 67 | 68 | ///Use this value to determine whether your image sequence should start playing immediately or not. 69 | final bool isAutoPlay; 70 | 71 | ///Use this value to determine the color for your image sequence. 72 | final Color? color; 73 | 74 | ///Set this value to true if your [folderName] is an online path. 75 | final bool isOnline; 76 | 77 | ///Set this value to true if you want the [ImageSequenceAnimator] to wait until the entire image sequence is cached. Otherwise, the [ImageSequenceAnimator] 78 | ///will invoke [onReadyToPlay] and start playing if [isAutoPlay] is set to true when it approximates that the remaining caching can be completed without 79 | ///causing stutters. This value is only used if [isOnline] is set to true. 80 | final bool waitUntilCacheIsComplete; 81 | 82 | ///Use this function to display a widget until the [ImageSequenceAnimator] is ready to be played. This value is only used if [isOnline] is set to true. 83 | final CacheProgressIndicatorBuilder? cacheProgressIndicatorBuilder; 84 | 85 | ///The callback for when the [ImageSequenceAnimator] is ready to start playing. 86 | final ImageSequenceProcessCallback? onReadyToPlay; 87 | 88 | ///The callback for when the [ImageSequenceAnimator] starts playing. 89 | final ImageSequenceProcessCallback? onStartPlaying; 90 | 91 | ///The callback for when the [ImageSequenceAnimator] is playing. This callback is continuously through the entire process. 92 | final ImageSequenceProcessCallback? onPlaying; 93 | 94 | ///The callback for when the [ImageSequenceAnimator] finishes playing. 95 | final ImageSequenceProcessCallback? onFinishPlaying; 96 | 97 | ///The image fit 98 | final BoxFit? fit; 99 | 100 | const ImageSequenceAnimator( 101 | this.folderName, 102 | this.fileName, 103 | this.suffixStart, 104 | this.suffixCount, 105 | this.fileFormat, 106 | this.frameCount, { 107 | Key? key, 108 | this.fullPaths, 109 | this.fps: 60, 110 | this.isLooping: false, 111 | this.isBoomerang: false, 112 | this.isAutoPlay: true, 113 | this.color, 114 | this.isOnline: false, 115 | this.waitUntilCacheIsComplete: false, 116 | this.cacheProgressIndicatorBuilder, 117 | this.onReadyToPlay, 118 | this.onStartPlaying, 119 | this.onPlaying, 120 | this.onFinishPlaying, 121 | this.fit, 122 | }) : super(key: key); 123 | 124 | @override 125 | ImageSequenceAnimatorState createState() { 126 | return ImageSequenceAnimatorState( 127 | folderName, 128 | fileName, 129 | fileFormat, 130 | isLooping, 131 | isBoomerang, 132 | color, 133 | ); 134 | } 135 | } 136 | 137 | class ImageSequenceAnimatorState extends State with SingleTickerProviderStateMixin { 138 | AnimationController? _animationController; 139 | final ValueNotifier _changeNotifier = ValueNotifier(0); 140 | 141 | String _folderName; 142 | String _fileName; 143 | String _fileFormat; 144 | double get _frameCount => _useFullPaths ? widget.fullPaths!.length * 1.0 : widget.frameCount; 145 | bool get _useFullPaths => widget.fullPaths != null && widget.fullPaths!.isNotEmpty; 146 | 147 | ///Use this value to check if this [ImageSequenceAnimator] is currently looping. 148 | bool get isLooping => _isLooping; 149 | bool _isLooping; 150 | 151 | ///Use this value to check if this [ImageSequenceAnimator] is currently boomeranging. 152 | bool get isBoomerang => _isBoomerang; 153 | bool _isBoomerang; 154 | 155 | ///Use this value to check the current color of this [ImageSequenceAnimator]. 156 | Color? color; 157 | 158 | bool _isReadyToPlay = false; 159 | bool _isCacheComplete = false; 160 | bool _colorChanged = false; 161 | 162 | int _previousFrame = 0; 163 | int get _newFrame => _animationController!.value.floor(); 164 | int _previousCacheFrame = 0; 165 | int? _newCacheFrame; 166 | 167 | Widget? _currentOfflineFrame; 168 | Widget? _currentCachedOnlineFrame; 169 | Widget? _currentDisplayedOnlineFrame; 170 | 171 | Timer? _cacheTimer; 172 | DateTime? _cacheStartDateTime; 173 | int get _cacheMillisProgressed => DateTime.now().difference(_cacheStartDateTime!).inMilliseconds; 174 | double get _cacheMillisRemaining => _cacheMillisProgressed.toDouble() / _previousCacheFrame.toDouble() * (_frameCount - _previousCacheFrame).toDouble(); 175 | double get _cacheMillisTotal => _cacheMillisProgressed + _cacheMillisRemaining; 176 | 177 | bool get isPlaying => _animationController != null && _animationController!.isAnimating; 178 | int get _fpsInMilliseconds => (1.0 / widget.fps * 1000.0).floor(); 179 | 180 | ///Use this value to get the current time of the animation in frames. 181 | double get currentProgress => _animationController == null ? 0.0 : _animationController!.value; 182 | 183 | ///Use this value to get the total time of the animation in frames. 184 | double get totalProgress => _animationController == null ? 0.0 : _animationController!.upperBound; 185 | 186 | ///Use this value to get the current time of the animation in milliseconds. 187 | double get currentTime => currentProgress * _fpsInMilliseconds; 188 | 189 | ///Use this value to get the total time of the animation in milliseconds. 190 | double get totalTime => totalProgress * _fpsInMilliseconds; 191 | 192 | ImageSequenceAnimatorState( 193 | this._folderName, 194 | this._fileName, 195 | this._fileFormat, 196 | this._isLooping, 197 | this._isBoomerang, 198 | this.color, 199 | ); 200 | 201 | void animationListener() { 202 | _changeNotifier.value++; 203 | 204 | if (widget.onPlaying != null) widget.onPlaying!(this); 205 | } 206 | 207 | void animationStatusListener(AnimationStatus animationStatus) { 208 | switch (animationStatus) { 209 | case AnimationStatus.completed: 210 | if (widget.onFinishPlaying != null) widget.onFinishPlaying!(this); 211 | 212 | if (isLooping) restart(); 213 | if (isBoomerang) rewind(); 214 | break; 215 | case AnimationStatus.dismissed: 216 | if (widget.onFinishPlaying != null) widget.onFinishPlaying!(this); 217 | 218 | if (isLooping || isBoomerang) play(); 219 | break; 220 | default: 221 | break; 222 | } 223 | } 224 | 225 | @override 226 | void initState() { 227 | super.initState(); 228 | 229 | _animationController = AnimationController( 230 | vsync: this, 231 | lowerBound: 0, 232 | upperBound: _frameCount, 233 | duration: Duration(milliseconds: _frameCount.ceil() * _fpsInMilliseconds), 234 | ) 235 | ..addListener(animationListener) 236 | ..addStatusListener(animationStatusListener); 237 | 238 | if (isLooping) _isBoomerang = false; 239 | 240 | if (_folderName.endsWith("/")) _folderName = _folderName.substring(0, _folderName.indexOf(("/"))); 241 | if (_fileFormat.startsWith(".")) _fileFormat = _fileFormat.substring(1); 242 | 243 | if (!widget.isOnline) { 244 | _isReadyToPlay = true; 245 | if (widget.onReadyToPlay != null) widget.onReadyToPlay!(this); 246 | if (widget.isAutoPlay) play(); 247 | } 248 | } 249 | 250 | @override 251 | void dispose() { 252 | _reset(); 253 | 254 | _animationController!.removeListener(animationListener); 255 | _animationController!.removeStatusListener(animationStatusListener); 256 | _animationController!.dispose(); 257 | 258 | super.dispose(); 259 | } 260 | 261 | ///Use this function to set the value for [ImageSequenceAnimatorState.isLooping] at runtime. 262 | void setIsLooping(bool isLooping) { 263 | if (!_isReadyToPlay) return; 264 | 265 | this._isLooping = isLooping; 266 | if (this.isLooping) { 267 | _isBoomerang = false; 268 | if (!_animationController!.isAnimating) restart(); 269 | } 270 | } 271 | 272 | ///Use this function to set the value for [ImageSequenceAnimatorState.isBoomerang] at runtime. 273 | void setIsBoomerang(bool isBoomerang) { 274 | if (!_isReadyToPlay) return; 275 | 276 | this._isBoomerang = isBoomerang; 277 | if (this.isBoomerang) { 278 | _isLooping = false; 279 | if (!_animationController!.isAnimating) restart(); 280 | } 281 | } 282 | 283 | ///Use this function to set the value for [ImageSequenceAnimatorState.color] at runtime. 284 | void changeColor(Color color) { 285 | if (!_isReadyToPlay) return; 286 | 287 | this.color = color; 288 | _colorChanged = true; 289 | _changeNotifier.value++; 290 | } 291 | 292 | ///Use this function to play this [ImageSequenceAnimator]. 293 | void play({double from: -1.0}) { 294 | if (!_isReadyToPlay) return; 295 | 296 | if (!_animationController!.isAnimating && widget.onStartPlaying != null) widget.onStartPlaying!(this); 297 | 298 | if (from == -1.0) 299 | _animationController!.forward(); 300 | else 301 | _animationController!.forward(from: from); 302 | } 303 | 304 | ///Use this function to rewind this [ImageSequenceAnimator]. 305 | void rewind({double from: -1.0}) { 306 | if (!_isReadyToPlay) return; 307 | 308 | if (!_animationController!.isAnimating && widget.onStartPlaying != null) widget.onStartPlaying!(this); 309 | 310 | if (from == -1.0) 311 | _animationController!.reverse(); 312 | else 313 | _animationController!.reverse(from: from); 314 | } 315 | 316 | ///Use this function to pause this [ImageSequenceAnimator]. 317 | void pause() { 318 | if (!_isReadyToPlay) return; 319 | 320 | _animationController!.stop(); 321 | } 322 | 323 | ///Only use either value or percentage. 324 | void skip(double value, {double percentage: -1.0}) { 325 | if (!_isReadyToPlay) return; 326 | 327 | if (percentage != -1.0) 328 | _animationController!.value = totalTime * percentage; 329 | else 330 | _animationController!.value = value; 331 | } 332 | 333 | ///Use this function to restart this [ImageSequenceAnimator]. 334 | void restart() { 335 | if (!_isReadyToPlay) return; 336 | 337 | stop(); 338 | play(); 339 | } 340 | 341 | ///Use this function to stop this [ImageSequenceAnimator]. 342 | void stop() { 343 | if (!_isReadyToPlay) return; 344 | 345 | _reset(); 346 | } 347 | 348 | void _reset() { 349 | _animationController!.value = 0; 350 | _animationController!.stop(canceled: true); 351 | _previousFrame = 0; 352 | _currentOfflineFrame = null; 353 | } 354 | 355 | void _cache() { 356 | int _value = _previousCacheFrame; 357 | _value++; 358 | 359 | if (_value < _frameCount) { 360 | _previousCacheFrame = _value; 361 | _changeNotifier.value++; 362 | } else 363 | _isCacheComplete = true; 364 | 365 | if (!_isReadyToPlay) { 366 | if ((widget.waitUntilCacheIsComplete && _isCacheComplete) || (!widget.waitUntilCacheIsComplete && _cacheMillisRemaining * 0.85 < totalTime)) { 367 | _isReadyToPlay = true; 368 | if (widget.onReadyToPlay != null) widget.onReadyToPlay!(this); 369 | if (widget.isAutoPlay) play(from: 0.0); 370 | } 371 | } 372 | } 373 | 374 | String _getSuffix(String value) { 375 | while (value.length < widget.suffixCount) value = "0" + value; 376 | return value; 377 | } 378 | 379 | String _getDirectory() { 380 | if (_useFullPaths) { 381 | return widget.fullPaths![_previousFrame]; 382 | } 383 | return _folderName + "/" + _fileName + _getSuffix((widget.suffixStart + _previousFrame).toString()) + "." + _fileFormat; 384 | } 385 | 386 | String _getCacheDirectory() { 387 | if (_useFullPaths) { 388 | return widget.fullPaths![_previousCacheFrame]; 389 | } 390 | return _folderName + "/" + _fileName + _getSuffix((widget.suffixStart + _previousCacheFrame).toString()) + "." + _fileFormat; 391 | } 392 | 393 | @override 394 | Widget build(BuildContext context) { 395 | if (!widget.isOnline) 396 | return ValueListenableBuilder( 397 | builder: (BuildContext context, int change, Widget? cachedChild) { 398 | if (_currentOfflineFrame == null || _animationController!.value.floor() != _previousFrame || _colorChanged) { 399 | _colorChanged = false; 400 | _previousFrame = _animationController!.value.floor(); 401 | if (_previousFrame < _frameCount) 402 | _currentOfflineFrame = Image.asset( 403 | _getDirectory(), 404 | color: color, 405 | gaplessPlayback: true, 406 | fit: widget.fit, 407 | ); 408 | } 409 | 410 | return _currentOfflineFrame!; 411 | }, 412 | valueListenable: _changeNotifier, 413 | ); 414 | else 415 | return ValueListenableBuilder( 416 | builder: (BuildContext context, int change, Widget? cachedChild) { 417 | if (!_isCacheComplete) { 418 | if (_currentCachedOnlineFrame == null || _newCacheFrame != _previousCacheFrame) { 419 | _newCacheFrame = _previousCacheFrame; 420 | if (_cacheStartDateTime == null) _cacheStartDateTime = DateTime.now(); 421 | _currentCachedOnlineFrame = CachedNetworkImage( 422 | imageUrl: _getCacheDirectory(), 423 | progressIndicatorBuilder: (context, url, downloadProgress) { 424 | if (downloadProgress.progress == null) { 425 | _cacheTimer?.cancel(); 426 | _cacheTimer = Timer(const Duration(milliseconds: 25), () => _cache()); 427 | } else { 428 | _cacheTimer?.cancel(); 429 | if (downloadProgress.progress == 1.0) _cache(); 430 | } 431 | if (!_isReadyToPlay && widget.cacheProgressIndicatorBuilder != null) 432 | return widget.cacheProgressIndicatorBuilder!(context, 1.0 - _cacheMillisRemaining / _cacheMillisTotal); 433 | else 434 | return Container(); 435 | }, 436 | color: Colors.transparent, 437 | fit: widget.fit, 438 | ); 439 | } 440 | } else 441 | _currentCachedOnlineFrame = Container(); 442 | if (_isReadyToPlay) { 443 | if (_currentDisplayedOnlineFrame == null || _newFrame != _previousFrame || _colorChanged) { 444 | _colorChanged = false; 445 | _previousFrame = _animationController!.value.floor(); 446 | if (_previousFrame < _frameCount) 447 | _currentDisplayedOnlineFrame = CachedNetworkImage( 448 | imageUrl: _getDirectory(), 449 | color: color, 450 | useOldImageOnUrlChange: _isCacheComplete, 451 | fadeOutDuration: const Duration(milliseconds: 0), 452 | fadeInDuration: const Duration(milliseconds: 0), 453 | fit: widget.fit, 454 | ); 455 | } 456 | } else 457 | _currentDisplayedOnlineFrame = Container(); 458 | 459 | return Stack( 460 | alignment: Alignment.center, 461 | children: [ 462 | _currentCachedOnlineFrame!, 463 | _currentDisplayedOnlineFrame!, 464 | ], 465 | ); 466 | }, 467 | valueListenable: _changeNotifier, 468 | ); 469 | } 470 | } 471 | --------------------------------------------------------------------------------