Compare commits
7 Commits
v0.8.0-nul
...
xha/tests
Author | SHA1 | Date | |
---|---|---|---|
a0b9572315 | |||
9471029b0a | |||
a8f853437b | |||
a570e3f580 | |||
9584834956 | |||
d0edd1b3ee | |||
6831f475d4 |
30
.github/workflows/analyze-and-test.yaml
vendored
@ -6,11 +6,11 @@ on:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
analyze_and_test:
|
||||
analyze:
|
||||
name: Flutter analyze
|
||||
strategy:
|
||||
matrix:
|
||||
flutter: ['beta']
|
||||
flutter: ['stable', 'beta']
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@ -22,9 +22,6 @@ jobs:
|
||||
- run: flutter pub get
|
||||
working-directory: example
|
||||
- run: flutter analyze
|
||||
- run: flutter test test # https://github.com/flutter/flutter/issues/20907
|
||||
- run: flutter test test
|
||||
working-directory: example
|
||||
- run: flutter pub run tool/prepare_submit.dart
|
||||
- name: "check for uncommitted changes"
|
||||
run: |
|
||||
@ -33,3 +30,26 @@ jobs:
|
||||
"and check in all changes" \
|
||||
&& exit 1)
|
||||
shell: bash
|
||||
test:
|
||||
name: Run all tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run tests
|
||||
uses: docker://cirrusci/flutter:2.0.6
|
||||
with:
|
||||
args: sh run_tests.sh
|
||||
build_web_version:
|
||||
name: Check that the web version compile
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: subosito/flutter-action@v1
|
||||
with:
|
||||
channel: 'beta'
|
||||
- run: flutter config --enable-web
|
||||
- run: flutter precache web
|
||||
- run: flutter pub get
|
||||
working-directory: example
|
||||
- run: flutter build web
|
||||
working-directory: example
|
||||
|
@ -1,6 +1,11 @@
|
||||
## [0.8.0]
|
||||
## [1.0.1]
|
||||
- Implement `RenderBox.computeDryLayout`
|
||||
|
||||
## [1.0.0]
|
||||
- Migrate to null safety
|
||||
- Fix some rendering bugs
|
||||
- Add an image delegate to dynamically change images
|
||||
- Allow to use an imageProviderFactory with a zip file
|
||||
|
||||
## [0.7.1]
|
||||
- Fix a crash for some lottie file with empty paths.
|
||||
|
7
CONTRIBUTING.md
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
## Run the Golden tests
|
||||
Run and update the golden tests requires Docker installed.
|
||||
|
||||
```shell script
|
||||
sh update_goldens.sh
|
||||
```
|
@ -6,7 +6,7 @@
|
||||
Lottie is a mobile library for Android and iOS that parses [Adobe After Effects](https://www.adobe.com/products/aftereffects.html)
|
||||
animations exported as json with [Bodymovin](https://github.com/airbnb/lottie-web) and renders them natively on mobile!
|
||||
|
||||
This repository is a unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart.
|
||||
This repository is an unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart.
|
||||
|
||||
It works on Android, iOS, macOS, linux, windows and web.
|
||||
|
||||
@ -246,13 +246,12 @@ class _Animation extends StatelessWidget {
|
||||
````
|
||||
|
||||
## Limitations
|
||||
Only the [supported features of Lottie Android](https://airbnb.io/lottie/#/supported-features)
|
||||
are supported in this port.
|
||||
This port supports the same [feature set as Lottie Android](https://airbnb.io/lottie/#/supported-features).
|
||||
|
||||
## Flutter Web
|
||||
Run the app with `flutter run -d Chrome --dart-define=FLUTTER_WEB_USE_SKIA=true --release`
|
||||
Run the app with `flutter run -d chrome --web-renderer canvaskit`
|
||||
|
||||
See a preview here: https://xvrh.github.io/lottie-flutter/index.html
|
||||
See a preview here: https://xvrh.github.io/lottie-flutter-web/
|
||||
|
||||
## More examples
|
||||
See the `example` folder for more code samples of the various possibilities.
|
||||
|
@ -6,7 +6,7 @@
|
||||
Lottie is a mobile library for Android and iOS that parses [Adobe After Effects](https://www.adobe.com/products/aftereffects.html)
|
||||
animations exported as json with [Bodymovin](https://github.com/airbnb/lottie-web) and renders them natively on mobile!
|
||||
|
||||
This repository is a unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart.
|
||||
This repository is an unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart.
|
||||
|
||||
It works on Android, iOS, macOS, linux, windows and web.
|
||||
|
||||
@ -78,13 +78,12 @@ import 'example/lib/examples/simple_dynamic_properties.dart#example';
|
||||
````
|
||||
|
||||
## Limitations
|
||||
Only the [supported features of Lottie Android](https://airbnb.io/lottie/#/supported-features)
|
||||
are supported in this port.
|
||||
This port supports the same [feature set as Lottie Android](https://airbnb.io/lottie/#/supported-features).
|
||||
|
||||
## Flutter Web
|
||||
Run the app with `flutter run -d Chrome --dart-define=FLUTTER_WEB_USE_SKIA=true --release`
|
||||
Run the app with `flutter run -d chrome --web-renderer canvaskit`
|
||||
|
||||
See a preview here: https://xvrh.github.io/lottie-flutter/index.html
|
||||
See a preview here: https://xvrh.github.io/lottie-flutter-web/
|
||||
|
||||
## More examples
|
||||
See the `example` folder for more code samples of the various possibilities.
|
||||
|
@ -1,16 +1,17 @@
|
||||
include: package:pedantic/analysis_options.yaml
|
||||
analyzer:
|
||||
errors:
|
||||
strong-mode:
|
||||
implicit-casts: false
|
||||
implicit-dynamic: false
|
||||
linter:
|
||||
rules:
|
||||
avoid_dynamic_calls: true
|
||||
avoid_renaming_method_parameters: true
|
||||
avoid_returning_null_for_future: true
|
||||
avoid_returning_null_for_void: true
|
||||
avoid_returning_this: true
|
||||
avoid_setters_without_getters: true
|
||||
avoid_web_libraries_in_flutter: true
|
||||
await_only_futures: true
|
||||
camel_case_types: true
|
||||
cancel_subscriptions: true
|
||||
@ -26,6 +27,7 @@ linter:
|
||||
overridden_fields: true
|
||||
prefer_inlined_adds: true
|
||||
prefer_interpolation_to_compose_strings: true
|
||||
prefer_null_aware_method_calls: true
|
||||
prefer_null_aware_operators: true
|
||||
prefer_relative_imports: true
|
||||
prefer_typing_uninitialized_variables: true
|
||||
@ -33,7 +35,9 @@ linter:
|
||||
test_types_in_equals: true
|
||||
unnecessary_brace_in_string_interps: true
|
||||
unnecessary_getters_setters: true
|
||||
unnecessary_null_checks: true
|
||||
unnecessary_parenthesis: true
|
||||
unnecessary_statements: true
|
||||
use_function_type_syntax_for_parameters: true
|
||||
use_if_null_to_convert_nulls_to_bools: true
|
||||
void_checks: true
|
||||
|
BIN
example/assets/spinning_carrousel.zip
Normal file
@ -87,7 +87,6 @@ class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
ElevatedButton(
|
||||
child: Text('Loop between frames'),
|
||||
onPressed: () {
|
||||
// Loop between 2 specifics frames
|
||||
|
||||
@ -100,6 +99,7 @@ class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||
period: _controller.duration! * (stop - start),
|
||||
);
|
||||
},
|
||||
child: Text('Loop between frames'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -88,16 +88,16 @@ class _LottieDetailsState extends State<_LottieDetails>
|
||||
trailing: Text(widget.composition.durationFrames.toStringAsFixed(1)),
|
||||
),
|
||||
ElevatedButton(
|
||||
child: Text('touchDownEnd - touchUpCancel'),
|
||||
onPressed: () => _playBetween('touchDownEnd', 'touchUpCancel'),
|
||||
child: Text('touchDownEnd - touchUpCancel'),
|
||||
),
|
||||
ElevatedButton(
|
||||
child: Text('touchDownStart - touchDownEnd'),
|
||||
onPressed: () => _playBetween('touchDownStart', 'touchDownEnd'),
|
||||
child: Text('touchDownStart - touchDownEnd'),
|
||||
),
|
||||
ElevatedButton(
|
||||
child: Text('touchDownEnd - touchUpEnd'),
|
||||
onPressed: () => _playBetween('touchDownEnd', 'touchUpEnd'),
|
||||
child: Text('touchDownEnd - touchUpEnd'),
|
||||
),
|
||||
for (var marker in widget.composition.markers)
|
||||
ListTile(
|
||||
|
@ -29,8 +29,8 @@ class _MyAppState extends State<MyApp> {
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
child: Text('Export all frames'),
|
||||
onPressed: _export,
|
||||
child: Text('Export all frames'),
|
||||
),
|
||||
if (_frames != null)
|
||||
Expanded(
|
||||
|
@ -29,25 +29,25 @@ class App extends StatelessWidget {
|
||||
itemBuilder: (context, index) {
|
||||
var assetName = files[index];
|
||||
return GestureDetector(
|
||||
child: _Item(
|
||||
child: Lottie.asset(
|
||||
assetName,
|
||||
frameBuilder: (context, child, composition) {
|
||||
return AnimatedOpacity(
|
||||
child: child,
|
||||
opacity: composition == null ? 0 : 1,
|
||||
duration: const Duration(seconds: 1),
|
||||
curve: Curves.easeOut,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => Detail(assetName)));
|
||||
},
|
||||
child: _Item(
|
||||
child: Lottie.asset(
|
||||
assetName,
|
||||
frameBuilder: (context, child, composition) {
|
||||
return AnimatedOpacity(
|
||||
opacity: composition == null ? 0 : 1,
|
||||
duration: const Duration(seconds: 1),
|
||||
curve: Curves.easeOut,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -108,14 +108,17 @@ final files = [
|
||||
'assets/Tests/hd.json',
|
||||
'assets/Tests/map.zip',
|
||||
'assets/TwitterHeartButton.json',
|
||||
'assets/_loading_indicator.json',
|
||||
'assets/battery_optimizations.json',
|
||||
'assets/bluetoothscanning.json',
|
||||
'assets/camera_change.json',
|
||||
'assets/envelope.json',
|
||||
'assets/example_with_images/data.json',
|
||||
'assets/lf20_w2Afea.json',
|
||||
'assets/lottiefiles/100_percent.json',
|
||||
'assets/lottiefiles/28861-connection-style-2.json',
|
||||
'assets/lottiefiles/45668-arrow-with-light-passing-through.json',
|
||||
'assets/lottiefiles/Plane.json',
|
||||
'assets/lottiefiles/StreetByMorning.json',
|
||||
'assets/lottiefiles/___.json',
|
||||
'assets/lottiefiles/a_mountain.json',
|
||||
'assets/lottiefiles/accept_arrows.json',
|
||||
'assets/lottiefiles/airbnb.json',
|
||||
@ -346,7 +349,9 @@ final files = [
|
||||
'assets/lottiefiles/yoga_carpet.json',
|
||||
'assets/lottiefiles/youtube_icon_reveal.json',
|
||||
'assets/playing.json',
|
||||
'assets/weather/_hurricane.json',
|
||||
'assets/spinning_carrousel.zip',
|
||||
'assets/sticker.json',
|
||||
'assets/tent.json',
|
||||
'assets/weather/fog.json',
|
||||
'assets/weather/hurricane.json',
|
||||
'assets/weather/thunder-storm.json',
|
||||
|
@ -7,77 +7,77 @@ packages:
|
||||
name: archive
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0-nullsafety.0"
|
||||
version: "3.1.2"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.5.0-nullsafety.3"
|
||||
version: "2.5.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety.3"
|
||||
version: "2.1.0"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-nullsafety.5"
|
||||
version: "1.1.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0-nullsafety.3"
|
||||
version: "1.2.0"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-nullsafety.3"
|
||||
version: "1.1.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0-nullsafety.5"
|
||||
version: "1.15.0"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0-nullsafety.0"
|
||||
version: "3.0.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0-nullsafety.3"
|
||||
version: "1.2.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
version: "1.0.0"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.2.1"
|
||||
version: "6.1.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -89,138 +89,124 @@ packages:
|
||||
name: flutter_colorpicker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.0-nullsafety.0"
|
||||
version: "0.4.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
golden_toolkit:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: golden_toolkit
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.0-nullsafety.0"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.2"
|
||||
version: "0.13.3"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.4"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.16.1"
|
||||
version: "4.0.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.0.1"
|
||||
lottie:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.8.0-nullsafety.2"
|
||||
version: "1.0.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.10-nullsafety.3"
|
||||
version: "0.12.10"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0-nullsafety.6"
|
||||
version: "1.3.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0-nullsafety.3"
|
||||
version: "1.8.0"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.6.27"
|
||||
version: "2.0.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.1+2"
|
||||
version: "2.0.0"
|
||||
path_provider_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.4+8"
|
||||
version: "2.0.0"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
version: "2.0.1"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.4+3"
|
||||
version: "2.0.1"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.9.2"
|
||||
version: "1.11.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
version: "3.0.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
version: "2.0.0"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.13"
|
||||
version: "4.2.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -232,70 +218,70 @@ packages:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0-nullsafety.4"
|
||||
version: "1.8.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0-nullsafety.6"
|
||||
version: "1.10.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety.3"
|
||||
version: "2.1.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-nullsafety.3"
|
||||
version: "1.1.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0-nullsafety.3"
|
||||
version: "1.2.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.19-nullsafety.6"
|
||||
version: "0.3.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0-nullsafety.5"
|
||||
version: "1.3.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety.5"
|
||||
version: "2.1.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.4"
|
||||
version: "2.0.5"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.2"
|
||||
version: "0.2.0"
|
||||
sdks:
|
||||
dart: ">=2.12.0-29.10.beta <3.0.0"
|
||||
flutter: ">=1.24.0-10.2.pre"
|
||||
dart: ">=2.12.0 <3.0.0"
|
||||
flutter: ">=1.20.0"
|
||||
|
@ -8,7 +8,7 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_colorpicker: ^0.4.0-nullsafety.0
|
||||
flutter_colorpicker:
|
||||
http:
|
||||
lottie:
|
||||
path: ../
|
||||
@ -17,7 +17,6 @@ dependencies:
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
golden_toolkit: ^0.9.0-nullsafety.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
@ -60,4 +59,4 @@ flutter:
|
||||
- asset: assets/fonts/Roboto.ttf
|
||||
- family: Noto Emoji
|
||||
fonts:
|
||||
- asset: assets/fonts/NotoEmoji-Regular.ttf
|
||||
- asset: assets/fonts/Noto-Emoji.ttf
|
@ -1,7 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:golden_toolkit/golden_toolkit.dart';
|
||||
|
||||
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
|
||||
await loadAppFonts();
|
||||
return testMain();
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import 'dart:io';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
void main() {
|
||||
var buffer = StringBuffer();
|
||||
@ -8,7 +9,9 @@ void main() {
|
||||
var allFiles = Directory('assets')
|
||||
.listSync(recursive: true)
|
||||
.whereType<File>()
|
||||
.where((f) => f.path.endsWith('.json') || f.path.endsWith('.zip'))
|
||||
.where((f) =>
|
||||
(f.path.endsWith('.json') || f.path.endsWith('.zip')) &&
|
||||
!p.basename(f.path).startsWith('_'))
|
||||
.toList();
|
||||
allFiles.sort((a, b) => a.path.compareTo(b.path));
|
||||
for (var file in allFiles) {
|
||||
|
@ -9,6 +9,7 @@ export 'src/model/marker.dart' show Marker;
|
||||
export 'src/options.dart' show LottieOptions;
|
||||
export 'src/providers/asset_provider.dart' show AssetLottie;
|
||||
export 'src/providers/file_provider.dart' show FileLottie;
|
||||
export 'src/providers/load_image.dart' show LottieImageProviderFactory;
|
||||
export 'src/providers/lottie_provider.dart' show LottieProvider;
|
||||
export 'src/providers/memory_provider.dart' show MemoryLottie;
|
||||
export 'src/providers/network_provider.dart' show NetworkLottie;
|
||||
|
@ -241,8 +241,7 @@ abstract class BaseStrokeContent
|
||||
var bounds = _path.getBounds();
|
||||
|
||||
var width = _widthAnimation.value;
|
||||
bounds = Rect.fromLTRB(bounds.left - width / 2.0, bounds.top - width / 2.0,
|
||||
bounds.right + width / 2.0, bounds.bottom + width / 2.0);
|
||||
bounds = bounds.inflate(width / 2.0);
|
||||
// Add padding to account for rounding errors.
|
||||
bounds = bounds.inflate(1);
|
||||
L.endSection('StrokeContent#getBounds');
|
||||
|
@ -198,7 +198,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
colors[i] = dynamicColors[i];
|
||||
}
|
||||
} else {
|
||||
colors = List.filled(dynamicColors.length, Color(0));
|
||||
colors = List.filled(dynamicColors.length, Color(0x00000000));
|
||||
for (var i = 0; i < dynamicColors.length; i++) {
|
||||
colors[i] = dynamicColors[i];
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ class GradientStrokeContent extends BaseStrokeContent {
|
||||
colors[i] = dynamicColors[i];
|
||||
}
|
||||
} else {
|
||||
colors = List<Color>.filled(dynamicColors.length, Color(0));
|
||||
colors = List<Color>.filled(dynamicColors.length, Color(0x00000000));
|
||||
for (var i = 0; i < dynamicColors.length; i++) {
|
||||
colors[i] = dynamicColors[i];
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ class GradientColorKeyframeAnimation extends KeyframeAnimation<GradientColor> {
|
||||
: super(keyframes) {
|
||||
var startValue = keyframes.first.startValue;
|
||||
var size = startValue == null ? 0 : startValue.size;
|
||||
_gradientColor = GradientColor(
|
||||
List<double>.filled(size, 0.0), List<Color>.filled(size, Color(0)));
|
||||
_gradientColor = GradientColor(List<double>.filled(size, 0.0),
|
||||
List<Color>.filled(size, Color(0x00000000)));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -34,12 +34,14 @@ class CompositionParameters {
|
||||
}
|
||||
|
||||
class LottieComposition {
|
||||
static Future<LottieComposition> fromByteData(ByteData data, {String? name}) {
|
||||
return fromBytes(data.buffer.asUint8List(), name: name);
|
||||
static Future<LottieComposition> fromByteData(ByteData data,
|
||||
{String? name, LottieImageProviderFactory? imageProviderFactory}) {
|
||||
return fromBytes(data.buffer.asUint8List(),
|
||||
name: name, imageProviderFactory: imageProviderFactory);
|
||||
}
|
||||
|
||||
static Future<LottieComposition> fromBytes(Uint8List bytes,
|
||||
{String? name}) async {
|
||||
{String? name, LottieImageProviderFactory? imageProviderFactory}) async {
|
||||
Archive? archive;
|
||||
if (bytes[0] == 0x50 && bytes[1] == 0x4B) {
|
||||
archive = ZipDecoder().decodeBytes(bytes);
|
||||
@ -55,8 +57,18 @@ class LottieComposition {
|
||||
var imagePath = p.posix.join(image.dirName, image.fileName);
|
||||
var found = archive.files.firstWhereOrNull(
|
||||
(f) => f.name.toLowerCase() == imagePath.toLowerCase());
|
||||
|
||||
ImageProvider? provider;
|
||||
if (imageProviderFactory != null) {
|
||||
provider = imageProviderFactory(image);
|
||||
}
|
||||
|
||||
if (provider != null) {
|
||||
image.loadedImage = await loadImage(composition, image, provider);
|
||||
}
|
||||
|
||||
if (found != null) {
|
||||
image.loadedImage = await loadImage(
|
||||
image.loadedImage ??= await loadImage(
|
||||
composition, image, MemoryImage(found.content as Uint8List));
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/widgets.dart';
|
||||
import '../lottie.dart';
|
||||
import 'lottie_drawable.dart';
|
||||
import 'value_delegate.dart';
|
||||
|
||||
@ -43,12 +45,31 @@ class LottieDelegates {
|
||||
/// ```
|
||||
final List<ValueDelegate>? values;
|
||||
|
||||
//TODO(xha): imageDelegate to change the image to display?
|
||||
/// A callback to dynamically change an image of the animation.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// Lottie.asset(
|
||||
// 'assets/data.json',
|
||||
// delegates: LottieDelegates(
|
||||
// image: (composition, image) {
|
||||
// if (image.id == 'img_0' && _isMouseOver) {
|
||||
// return myCustomImage;
|
||||
// }
|
||||
//
|
||||
// // Use the default method: composition.images[image.id].loadedImage;
|
||||
// return null;
|
||||
// },
|
||||
// )
|
||||
// )
|
||||
/// ```
|
||||
final ui.Image? Function(LottieComposition, LottieImageAsset)? image;
|
||||
|
||||
LottieDelegates({
|
||||
this.text,
|
||||
TextStyle Function(LottieFontStyle)? textStyle,
|
||||
this.values,
|
||||
this.image,
|
||||
}) : textStyle = textStyle;
|
||||
|
||||
@override
|
||||
|
@ -79,7 +79,13 @@ class LottieDrawable {
|
||||
ui.Image? getImageAsset(String? ref) {
|
||||
var imageAsset = composition.images[ref];
|
||||
if (imageAsset != null) {
|
||||
return imageAsset.loadedImage;
|
||||
var imageDelegate = delegates?.image;
|
||||
ui.Image? image;
|
||||
if (imageDelegate != null) {
|
||||
image = imageDelegate(composition, imageAsset);
|
||||
}
|
||||
|
||||
return image ?? imageAsset.loadedImage;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -51,8 +51,8 @@ import 'dart:ui';
|
||||
/// {@link #TIME_REMAP} (composition layers only)
|
||||
abstract class LottieProperty {
|
||||
/// ColorInt **/
|
||||
static final Color color = Color(1);
|
||||
static final Color strokeColor = Color(2);
|
||||
static final Color color = Color(0x00000001);
|
||||
static final Color strokeColor = Color(0x00000002);
|
||||
|
||||
/// Opacity value are 0-100 to match after effects **/
|
||||
static final int transformOpacity = 3;
|
||||
|
@ -261,10 +261,7 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
void _clearCanvas(Canvas canvas, Rect bounds) {
|
||||
L.beginSection('Layer#clearLayer');
|
||||
// If we don't pad the clear draw, some phones leave a 1px border of the graphics buffer.
|
||||
canvas.drawRect(
|
||||
Rect.fromLTRB(bounds.left - 1, bounds.top - 1, bounds.right + 1,
|
||||
bounds.bottom + 1),
|
||||
_clearPaint);
|
||||
canvas.drawRect(bounds.inflate(1), _clearPaint);
|
||||
L.endSection('Layer#clearLayer');
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@ class TextLayer extends BaseLayer {
|
||||
_colorCallbackAnimation = null;
|
||||
} else {
|
||||
_colorCallbackAnimation = ValueCallbackKeyframeAnimation(
|
||||
callback as LottieValueCallback<Color>, const Color(0))
|
||||
callback as LottieValueCallback<Color>, const Color(0x00000000))
|
||||
..addUpdateListener(invalidateSelf);
|
||||
addAnimation(_colorCallbackAnimation);
|
||||
}
|
||||
@ -438,7 +438,7 @@ class TextLayer extends BaseLayer {
|
||||
_strokeColorCallbackAnimation = null;
|
||||
} else {
|
||||
_strokeColorCallbackAnimation = ValueCallbackKeyframeAnimation(
|
||||
callback as LottieValueCallback<Color>, const Color(0))
|
||||
callback as LottieValueCallback<Color>, const Color(0x00000000))
|
||||
..addUpdateListener(invalidateSelf);
|
||||
addAnimation(_strokeColorCallbackAnimation);
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ DocumentData documentDataParser(JsonReader reader, {required double scale}) {
|
||||
var tracking = 0;
|
||||
var lineHeight = 0.0;
|
||||
var baselineShift = 0.0;
|
||||
var fillColor = Color(0);
|
||||
var strokeColor = Color(0);
|
||||
var fillColor = Color(0x00000000);
|
||||
var strokeColor = Color(0x00000000);
|
||||
var strokeWidth = 0.0;
|
||||
var strokeOverFill = true;
|
||||
|
||||
|
@ -45,7 +45,7 @@ class GradientColorParser {
|
||||
}
|
||||
|
||||
var positions = List<double>.filled(_colorPoints, 0.0);
|
||||
var colors = List<Color>.filled(_colorPoints, Color(0));
|
||||
var colors = List<Color>.filled(_colorPoints, Color(0x00000000));
|
||||
|
||||
var r = 0;
|
||||
var g = 0;
|
||||
|
@ -59,7 +59,7 @@ class LayerParser {
|
||||
transform: AnimatableTransform(),
|
||||
solidWidth: 0,
|
||||
solidHeight: 0,
|
||||
solidColor: Color(0),
|
||||
solidColor: Color(0x00000000),
|
||||
timeStretch: 0,
|
||||
startFrame: 0,
|
||||
preCompWidth: bounds.width,
|
||||
@ -85,7 +85,7 @@ class LayerParser {
|
||||
var layerId = 0;
|
||||
var solidWidth = 0;
|
||||
var solidHeight = 0;
|
||||
var solidColor = Color(0);
|
||||
var solidColor = Color(0x00000000);
|
||||
var preCompWidth = 0;
|
||||
var preCompHeight = 0;
|
||||
var parentId = -1;
|
||||
|
@ -101,14 +101,13 @@ class LottieCompositionParser {
|
||||
}
|
||||
layers.add(layer);
|
||||
layerMap[layer.id] = layer;
|
||||
|
||||
}
|
||||
if (imageCount > 4) {
|
||||
composition.addWarning(
|
||||
'You have $imageCount images. Lottie should primarily be '
|
||||
'used with shapes. If you are using Adobe Illustrator, convert the Illustrator layers'
|
||||
' to shape layers.');
|
||||
}
|
||||
}
|
||||
reader.endArray();
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,8 @@ class AssetLottie extends LottieProvider {
|
||||
var data = await chosenBundle.load(keyName);
|
||||
|
||||
var composition = await LottieComposition.fromByteData(data,
|
||||
name: p.url.basenameWithoutExtension(keyName));
|
||||
name: p.url.basenameWithoutExtension(keyName),
|
||||
imageProviderFactory: imageProviderFactory);
|
||||
|
||||
for (var image in composition.images.values) {
|
||||
image.loadedImage ??= await _loadImage(composition, image);
|
||||
|
@ -18,7 +18,8 @@ class FileLottie extends LottieProvider {
|
||||
return sharedLottieCache.putIfAbsent(cacheKey, () async {
|
||||
var bytes = await io.loadFile(file);
|
||||
var composition = await LottieComposition.fromBytes(bytes,
|
||||
name: p.basenameWithoutExtension(io.filePath(file)));
|
||||
name: p.basenameWithoutExtension(io.filePath(file)),
|
||||
imageProviderFactory: imageProviderFactory);
|
||||
|
||||
for (var image in composition.images.values) {
|
||||
image.loadedImage ??= await _loadImage(composition, image);
|
||||
|
@ -4,7 +4,7 @@ import 'package:flutter/widgets.dart';
|
||||
import '../composition.dart';
|
||||
import '../lottie_image_asset.dart';
|
||||
|
||||
typedef LottieImageProviderFactory = ImageProvider Function(LottieImageAsset);
|
||||
typedef LottieImageProviderFactory = ImageProvider? Function(LottieImageAsset);
|
||||
|
||||
Future<ui.Image?> loadImage(LottieComposition composition,
|
||||
LottieImageAsset lottieImage, ImageProvider provider) {
|
||||
|
@ -18,7 +18,8 @@ class MemoryLottie extends LottieProvider {
|
||||
// TODO(xha): hash the list content
|
||||
var cacheKey = 'memory-${bytes.hashCode}-${bytes.lengthInBytes}';
|
||||
return sharedLottieCache.putIfAbsent(cacheKey, () async {
|
||||
var composition = await LottieComposition.fromBytes(bytes);
|
||||
var composition = await LottieComposition.fromBytes(bytes,
|
||||
imageProviderFactory: imageProviderFactory);
|
||||
for (var image in composition.images.values) {
|
||||
image.loadedImage ??= await _loadImage(composition, image);
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ class NetworkLottie extends LottieProvider {
|
||||
var bytes = await network.loadHttp(resolved, headers: headers);
|
||||
|
||||
var composition = await LottieComposition.fromBytes(bytes,
|
||||
name: p.url.basenameWithoutExtension(url));
|
||||
name: p.url.basenameWithoutExtension(url),
|
||||
imageProviderFactory: imageProviderFactory);
|
||||
|
||||
for (var image in composition.images.values) {
|
||||
image.loadedImage ??= await _loadImage(resolved, composition, image);
|
||||
|
@ -1,3 +1,5 @@
|
||||
// This file is using conditional import so it is safe to import dart:html
|
||||
// ignore: avoid_web_libraries_in_flutter
|
||||
import 'dart:html';
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/rendering.dart';
|
||||
@ -30,6 +32,6 @@ String filePath(Object file) {
|
||||
return (file as File).relativePath ?? '';
|
||||
}
|
||||
|
||||
ImageProvider? loadImageForFile(Object file, LottieImageAsset lottieImage) {
|
||||
return null;
|
||||
ImageProvider loadImageForFile(Object file, LottieImageAsset lottieImage) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
@ -185,6 +185,11 @@ class RenderLottie extends RenderBox {
|
||||
@override
|
||||
bool hitTestSelf(Offset position) => true;
|
||||
|
||||
@override
|
||||
Size computeDryLayout(BoxConstraints constraints) {
|
||||
return _sizeForConstraints(constraints);
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
size = _sizeForConstraints(constraints);
|
||||
|
157
pubspec.lock
@ -7,189 +7,189 @@ packages:
|
||||
name: _fe_analyzer_shared
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "14.0.0"
|
||||
version: "21.0.0"
|
||||
analyzer:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: analyzer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.41.2"
|
||||
version: "1.5.0"
|
||||
archive:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: archive
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0-nullsafety.0"
|
||||
version: "3.1.2"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.6.0"
|
||||
version: "2.1.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.5.0-nullsafety.3"
|
||||
version: "2.5.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety.3"
|
||||
version: "2.1.0"
|
||||
build:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.6.2"
|
||||
version: "2.0.1"
|
||||
build_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.5"
|
||||
version: "1.0.0"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.7"
|
||||
version: "3.0.0"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.3"
|
||||
version: "2.0.1"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
version: "2.0.2"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.7"
|
||||
version: "7.0.0"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.3.2"
|
||||
version: "5.0.0"
|
||||
built_value:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "7.1.0"
|
||||
version: "8.0.5"
|
||||
characters:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-nullsafety.5"
|
||||
version: "1.1.0"
|
||||
charcode:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0-nullsafety.3"
|
||||
version: "1.2.0"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
version: "2.0.1"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
version: "0.3.0"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-nullsafety.3"
|
||||
version: "1.1.0"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_builder
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.6.0"
|
||||
version: "4.0.0"
|
||||
collection:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0-nullsafety.5"
|
||||
version: "1.15.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "3.0.0"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0-nullsafety.0"
|
||||
version: "3.0.1"
|
||||
dart_style:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: dart_style
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.11"
|
||||
version: "2.0.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0-nullsafety.3"
|
||||
version: "1.2.0"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.2.1"
|
||||
version: "6.1.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.10.11"
|
||||
version: "1.0.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -200,48 +200,48 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "2.0.1"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: graphs
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
version: "2.0.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
version: "3.0.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.4"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.16.1"
|
||||
version: "4.0.0"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.4"
|
||||
version: "1.0.0"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -255,28 +255,28 @@ packages:
|
||||
name: json_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
version: "4.0.1"
|
||||
logging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: logging
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.0.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.10-nullsafety.3"
|
||||
version: "0.12.10"
|
||||
meta:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0-nullsafety.6"
|
||||
version: "1.3.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -290,84 +290,63 @@ packages:
|
||||
name: mockito
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.0-nullsafety.7"
|
||||
node_interop:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_interop
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
node_io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_io
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "5.0.7"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.9.3"
|
||||
version: "2.0.0"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0-nullsafety.3"
|
||||
version: "1.8.0"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
version: "1.11.0"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
version: "1.5.0"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: pub_semver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.4"
|
||||
version: "2.0.0"
|
||||
pubspec_parse:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pubspec_parse
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.7"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
version: "1.0.0"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.7.9"
|
||||
version: "1.1.1"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.4"
|
||||
version: "1.0.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -379,97 +358,97 @@ packages:
|
||||
name: source_gen
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.10+1"
|
||||
version: "1.0.0"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0-nullsafety.4"
|
||||
version: "1.8.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0-nullsafety.6"
|
||||
version: "1.10.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety.3"
|
||||
version: "2.1.0"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_transform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "2.0.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-nullsafety.3"
|
||||
version: "1.1.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0-nullsafety.3"
|
||||
version: "1.2.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.19-nullsafety.6"
|
||||
version: "0.2.19"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timing
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.1+3"
|
||||
version: "1.0.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0-nullsafety.5"
|
||||
version: "1.3.0"
|
||||
vector_math:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety.5"
|
||||
version: "2.1.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.7+15"
|
||||
version: "1.0.0"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "2.1.0"
|
||||
yaml:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: yaml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0-nullsafety.0"
|
||||
version: "3.1.0"
|
||||
sdks:
|
||||
dart: ">=2.12.0-0.0 <3.0.0"
|
||||
dart: ">=2.12.0 <3.0.0"
|
||||
|
21
pubspec.yaml
@ -1,22 +1,22 @@
|
||||
name: lottie
|
||||
description: Render After Effects animations natively on Flutter. This package is a pure Dart implementation of a Lottie player.
|
||||
version: 0.8.0-nullsafety.2
|
||||
version: 1.0.2
|
||||
homepage: https://github.com/xvrh/lottie-flutter
|
||||
|
||||
environment:
|
||||
sdk: '>=2.12.0-0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
archive: ^3.0.0-nullsafety.0
|
||||
characters: ^1.1.0-nullsafety.5
|
||||
charcode: ^1.2.0-nullsafety.3
|
||||
collection: ^1.15.0-nullsafety.5
|
||||
archive: ^3.0.0
|
||||
characters: ^1.1.0
|
||||
charcode: ^1.2.0
|
||||
collection: ^1.15.0
|
||||
flutter:
|
||||
sdk: flutter
|
||||
logging: ^1.0.0
|
||||
meta: ^1.3.0-nullsafety.6
|
||||
path: ^1.8.0-nullsafety.3
|
||||
vector_math: ^2.1.0-nullsafety.5
|
||||
meta: ^1.3.0
|
||||
path: ^1.8.0
|
||||
vector_math: ^2.1.0
|
||||
|
||||
dev_dependencies:
|
||||
analyzer:
|
||||
@ -24,5 +24,6 @@ dev_dependencies:
|
||||
dart_style:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
mockito: ^5.0.0-nullsafety.7
|
||||
yaml: ^3.0.0-nullsafety.0
|
||||
mockito:
|
||||
pub_semver:
|
||||
yaml:
|
||||
|
2
run_tests.sh
Normal file
@ -0,0 +1,2 @@
|
||||
flutter test test
|
||||
(cd example && flutter test test)
|
74
test/dynamic_image_test.dart
Normal file
@ -0,0 +1,74 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Can specify ImageProvider with zip file ', (tester) async {
|
||||
var size = Size(500, 400);
|
||||
tester.binding.window.physicalSizeTestValue = size;
|
||||
tester.binding.window.devicePixelRatioTestValue = 1.0;
|
||||
|
||||
var callCount = 0;
|
||||
LottieImageProviderFactory imageProviderFactory = (image) {
|
||||
++callCount;
|
||||
return FileImage(File('example/assets/Images/WeAccept/img_0.png'));
|
||||
};
|
||||
|
||||
var composition = (await tester.runAsync(() => FileLottie(
|
||||
File('example/assets/spinning_carrousel.zip'),
|
||||
imageProviderFactory: imageProviderFactory)
|
||||
.load()))!;
|
||||
|
||||
await tester.pumpWidget(FilmStrip(composition, size: size));
|
||||
|
||||
expect(callCount, 2);
|
||||
await expectLater(find.byType(FilmStrip),
|
||||
matchesGoldenFile('goldens/dynamic_image/zip_with_provider.png'));
|
||||
});
|
||||
|
||||
testWidgets('Can specify image delegate', (tester) async {
|
||||
var size = Size(500, 400);
|
||||
tester.binding.window.physicalSizeTestValue = size;
|
||||
tester.binding.window.devicePixelRatioTestValue = 1.0;
|
||||
|
||||
var image = await tester.runAsync(() =>
|
||||
loadImage(FileImage(File('example/assets/Images/WeAccept/img_0.png'))));
|
||||
|
||||
var composition = (await tester.runAsync(() =>
|
||||
FileLottie(File('example/assets/spinning_carrousel.zip')).load()))!;
|
||||
|
||||
var delegates = LottieDelegates(image: (composition, asset) {
|
||||
return image;
|
||||
});
|
||||
await tester.pumpWidget(FilmStrip(
|
||||
composition,
|
||||
size: size,
|
||||
delegates: delegates,
|
||||
));
|
||||
|
||||
await expectLater(find.byType(FilmStrip),
|
||||
matchesGoldenFile('goldens/dynamic_image/delegate.png'));
|
||||
});
|
||||
}
|
||||
|
||||
Future<ui.Image?> loadImage(ImageProvider provider) {
|
||||
var completer = Completer<ui.Image?>();
|
||||
var imageStream = provider.resolve(ImageConfiguration.empty);
|
||||
late ImageStreamListener listener;
|
||||
listener = ImageStreamListener((image, synchronousLoaded) {
|
||||
imageStream.removeListener(listener);
|
||||
|
||||
completer.complete(image.image);
|
||||
}, onError: (dynamic e, __) {
|
||||
imageStream.removeListener(listener);
|
||||
|
||||
completer.complete();
|
||||
});
|
||||
imageStream.addListener(listener);
|
||||
|
||||
return completer.future;
|
||||
}
|
@ -11,7 +11,7 @@ void main() {
|
||||
|
||||
setUpAll(() async {
|
||||
composition = await LottieComposition.fromBytes(
|
||||
File('assets/Tests/Shapes.json').readAsBytesSync());
|
||||
File('example/assets/Tests/Shapes.json').readAsBytesSync());
|
||||
});
|
||||
|
||||
void testGolden(String description, ValueDelegate delegate,
|
||||
@ -22,6 +22,9 @@ void main() {
|
||||
.replaceAll(' ', '_');
|
||||
|
||||
testWidgets(description, (tester) async {
|
||||
tester.binding.window.physicalSizeTestValue = Size(500, 400);
|
||||
tester.binding.window.devicePixelRatioTestValue = 1.0;
|
||||
|
||||
var animation =
|
||||
AnimationController(vsync: tester, duration: composition.duration);
|
||||
if (progress != null) {
|
@ -1,13 +1,15 @@
|
||||
import 'dart:io';
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Dynamic test', (tester) async {
|
||||
tester.binding.window.physicalSizeTestValue = Size(500, 400);
|
||||
tester.binding.window.devicePixelRatioTestValue = 1.0;
|
||||
|
||||
var composition = await LottieComposition.fromBytes(
|
||||
File('assets/Tests/DynamicText.json').readAsBytesSync());
|
||||
File('example/assets/Tests/DynamicText.json').readAsBytesSync());
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
@ -13,7 +13,7 @@ void main() {
|
||||
tester.binding.window.devicePixelRatioTestValue = 1.0;
|
||||
|
||||
var composition = await LottieComposition.fromBytes(
|
||||
File('assets/17297-fireworks.json').readAsBytesSync());
|
||||
File('example/assets/17297-fireworks.json').readAsBytesSync());
|
||||
|
||||
await tester.pumpWidget(FilmStrip(composition, size: size));
|
||||
|
22
test/flutter_test_config.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
|
||||
await loadFonts();
|
||||
return testMain();
|
||||
}
|
||||
|
||||
Future<void> loadFonts() async {
|
||||
for (var file in Directory('example/assets/fonts')
|
||||
.listSync()
|
||||
.whereType<File>()
|
||||
.where((f) => f.path.endsWith('.ttf'))) {
|
||||
var fontLoader = FontLoader(
|
||||
path.basenameWithoutExtension(file.path).replaceAll('-', ' '));
|
||||
var future = file.readAsBytes().then((value) => value.buffer.asByteData());
|
||||
fontLoader.addFont(future);
|
||||
await fontLoader.load();
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ import 'package:path/path.dart' as p;
|
||||
import 'utils.dart';
|
||||
|
||||
void main() {
|
||||
var root = 'assets';
|
||||
var root = 'example/assets';
|
||||
for (var asset in Directory(root)
|
||||
.listSync(recursive: true)
|
||||
.whereType<File>()
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |