Compare commits

...

6 Commits

192 changed files with 9156 additions and 1593 deletions

View File

@ -10,7 +10,7 @@ jobs:
name: Flutter analyze
strategy:
matrix:
flutter: ['stable', 'dev']
flutter: ['beta']
runs-on: macos-latest
steps:
- uses: actions/checkout@v2

View File

@ -10,12 +10,11 @@ jobs:
- uses: actions/checkout@v2
- uses: subosito/flutter-action@v1
with:
channel: 'stable'
channel: 'beta'
- run: flutter pub get
- run: flutter pub run tool/publish/comment_dependency_overrides.dart
- run: flutter pub get
- run: echo ::set-env name=RELEASE_VERSION::${GITHUB_REF}
- run: flutter pub run tool/publish/check_version.dart ${{ env.RELEASE_VERSION }}
- run: flutter pub run tool/publish/check_version.dart ${GITHUB_REF}
- name: Setup credentials
run: |
mkdir -p $FLUTTER_HOME/.pub-cache

View File

@ -1,3 +1,12 @@
## [0.7.1]
- Fix a crash for some lottie file with empty paths.
## [0.7.0+1]
- Fix Flutter Web compilation error
## [0.7.0]
- Performance improvement for complex animations.
## [0.6.0]
- Runs the animation at the frame rate specified in the json file (ie. An animation encoded with a 20 FPS will only
be paint 20 times per seconds even though the AnimationController will invalidate the widget 60 times per seconds).

View File

@ -8,7 +8,7 @@ animations exported as json with [Bodymovin](https://github.com/airbnb/lottie-we
This repository is a unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart.
It works on Android, iOS and macOS and web.
It works on Android, iOS, macOS, linux, windows and web.
## Usage
@ -64,7 +64,7 @@ class MyApp extends StatefulWidget {
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
AnimationController _controller;
late final AnimationController _controller;
@override
void initState() {
@ -137,7 +137,7 @@ class MyWidget extends StatefulWidget {
}
class _MyWidgetState extends State<MyWidget> {
Future<LottieComposition> _composition;
late final Future<LottieComposition> _composition;
@override
void initState() {
@ -176,7 +176,7 @@ a specific position and size.
class CustomDrawer extends StatelessWidget {
final LottieComposition composition;
const CustomDrawer(this.composition, {Key key}) : super(key: key);
const CustomDrawer(this.composition, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {

View File

@ -8,7 +8,7 @@ animations exported as json with [Bodymovin](https://github.com/airbnb/lottie-we
This repository is a unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart.
It works on Android, iOS and macOS and web.
It works on Android, iOS, macOS, linux, windows and web.
## Usage

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

7280
example/assets/envelope.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -23,7 +23,7 @@ class __PageState extends State<_Page> {
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) => _showLoader());
SchedulerBinding.instance!.addPostFrameCallback((_) => _showLoader());
}
void _showLoader() {

View File

@ -6,7 +6,7 @@ void main() async {
}
class App extends StatelessWidget {
const App({Key key}) : super(key: key);
const App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {

View File

@ -9,7 +9,7 @@ class MyApp extends StatefulWidget {
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
AnimationController _controller;
late final AnimationController _controller;
@override
void initState() {

View File

@ -17,7 +17,7 @@ class MyApp extends StatefulWidget {
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
AnimationController _controller;
late final AnimationController _controller;
@override
void initState() {
@ -97,7 +97,7 @@ class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
min: start,
max: stop,
reverse: true,
period: _controller.duration * (stop - start),
period: _controller.duration! * (stop - start),
);
},
),

View File

@ -22,7 +22,7 @@ class MyWidget extends StatefulWidget {
}
class _MyWidgetState extends State<MyWidget> {
Future<LottieComposition> _composition;
late final Future<LottieComposition> _composition;
@override
void initState() {
@ -57,7 +57,7 @@ class _MyWidgetState extends State<MyWidget> {
class CustomDrawer extends StatelessWidget {
final LottieComposition composition;
const CustomDrawer(this.composition, {Key key}) : super(key: key);
const CustomDrawer(this.composition, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {

View File

@ -23,7 +23,7 @@ class MyWidget extends StatefulWidget {
}
class _MyWidgetState extends State<MyWidget> {
Future<LottieComposition> _composition;
late final Future<LottieComposition> _composition;
@override
void initState() {

View File

@ -8,7 +8,7 @@ void main() async {
}
class App extends StatefulWidget {
const App({Key key}) : super(key: key);
const App({Key? key}) : super(key: key);
@override
_AppState createState() => _AppState();
@ -50,7 +50,7 @@ class _AppState extends State<App> with TickerProviderStateMixin {
value: _useDelegates,
onChanged: (newValue) {
setState(() {
_useDelegates = newValue;
_useDelegates = newValue!;
});
},
),

View File

@ -7,14 +7,14 @@ void main() async {
}
class App extends StatefulWidget {
const App({Key key}) : super(key: key);
const App({Key? key}) : super(key: key);
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {
TextEditingController _textController;
late final TextEditingController _textController;
@override
void initState() {

View File

@ -6,14 +6,14 @@ void main() async {
}
class App extends StatefulWidget {
const App({Key key}) : super(key: key);
const App({Key? key}) : super(key: key);
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {
AnimationController _animationController;
late final AnimationController _animationController;
bool _showAnimation = true;
@override

View File

@ -9,14 +9,14 @@ void main() async {
}
class App extends StatefulWidget {
const App({Key key}) : super(key: key);
const App({Key? key}) : super(key: key);
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {
Future<LottieComposition> _composition;
late final Future<LottieComposition> _composition;
@override
void initState() {
@ -35,9 +35,9 @@ class _AppState extends State<App> with TickerProviderStateMixin {
body: FutureBuilder<LottieComposition>(
future: _composition,
builder: (context, snapshot) {
if (snapshot.hasError) return ErrorWidget(snapshot.error);
if (snapshot.hasError) return ErrorWidget(snapshot.error!);
if (!snapshot.hasData) return CircularProgressIndicator();
return _LottieDetails(snapshot.data);
return _LottieDetails(snapshot.data!);
},
),
),
@ -48,7 +48,7 @@ class _AppState extends State<App> with TickerProviderStateMixin {
class _LottieDetails extends StatefulWidget {
final LottieComposition composition;
const _LottieDetails(this.composition, {Key key}) : super(key: key);
const _LottieDetails(this.composition, {Key? key}) : super(key: key);
@override
_LottieDetailsState createState() => _LottieDetailsState();
@ -56,7 +56,7 @@ class _LottieDetails extends StatefulWidget {
class _LottieDetailsState extends State<_LottieDetails>
with TickerProviderStateMixin {
AnimationController _controller;
late final AnimationController _controller;
@override
void initState() {
@ -112,8 +112,8 @@ class _LottieDetailsState extends State<_LottieDetails>
}
void _playBetween(String marker1, String marker2) {
var start = widget.composition.getMarker(marker1).start;
var end = widget.composition.getMarker(marker2).start;
var start = widget.composition.getMarker(marker1)!.start;
var end = widget.composition.getMarker(marker2)!.start;
_controller.value = start;
_controller.animateTo(end,

View File

@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
late final AnimationController _controller;
int _repeatIndex = 0;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this)
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
setState(() {
_repeatIndex++;
});
if (_repeatIndex < 5) {
_controller.reset();
_controller.forward();
}
}
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ListView(
children: [
Lottie.asset(
'assets/AndroidWave.json',
controller: _controller,
width: 150,
height: 150,
onLoaded: (composition) {
// Configure the AnimationController with the duration of the
// Lottie file and start the animation.
_controller.duration = composition.duration;
_controller.forward();
},
),
Center(child: Text('Repeat: $_repeatIndex')),
],
),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}

View File

@ -12,7 +12,7 @@ void main() async {
}
class App extends StatefulWidget {
const App({Key key}) : super(key: key);
const App({Key? key}) : super(key: key);
@override
_AppState createState() => _AppState();
@ -20,7 +20,7 @@ class App extends StatefulWidget {
class _AppState extends State<App> with TickerProviderStateMixin {
int _index = 0;
AnimationController _animationController;
late final AnimationController _animationController;
@override
void initState() {

View File

@ -1,3 +1,5 @@
//@dart=2.10
import 'dart:io';
import 'dart:ui';
import 'package:flutter/material.dart';

View File

@ -42,7 +42,9 @@ class App extends StatelessWidget {
),
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute<void>(
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => Detail(assetName)));
},
);
@ -56,7 +58,7 @@ class App extends StatelessWidget {
class _Item extends StatelessWidget {
final Widget child;
const _Item({Key key, this.child}) : super(key: key);
const _Item({Key? key, required this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -81,26 +83,18 @@ class _Item extends StatelessWidget {
class Detail extends StatefulWidget {
final String assetName;
const Detail(this.assetName, {Key key}) : super(key: key);
const Detail(this.assetName, {Key? key}) : super(key: key);
@override
_DetailState createState() => _DetailState();
}
class _DetailState extends State<Detail> with TickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
}
late final _controller = AnimationController(vsync: this);
@override
void dispose() {
_controller.dispose();
super.dispose();
}

View File

@ -13,7 +13,7 @@ void main() async {
class App extends StatelessWidget {
final LottieComposition composition;
const App({Key key, this.composition}) : super(key: key);
const App({Key? key, required this.composition}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -97,13 +97,13 @@ class App extends StatelessWidget {
class _Lottie extends StatefulWidget {
final LottieComposition composition;
final double width;
final double height;
final BoxFit fit;
final AlignmentGeometry alignment;
final double? width;
final double? height;
final BoxFit? fit;
final AlignmentGeometry? alignment;
const _Lottie(this.composition,
{Key key, this.width, this.height, this.fit, this.alignment})
{Key? key, this.width, this.height, this.fit, this.alignment})
: super(key: key);
@override
@ -111,7 +111,7 @@ class _Lottie extends StatefulWidget {
}
class __LottieState extends State<_Lottie> with TickerProviderStateMixin {
AnimationController _controller;
late AnimationController _controller;
@override
void initState() {

View File

@ -6,7 +6,7 @@ void main() async {
}
class App extends StatelessWidget {
const App({Key key}) : super(key: key);
const App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {

View File

@ -6,7 +6,7 @@ void main() async {
}
class App extends StatelessWidget {
const App({Key key}) : super(key: key);
const App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {

View File

@ -24,4 +24,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: d8ba9b3e9e93c62c74a660b46c6fcb09f03991a7
COCOAPODS: 1.9.1
COCOAPODS: 1.10.0

View File

@ -330,10 +330,10 @@
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;

View File

@ -7,77 +7,70 @@ packages:
name: archive
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.13"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.0"
version: "3.0.0-nullsafety.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.2"
version: "2.5.0-nullsafety.3"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0-nullsafety.3"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
version: "1.1.0-nullsafety.5"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.3"
version: "1.2.0-nullsafety.3"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "1.1.0-nullsafety.3"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.13"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "1.15.0-nullsafety.5"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
version: "3.0.0-nullsafety.0"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.2.0-nullsafety.3"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
file:
dependency: transitive
description:
@ -96,7 +89,7 @@ packages:
name: flutter_colorpicker
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.4"
version: "0.4.0-nullsafety.0"
flutter_test:
dependency: "direct dev"
description: flutter
@ -108,7 +101,7 @@ packages:
name: golden_toolkit
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.0"
version: "0.9.0-nullsafety.0"
http:
dependency: "direct main"
description:
@ -136,42 +129,42 @@ packages:
name: logging
url: "https://pub.dartlang.org"
source: hosted
version: "0.11.4"
version: "1.0.0-nullsafety.0"
lottie:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "0.6.0"
version: "0.8.0-nullsafety.0"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.8"
version: "0.12.10-nullsafety.3"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.8"
version: "1.3.0-nullsafety.6"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0-nullsafety.3"
path_provider:
dependency: "direct main"
description:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.14"
version: "1.6.27"
path_provider_linux:
dependency: transitive
description:
@ -185,21 +178,28 @@ packages:
name: path_provider_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4+3"
version: "0.0.4+8"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
version: "1.0.4"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4+3"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
version: "1.9.2"
platform:
dependency: transitive
description:
@ -213,7 +213,7 @@ packages:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
version: "1.0.3"
process:
dependency: transitive
description:
@ -232,63 +232,70 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0-nullsafety.4"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.5"
version: "1.10.0-nullsafety.6"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0-nullsafety.3"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
version: "1.1.0-nullsafety.3"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.2.0-nullsafety.3"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.17"
version: "0.2.19-nullsafety.6"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.3.0-nullsafety.5"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
version: "2.1.0-nullsafety.5"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.4"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.0"
version: "0.1.2"
sdks:
dart: ">=2.9.0-14.0.dev <3.0.0"
flutter: ">=1.12.13+hotfix.5 <2.0.0"
dart: ">=2.12.0-29.10.beta <3.0.0"
flutter: ">=1.24.0-10.2.pre <2.0.0"

View File

@ -1,23 +1,23 @@
name: lottie_example
description: A sample app for the Lottie player
version: 0.0.1
publish_to: none
environment:
sdk: ">=2.7.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_colorpicker: ^0.4.0-nullsafety.0
http:
lottie:
path: ../
flutter_colorpicker:
path_provider:
http:
dev_dependencies:
flutter_test:
sdk: flutter
golden_toolkit:
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
@ -31,6 +31,7 @@ flutter:
- assets/lottiefiles/
- assets/Mobilo/
- assets/Tests/
- assets/Tests/images/
- assets/Logo/
- assets/Images/
- assets/Images/WeAccept/

View File

@ -7,7 +7,7 @@ import 'package:lottie/lottie.dart';
import 'utils.dart';
void main() {
LottieComposition composition;
late LottieComposition composition;
setUpAll(() async {
composition = await LottieComposition.fromBytes(
@ -15,7 +15,7 @@ void main() {
});
void testGolden(String description, ValueDelegate delegate,
{double progress}) async {
{double? progress}) async {
var screenshotName = description
.toLowerCase()
.replaceAll(RegExp('[^a-z0-9 ]'), '')
@ -288,8 +288,8 @@ void main() {
testGolden(
'Opacity interpolation ($progress)',
ValueDelegate.transformOpacity(['Shape Layer 1', 'Rectangle'],
callback: (frameInfo) => lerpDouble(
10, 100, Curves.linear.transform(frameInfo.overallProgress))
callback: (frameInfo) => lerpDouble(10, 100,
Curves.linear.transform(frameInfo.overallProgress))!
.round()),
progress: progress);
}

View File

@ -1,7 +1,7 @@
import 'dart:async';
import 'package:golden_toolkit/golden_toolkit.dart';
Future<void> main(FutureOr<void> Function() testMain) async {
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
await loadAppFonts();
return testMain();
}

View File

@ -16,7 +16,8 @@ void main() {
var size = Size(500, 400);
tester.binding.window.physicalSizeTestValue = size;
tester.binding.window.devicePixelRatioTestValue = 1.0;
var composition = await tester.runAsync(() => FileLottie(asset).load());
var composition =
(await tester.runAsync(() => FileLottie(asset).load()))!;
await tester.pumpWidget(FilmStrip(composition, size: size));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -3,11 +3,11 @@ import 'package:lottie/lottie.dart';
class FilmStrip extends StatelessWidget {
final LottieComposition composition;
final LottieDelegates delegates;
final LottieDelegates? delegates;
final Size size;
const FilmStrip(this.composition,
{Key key, @required this.size, this.delegates})
{Key? key, required this.size, this.delegates})
: super(key: key);
@override

View File

@ -34,21 +34,20 @@ abstract class BaseStrokeContent
final List<double> _dashPatternValues;
final Paint paint = Paint()..style = PaintingStyle.stroke;
final BaseKeyframeAnimation<dynamic, double> _widthAnimation;
final BaseKeyframeAnimation<dynamic, int> _opacityAnimation;
final List<BaseKeyframeAnimation<dynamic, double>> _dashPatternAnimations;
final BaseKeyframeAnimation<dynamic,
double> /*?*/ _dashPatternOffsetAnimation;
BaseKeyframeAnimation<ColorFilter, ColorFilter> /*?*/ _colorFilterAnimation;
final BaseKeyframeAnimation<Object, double> _widthAnimation;
final BaseKeyframeAnimation<Object, int> _opacityAnimation;
final List<BaseKeyframeAnimation<Object, double>> _dashPatternAnimations;
final BaseKeyframeAnimation<Object, double>? _dashPatternOffsetAnimation;
BaseKeyframeAnimation<ColorFilter, ColorFilter?>? _colorFilterAnimation;
BaseStrokeContent(this.lottieDrawable, this.layer,
{StrokeCap cap,
StrokeJoin join,
double miterLimit,
AnimatableIntegerValue opacity,
AnimatableDoubleValue width,
List<AnimatableDoubleValue> dashPattern,
AnimatableDoubleValue dashOffset})
{required StrokeCap cap,
required StrokeJoin join,
required double miterLimit,
required AnimatableIntegerValue opacity,
required AnimatableDoubleValue width,
required List<AnimatableDoubleValue> dashPattern,
AnimatableDoubleValue? dashOffset})
: _widthAnimation = width.createAnimation(),
_opacityAnimation = opacity.createAnimation(),
_dashPatternOffsetAnimation = dashOffset?.createAnimation(),
@ -76,7 +75,7 @@ abstract class BaseStrokeContent
_dashPatternAnimations[i].addUpdateListener(onUpdateListener);
}
if (_dashPatternOffsetAnimation != null) {
_dashPatternOffsetAnimation.addUpdateListener(onUpdateListener);
_dashPatternOffsetAnimation!.addUpdateListener(onUpdateListener);
}
}
@ -86,7 +85,7 @@ abstract class BaseStrokeContent
@override
void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
TrimPathContent trimPathContentBefore;
TrimPathContent? trimPathContentBefore;
for (var i = contentsBefore.length - 1; i >= 0; i--) {
var content = contentsBefore[i];
if (content is TrimPathContent &&
@ -98,7 +97,7 @@ abstract class BaseStrokeContent
trimPathContentBefore.addListener(onUpdateListener);
}
_PathGroup currentPathGroup;
_PathGroup? currentPathGroup;
for (var i = contentsAfter.length - 1; i >= 0; i--) {
var content = contentsAfter[i];
if (content is TrimPathContent &&
@ -119,7 +118,8 @@ abstract class BaseStrokeContent
}
@override
void draw(Canvas canvas, Size size, Matrix4 parentMatrix, {int parentAlpha}) {
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
{required int parentAlpha}) {
L.beginSection('StrokeContent#draw');
if (parentMatrix.hasZeroScaleAxis) {
L.endSection('StrokeContent#draw');
@ -136,7 +136,7 @@ abstract class BaseStrokeContent
}
if (_colorFilterAnimation != null) {
paint.colorFilter = _colorFilterAnimation.value;
paint.colorFilter = _colorFilterAnimation!.value;
}
for (var i = 0; i < _pathGroups.length; i++) {
@ -175,18 +175,17 @@ abstract class BaseStrokeContent
var pathMetrics = _path.computeMetrics().toList();
var totalLength = pathMetrics.fold<double>(0.0, (a, b) => a + b.length);
var offsetLength = totalLength * pathGroup.trimPath.offset.value / 360.0;
var startLength =
totalLength * pathGroup.trimPath.start.value / 100.0 + offsetLength;
var endLength =
totalLength * pathGroup.trimPath.end.value / 100.0 + offsetLength;
var trimPath = pathGroup.trimPath!;
var offsetLength = totalLength * trimPath.offset.value / 360.0;
var startLength = totalLength * trimPath.start.value / 100.0 + offsetLength;
var endLength = totalLength * trimPath.end.value / 100.0 + offsetLength;
var currentLength = 0.0;
for (var j = pathGroup.paths.length - 1; j >= 0; j--) {
_trimPathPath
.set(pathGroup.paths[j].getPath().transform(parentMatrix.storage));
var pathMetrics = _trimPathPath.computeMetrics().toList();
var length = pathMetrics.first.length;
var length = pathMetrics.isNotEmpty ? pathMetrics.first.length : 0;
if (endLength > totalLength &&
endLength - totalLength < currentLength + length &&
currentLength < endLength - totalLength) {
@ -229,7 +228,7 @@ abstract class BaseStrokeContent
}
@override
Rect getBounds(Matrix4 parentMatrix, {bool applyParents}) {
Rect getBounds(Matrix4 parentMatrix, {required bool applyParents}) {
L.beginSection('StrokeContent#getBounds');
_path.reset();
for (var i = 0; i < _pathGroups.length; i++) {
@ -279,7 +278,7 @@ abstract class BaseStrokeContent
var offset = _dashPatternOffsetAnimation == null
? 0.0
: _dashPatternOffsetAnimation.value * scale;
: _dashPatternOffsetAnimation!.value * scale;
var newPath = dashPath(path, intervals: _dashPatternValues, phase: offset);
L.endSection('StrokeContent#applyDashPattern');
@ -295,7 +294,7 @@ abstract class BaseStrokeContent
@override
@mustCallSuper
void addValueCallback<T>(T property, LottieValueCallback<T> /*?*/ callback) {
void addValueCallback<T>(T property, LottieValueCallback<T>? callback) {
if (property == LottieProperty.opacity) {
_opacityAnimation.setValueCallback(callback as LottieValueCallback<int>);
} else if (property == LottieProperty.strokeWidth) {
@ -309,9 +308,9 @@ abstract class BaseStrokeContent
_colorFilterAnimation = null;
} else {
_colorFilterAnimation =
ValueCallbackKeyframeAnimation<ColorFilter, ColorFilter>(
callback as LottieValueCallback<ColorFilter>);
_colorFilterAnimation.addUpdateListener(onUpdateListener);
ValueCallbackKeyframeAnimation<ColorFilter, ColorFilter?>(
callback as LottieValueCallback<ColorFilter>, null);
_colorFilterAnimation!.addUpdateListener(onUpdateListener);
layer.addAnimation(_colorFilterAnimation);
}
}
@ -321,7 +320,7 @@ abstract class BaseStrokeContent
/// Data class to help drawing trim paths individually.
class _PathGroup {
final List<PathContent> paths = <PathContent>[];
final TrimPathContent /*?*/ trimPath;
final TrimPathContent? trimPath;
_PathGroup(this.trimPath);
}

View File

@ -1,5 +1,5 @@
abstract class Content {
String get name;
String? get name;
void setContents(List<Content> contentsBefore, List<Content> contentsAfter);
}

View File

@ -1,5 +1,4 @@
import 'dart:ui';
import 'package:meta/meta.dart';
import 'package:vector_math/vector_math_64.dart';
import '../../lottie_drawable.dart';
import '../../model/animatable/animatable_transform.dart';
@ -32,8 +31,7 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
return contents;
}
static AnimatableTransform /*?*/ findTransform(
List<ContentModel> contentModels) {
static AnimatableTransform? findTransform(List<ContentModel> contentModels) {
for (var i = 0; i < contentModels.length; i++) {
var contentModel = contentModels[i];
if (contentModel is AnimatableTransform) {
@ -47,12 +45,12 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
final Path _path = PathFactory.create();
@override
final String name;
final String? name;
final bool _hidden;
final List<Content> _contents;
final LottieDrawable _lottieDrawable;
List<PathContent> /*?*/ _pathContents;
TransformKeyframeAnimation /*?*/ _transformAnimation;
List<PathContent>? _pathContents;
TransformKeyframeAnimation? _transformAnimation;
ContentGroup(final LottieDrawable lottieDrawable, BaseLayer layer,
ShapeGroup shapeGroup)
@ -65,11 +63,11 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
findTransform(shapeGroup.items));
ContentGroup.copy(this._lottieDrawable, BaseLayer layer, this.name,
this._hidden, this._contents, AnimatableTransform /*?*/ transform) {
this._hidden, this._contents, AnimatableTransform? transform) {
if (transform != null) {
_transformAnimation = transform.createAnimation();
_transformAnimation.addAnimationsToLayer(layer);
_transformAnimation.addListener(onValueChanged);
_transformAnimation = transform.createAnimation()
..addAnimationsToLayer(layer)
..addListener(onValueChanged);
}
var greedyContents = <GreedyContent>[];
@ -104,20 +102,20 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
List<PathContent> getPathList() {
if (_pathContents == null) {
_pathContents = <PathContent>[];
var pathContents = _pathContents = <PathContent>[];
for (var i = 0; i < _contents.length; i++) {
var content = _contents[i];
if (content is PathContent) {
_pathContents.add(content);
pathContents.add(content);
}
}
}
return _pathContents;
return _pathContents!;
}
Matrix4 getTransformationMatrix() {
if (_transformAnimation != null) {
return _transformAnimation.getMatrix();
return _transformAnimation!.getMatrix();
}
_matrix.reset();
return _matrix;
@ -128,7 +126,7 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
// TODO: cache this somehow.
_matrix.reset();
if (_transformAnimation != null) {
_matrix.set(_transformAnimation.getMatrix());
_matrix.set(_transformAnimation!.getMatrix());
}
_path.reset();
if (_hidden) {
@ -145,17 +143,17 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
@override
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
{@required int parentAlpha}) {
{required int parentAlpha}) {
if (_hidden) {
return;
}
_matrix.set(parentMatrix);
int layerAlpha;
if (_transformAnimation != null) {
_matrix.preConcat(_transformAnimation.getMatrix());
var opacity = _transformAnimation.opacity == null
_matrix.preConcat(_transformAnimation!.getMatrix());
var opacity = _transformAnimation?.opacity == null
? 100
: _transformAnimation.opacity.value;
: _transformAnimation!.opacity!.value;
layerAlpha = ((opacity / 100.0 * parentAlpha / 255.0) * 255).round();
} else {
layerAlpha = parentAlpha;
@ -199,10 +197,10 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
}
@override
Rect getBounds(Matrix4 parentMatrix, {bool applyParents}) {
Rect getBounds(Matrix4 parentMatrix, {required bool applyParents}) {
_matrix.set(parentMatrix);
if (_transformAnimation != null) {
_matrix.preConcat(_transformAnimation.getMatrix());
_matrix.preConcat(_transformAnimation!.getMatrix());
}
var bounds = Rect.zero;
for (var i = _contents.length - 1; i >= 0; i--) {
@ -223,8 +221,8 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
return;
}
if ('__container' != name) {
currentPartialKeyPath = currentPartialKeyPath.addKey(name);
if ('__container' != name && name != null) {
currentPartialKeyPath = currentPartialKeyPath.addKey(name!);
if (keyPath.fullyResolvesTo(name, depth)) {
accumulator.add(currentPartialKeyPath.resolve(this));
@ -245,9 +243,9 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
}
@override
void addValueCallback<T>(T property, LottieValueCallback<T> /*?*/ callback) {
void addValueCallback<T>(T property, LottieValueCallback<T>? callback) {
if (_transformAnimation != null) {
_transformAnimation.applyValueCallback(property, callback);
_transformAnimation!.applyValueCallback(property, callback);
}
}
}

View File

@ -1,10 +1,9 @@
import 'dart:ui';
import 'package:meta/meta.dart';
import 'package:vector_math/vector_math_64.dart';
import 'content.dart';
abstract class DrawingContent extends Content {
void draw(Canvas canvas, Size canvasSize, Matrix4 parentMatrix,
{@required int parentAlpha});
Rect getBounds(Matrix4 parentMatrix, {@required bool applyParents});
{required int parentAlpha});
Rect getBounds(Matrix4 parentMatrix, {required bool applyParents});
}

View File

@ -22,10 +22,10 @@ class EllipseContent implements PathContent, KeyPathElementContent {
final Path _path = PathFactory.create();
@override
final String name;
final String? name;
final LottieDrawable lottieDrawable;
final BaseKeyframeAnimation<dynamic, Offset> _sizeAnimation;
final BaseKeyframeAnimation<dynamic, Offset> _positionAnimation;
final BaseKeyframeAnimation<Object, Offset> _sizeAnimation;
final BaseKeyframeAnimation<Object, Offset> _positionAnimation;
final CircleShape _circleShape;
final CompoundTrimPathContent _trimPaths = CompoundTrimPathContent();
@ -115,7 +115,7 @@ class EllipseContent implements PathContent, KeyPathElementContent {
}
@override
void addValueCallback<T>(T property, LottieValueCallback<T> /*?*/ callback) {
void addValueCallback<T>(T property, LottieValueCallback<T>? callback) {
if (property == LottieProperty.ellipseSize) {
_sizeAnimation.setValueCallback(callback as LottieValueCallback<Offset>);
} else if (property == LottieProperty.position) {

View File

@ -22,12 +22,12 @@ class FillContent implements DrawingContent, KeyPathElementContent {
final Paint _paint = Paint();
final BaseLayer layer;
@override
final String name;
final String? name;
final bool _hidden;
final List<PathContent> _paths = <PathContent>[];
BaseKeyframeAnimation<Color, Color> _colorAnimation;
BaseKeyframeAnimation<int, int> _opacityAnimation;
BaseKeyframeAnimation<ColorFilter, ColorFilter> /*?*/ _colorFilterAnimation;
late final BaseKeyframeAnimation<Color, Color> _colorAnimation;
late final BaseKeyframeAnimation<int, int> _opacityAnimation;
BaseKeyframeAnimation<ColorFilter, ColorFilter?>? _colorFilterAnimation;
final LottieDrawable lottieDrawable;
FillContent(this.lottieDrawable, this.layer, ShapeFill fill)
@ -39,10 +39,10 @@ class FillContent implements DrawingContent, KeyPathElementContent {
_path.fillType = fill.fillType;
_colorAnimation = fill.color.createAnimation();
_colorAnimation = fill.color!.createAnimation();
_colorAnimation.addUpdateListener(onValueChanged);
layer.addAnimation(_colorAnimation);
_opacityAnimation = fill.opacity.createAnimation();
_opacityAnimation = fill.opacity!.createAnimation();
_opacityAnimation.addUpdateListener(onValueChanged);
layer.addAnimation(_opacityAnimation);
}
@ -62,7 +62,8 @@ class FillContent implements DrawingContent, KeyPathElementContent {
}
@override
void draw(Canvas canvas, Size size, Matrix4 parentMatrix, {int parentAlpha}) {
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
{required int parentAlpha}) {
if (_hidden) {
return;
}
@ -76,7 +77,7 @@ class FillContent implements DrawingContent, KeyPathElementContent {
}
if (_colorFilterAnimation != null) {
_paint.colorFilter = _colorFilterAnimation.value;
_paint.colorFilter = _colorFilterAnimation!.value;
}
_path.reset();
@ -93,7 +94,7 @@ class FillContent implements DrawingContent, KeyPathElementContent {
}
@override
Rect getBounds(Matrix4 parentMatrix, {bool applyParents}) {
Rect getBounds(Matrix4 parentMatrix, {required bool applyParents}) {
_path.reset();
for (var i = 0; i < _paths.length; i++) {
_path.addPath(_paths[i].getPath(), Offset.zero,
@ -114,7 +115,7 @@ class FillContent implements DrawingContent, KeyPathElementContent {
}
@override
void addValueCallback<T>(T property, LottieValueCallback<T> /*?*/ callback) {
void addValueCallback<T>(T property, LottieValueCallback<T>? callback) {
if (property == LottieProperty.color) {
_colorAnimation.setValueCallback(callback as LottieValueCallback<Color>);
} else if (property == LottieProperty.opacity) {
@ -128,8 +129,8 @@ class FillContent implements DrawingContent, KeyPathElementContent {
_colorFilterAnimation = null;
} else {
_colorFilterAnimation = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<ColorFilter>);
_colorFilterAnimation.addUpdateListener(onValueChanged);
callback as LottieValueCallback<ColorFilter>, null)
..addUpdateListener(onValueChanged);
layer.addAnimation(_colorFilterAnimation);
}
}

View File

@ -33,9 +33,9 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
final BaseKeyframeAnimation<int, int> _opacityAnimation;
final BaseKeyframeAnimation<Offset, Offset> _startPointAnimation;
final BaseKeyframeAnimation<Offset, Offset> _endPointAnimation;
BaseKeyframeAnimation<ColorFilter, ColorFilter> /*?*/ _colorFilterAnimation;
ValueCallbackKeyframeAnimation<List<Color>,
List<Color>> /*?*/ _colorCallbackAnimation;
BaseKeyframeAnimation<ColorFilter, ColorFilter?>? _colorFilterAnimation;
ValueCallbackKeyframeAnimation<List<Color>, List<Color>>?
_colorCallbackAnimation;
final LottieDrawable lottieDrawable;
final int _cacheSteps;
@ -62,7 +62,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
}
@override
String get name => _fill.name;
String? get name => _fill.name;
void invalidate() {
lottieDrawable.invalidateSelf();
@ -79,7 +79,8 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
}
@override
void draw(Canvas canvas, Size size, Matrix4 parentMatrix, {int parentAlpha}) {
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
{required int parentAlpha}) {
if (_fill.hidden) {
return;
}
@ -99,7 +100,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
_paint.shader = gradient;
if (_colorFilterAnimation != null) {
_paint.colorFilter = _colorFilterAnimation.value;
_paint.colorFilter = _colorFilterAnimation!.value;
}
var alpha =
@ -117,7 +118,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
}
@override
Rect getBounds(Matrix4 parentMatrix, {bool applyParents}) {
Rect getBounds(Matrix4 parentMatrix, {required bool applyParents}) {
_path.reset();
for (var i = 0; i < _paths.length; i++) {
_path.addPath(_paths[i].getPath(), Offset.zero,
@ -192,7 +193,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
List<Color> _applyDynamicColorsIfNeeded(List<Color> colors) {
if (_colorCallbackAnimation != null) {
var dynamicColors = _colorCallbackAnimation.value;
var dynamicColors = _colorCallbackAnimation!.value;
if (colors.length == dynamicColors.length) {
for (var i = 0; i < colors.length; i++) {
colors[i] = dynamicColors[i];
@ -215,7 +216,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
}
@override
void addValueCallback<T>(T property, LottieValueCallback<T> /*?*/ callback) {
void addValueCallback<T>(T property, LottieValueCallback<T>? callback) {
if (property == LottieProperty.opacity) {
_opacityAnimation.setValueCallback(callback as LottieValueCallback<int>);
} else if (property == LottieProperty.colorFilter) {
@ -227,8 +228,8 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
_colorFilterAnimation = null;
} else {
_colorFilterAnimation = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<ColorFilter>);
_colorFilterAnimation.addUpdateListener(invalidate);
callback as LottieValueCallback<ColorFilter>, null)
..addUpdateListener(invalidate);
layer.addAnimation(_colorFilterAnimation);
}
} else if (property == LottieProperty.gradientColor) {
@ -240,8 +241,8 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
_colorCallbackAnimation = null;
} else {
_colorCallbackAnimation = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<List<Color>>);
_colorCallbackAnimation.addUpdateListener(invalidate);
callback as LottieValueCallback<List<Color>>, <Color>[])
..addUpdateListener(invalidate);
layer.addAnimation(_colorCallbackAnimation);
}
}

View File

@ -18,7 +18,7 @@ class GradientStrokeContent extends BaseStrokeContent {
static final int _cacheStepsMs = 32;
@override
final String name;
final String? name;
final bool _hidden;
final _linearGradientCache = <int, Gradient>{};
final _radialGradientCache = <int, Gradient>{};
@ -28,8 +28,8 @@ class GradientStrokeContent extends BaseStrokeContent {
final BaseKeyframeAnimation<GradientColor, GradientColor> _colorAnimation;
final BaseKeyframeAnimation<Offset, Offset> _startPointAnimation;
final BaseKeyframeAnimation<Offset, Offset> _endPointAnimation;
ValueCallbackKeyframeAnimation<List<Color>,
List<Color>> /*?*/ _colorCallbackAnimation;
ValueCallbackKeyframeAnimation<List<Color>, List<Color>>?
_colorCallbackAnimation;
GradientStrokeContent(final LottieDrawable lottieDrawable, BaseLayer layer,
GradientStroke stroke)
@ -61,7 +61,8 @@ class GradientStrokeContent extends BaseStrokeContent {
}
@override
void draw(Canvas canvas, Size size, Matrix4 parentMatrix, {int parentAlpha}) {
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
{required int parentAlpha}) {
if (_hidden) {
return;
}
@ -142,7 +143,7 @@ class GradientStrokeContent extends BaseStrokeContent {
List<Color> _applyDynamicColorsIfNeeded(List<Color> colors) {
if (_colorCallbackAnimation != null) {
var dynamicColors = _colorCallbackAnimation.value;
var dynamicColors = _colorCallbackAnimation!.value;
if (colors.length == dynamicColors.length) {
for (var i = 0; i < colors.length; i++) {
colors[i] = dynamicColors[i];
@ -158,7 +159,7 @@ class GradientStrokeContent extends BaseStrokeContent {
}
@override
void addValueCallback<T>(T property, LottieValueCallback<T> /*?*/ callback) {
void addValueCallback<T>(T property, LottieValueCallback<T>? callback) {
super.addValueCallback(property, callback);
if (property == LottieProperty.gradientColor) {
if (_colorCallbackAnimation != null) {
@ -169,8 +170,8 @@ class GradientStrokeContent extends BaseStrokeContent {
_colorCallbackAnimation = null;
} else {
_colorCallbackAnimation = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<List<Color>>);
_colorCallbackAnimation.addUpdateListener(onUpdateListener);
callback as LottieValueCallback<List<Color>>, <Color>[])
..addUpdateListener(onUpdateListener);
layer.addAnimation(_colorCallbackAnimation);
}
}

View File

@ -28,13 +28,13 @@ class PolystarContent implements PathContent, KeyPathElementContent {
final LottieDrawable lottieDrawable;
final PolystarShape _polystarShape;
final BaseKeyframeAnimation<dynamic, double> _pointsAnimation;
final BaseKeyframeAnimation<dynamic, Offset> _positionAnimation;
final BaseKeyframeAnimation<dynamic, double> _rotationAnimation;
final BaseKeyframeAnimation<dynamic, double> /*?*/ _innerRadiusAnimation;
final BaseKeyframeAnimation<dynamic, double> _outerRadiusAnimation;
final BaseKeyframeAnimation<dynamic, double> /*?*/ _innerRoundednessAnimation;
final BaseKeyframeAnimation<dynamic, double> _outerRoundednessAnimation;
final BaseKeyframeAnimation<Object, double> _pointsAnimation;
final BaseKeyframeAnimation<Object, Offset> _positionAnimation;
final BaseKeyframeAnimation<Object, double> _rotationAnimation;
final BaseKeyframeAnimation<Object, double>? _innerRadiusAnimation;
final BaseKeyframeAnimation<Object, double> _outerRadiusAnimation;
final BaseKeyframeAnimation<Object, double>? _innerRoundednessAnimation;
final BaseKeyframeAnimation<Object, double> _outerRoundednessAnimation;
final _trimPaths = CompoundTrimPathContent();
bool _isPathValid = false;
@ -47,11 +47,11 @@ class PolystarContent implements PathContent, KeyPathElementContent {
_outerRoundednessAnimation =
_polystarShape.outerRoundedness.createAnimation(),
_innerRadiusAnimation = _polystarShape.type == PolystarShapeType.star
? _polystarShape.innerRadius.createAnimation()
? _polystarShape.innerRadius!.createAnimation()
: null,
_innerRoundednessAnimation =
_polystarShape.type == PolystarShapeType.star
? _polystarShape.innerRoundedness.createAnimation()
? _polystarShape.innerRoundedness!.createAnimation()
: null {
layer.addAnimation(_pointsAnimation);
layer.addAnimation(_positionAnimation);
@ -69,8 +69,8 @@ class PolystarContent implements PathContent, KeyPathElementContent {
_outerRadiusAnimation.addUpdateListener(invalidate);
_outerRoundednessAnimation.addUpdateListener(invalidate);
if (_polystarShape.type == PolystarShapeType.star) {
_innerRadiusAnimation.addUpdateListener(invalidate);
_innerRoundednessAnimation.addUpdateListener(invalidate);
_innerRadiusAnimation!.addUpdateListener(invalidate);
_innerRoundednessAnimation!.addUpdateListener(invalidate);
}
}
@ -123,12 +123,11 @@ class PolystarContent implements PathContent, KeyPathElementContent {
}
@override
String get name => _polystarShape.name;
String? get name => _polystarShape.name;
void _createStarPath() {
var points = _pointsAnimation.value;
var currentAngle =
_rotationAnimation == null ? 0.0 : _rotationAnimation.value;
var currentAngle = _rotationAnimation.value;
// Start at +y instead of +x
currentAngle -= 90;
// convert to radians
@ -143,16 +142,13 @@ class PolystarContent implements PathContent, KeyPathElementContent {
var outerRadius = _outerRadiusAnimation.value;
//noinspection ConstantConditions
var innerRadius = _innerRadiusAnimation.value;
var innerRadius = _innerRadiusAnimation!.value;
var innerRoundedness = 0.0;
if (_innerRoundednessAnimation != null) {
innerRoundedness = _innerRoundednessAnimation.value / 100.0;
}
var outerRoundedness = 0.0;
if (_outerRoundednessAnimation != null) {
outerRoundedness = _outerRoundednessAnimation.value / 100.0;
innerRoundedness = _innerRoundednessAnimation!.value / 100.0;
}
var outerRoundedness = _outerRoundednessAnimation.value / 100.0;
double x;
double y;
@ -235,8 +231,7 @@ class PolystarContent implements PathContent, KeyPathElementContent {
void _createPolygonPath() {
var points = _pointsAnimation.value.floor();
var currentAngle =
_rotationAnimation == null ? 0.0 : _rotationAnimation.value;
var currentAngle = _rotationAnimation.value;
// Start at +y instead of +x
currentAngle -= 90;
// convert to radians
@ -297,7 +292,7 @@ class PolystarContent implements PathContent, KeyPathElementContent {
}
@override
void addValueCallback<T>(T property, LottieValueCallback<T> /*?*/ callback) {
void addValueCallback<T>(T property, LottieValueCallback<T>? callback) {
if (property == LottieProperty.polystarPoints) {
_pointsAnimation
.setValueCallback(callback as LottieValueCallback<double>);
@ -309,14 +304,14 @@ class PolystarContent implements PathContent, KeyPathElementContent {
.setValueCallback(callback as LottieValueCallback<Offset>);
} else if (property == LottieProperty.polystarInnerRadius &&
_innerRadiusAnimation != null) {
_innerRadiusAnimation
_innerRadiusAnimation!
.setValueCallback(callback as LottieValueCallback<double>);
} else if (property == LottieProperty.polystarOuterRadius) {
_outerRadiusAnimation
.setValueCallback(callback as LottieValueCallback<double>);
} else if (property == LottieProperty.polystarInnerRoundedness &&
_innerRoundednessAnimation != null) {
_innerRoundednessAnimation
_innerRoundednessAnimation!
.setValueCallback(callback as LottieValueCallback<double>);
} else if (property == LottieProperty.polystarOuterRoundedness) {
_outerRoundednessAnimation

View File

@ -21,12 +21,12 @@ class RectangleContent implements KeyPathElementContent, PathContent {
final _path = PathFactory.create();
@override
final String name;
final String? name;
final bool _hidden;
final LottieDrawable lottieDrawable;
final BaseKeyframeAnimation<dynamic, Offset> _positionAnimation;
final BaseKeyframeAnimation<dynamic, Offset> _sizeAnimation;
final BaseKeyframeAnimation<dynamic, double> _cornerRadiusAnimation;
final BaseKeyframeAnimation<Object, Offset> _positionAnimation;
final BaseKeyframeAnimation<Object, Offset> _sizeAnimation;
final BaseKeyframeAnimation<Object, double> _cornerRadiusAnimation;
final CompoundTrimPathContent _trimPaths = CompoundTrimPathContent();
bool _isPathValid = false;
@ -81,8 +81,7 @@ class RectangleContent implements KeyPathElementContent, PathContent {
var size = _sizeAnimation.value;
var halfWidth = size.dx / 2.0;
var halfHeight = size.dy / 2.0;
var radius =
_cornerRadiusAnimation == null ? 0.0 : _cornerRadiusAnimation.value;
var radius = _cornerRadiusAnimation.value;
var maxRadius = min(halfWidth, halfHeight);
if (radius > maxRadius) {
radius = maxRadius;
@ -164,7 +163,7 @@ class RectangleContent implements KeyPathElementContent, PathContent {
}
@override
void addValueCallback<T>(T property, LottieValueCallback<T> /*?*/ callback) {
void addValueCallback<T>(T property, LottieValueCallback<T>? callback) {
if (property == LottieProperty.rectangleSize) {
_sizeAnimation.setValueCallback(callback as LottieValueCallback<Offset>);
} else if (property == LottieProperty.position) {

View File

@ -33,7 +33,7 @@ class RepeaterContent
final BaseKeyframeAnimation<double, double> _copies;
final BaseKeyframeAnimation<double, double> _offset;
final TransformKeyframeAnimation _transform;
ContentGroup _contentGroup;
ContentGroup? _contentGroup;
RepeaterContent(this.lottieDrawable, this.layer, this._repeater)
: _copies = _repeater.copies.createAnimation(),
@ -83,16 +83,16 @@ class RepeaterContent
}
@override
String get name => _repeater.name;
String? get name => _repeater.name;
@override
void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
_contentGroup.setContents(contentsBefore, contentsAfter);
_contentGroup!.setContents(contentsBefore, contentsAfter);
}
@override
Path getPath() {
var contentPath = _contentGroup.getPath();
var contentPath = _contentGroup!.getPath();
_path.reset();
var copies = _copies.value;
var offset = _offset.value;
@ -104,23 +104,24 @@ class RepeaterContent
}
@override
void draw(Canvas canvas, Size size, Matrix4 parentMatrix, {int parentAlpha}) {
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
{required int parentAlpha}) {
var copies = _copies.value;
var offset = _offset.value;
var startOpacity = _transform.startOpacity.value / 100.0;
var endOpacity = _transform.endOpacity.value / 100.0;
var startOpacity = _transform.startOpacity!.value / 100.0;
var endOpacity = _transform.endOpacity!.value / 100.0;
for (var i = copies.toInt() - 1; i >= 0; i--) {
_matrix.set(parentMatrix);
_matrix.preConcat(_transform.getMatrixForRepeater(i + offset));
var newAlpha =
parentAlpha * lerpDouble(startOpacity, endOpacity, i / copies);
_contentGroup.draw(canvas, size, _matrix, parentAlpha: newAlpha.round());
parentAlpha * lerpDouble(startOpacity, endOpacity, i / copies)!;
_contentGroup!.draw(canvas, size, _matrix, parentAlpha: newAlpha.round());
}
}
@override
Rect getBounds(Matrix4 parentMatrix, {bool applyParents}) {
return _contentGroup.getBounds(parentMatrix, applyParents: applyParents);
Rect getBounds(Matrix4 parentMatrix, {required bool applyParents}) {
return _contentGroup!.getBounds(parentMatrix, applyParents: applyParents);
}
void _invalidate() {
@ -135,7 +136,7 @@ class RepeaterContent
}
@override
void addValueCallback<T>(T property, LottieValueCallback<T> /*?*/ callback) {
void addValueCallback<T>(T property, LottieValueCallback<T>? callback) {
if (_transform.applyValueCallback(property, callback)) {
return;
}

View File

@ -17,7 +17,7 @@ class ShapeContent implements PathContent {
final ShapePath _shape;
final LottieDrawable lottieDrawable;
final BaseKeyframeAnimation<dynamic, Path> _shapeAnimation;
final BaseKeyframeAnimation<Object, Path> _shapeAnimation;
bool _isPathValid = false;
final _trimPaths = CompoundTrimPathContent();
@ -48,7 +48,7 @@ class ShapeContent implements PathContent {
}
@override
String get name => _shape.name;
String? get name => _shape.name;
@override
Path getPath() {

View File

@ -11,10 +11,10 @@ import 'base_stroke_content.dart';
class StrokeContent extends BaseStrokeContent {
@override
final String name;
final String? name;
final bool _hidden;
final BaseKeyframeAnimation<Color, Color> _colorAnimation;
BaseKeyframeAnimation<ColorFilter, ColorFilter> /*?*/ _colorFilterAnimation;
BaseKeyframeAnimation<ColorFilter, ColorFilter?>? _colorFilterAnimation;
StrokeContent(
final LottieDrawable lottieDrawable, BaseLayer layer, ShapeStroke stroke)
@ -34,19 +34,20 @@ class StrokeContent extends BaseStrokeContent {
}
@override
void draw(Canvas canvas, Size size, Matrix4 parentMatrix, {int parentAlpha}) {
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
{required int parentAlpha}) {
if (_hidden) {
return;
}
paint.color = _colorAnimation.value.withAlpha(paint.color.alpha);
if (_colorFilterAnimation != null) {
paint.colorFilter = _colorFilterAnimation.value;
paint.colorFilter = _colorFilterAnimation!.value;
}
super.draw(canvas, size, parentMatrix, parentAlpha: parentAlpha);
}
@override
void addValueCallback<T>(T property, LottieValueCallback<T> /*?*/ callback) {
void addValueCallback<T>(T property, LottieValueCallback<T>? callback) {
super.addValueCallback(property, callback);
if (property == LottieProperty.strokeColor) {
_colorAnimation.setValueCallback(callback as LottieValueCallback<Color>);
@ -58,10 +59,9 @@ class StrokeContent extends BaseStrokeContent {
if (callback == null) {
_colorFilterAnimation = null;
} else {
_colorFilterAnimation =
ValueCallbackKeyframeAnimation<ColorFilter, ColorFilter>(
callback as LottieValueCallback<ColorFilter>);
_colorFilterAnimation.addUpdateListener(onUpdateListener);
_colorFilterAnimation = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<ColorFilter>, null)
..addUpdateListener(onUpdateListener);
layer.addAnimation(_colorAnimation);
}
}

View File

@ -5,13 +5,13 @@ import 'content.dart';
class TrimPathContent implements Content {
@override
final String name;
final String? name;
final bool hidden;
final _listeners = <void Function()>[];
final ShapeTrimPathType type;
final BaseKeyframeAnimation<dynamic, double> start;
final BaseKeyframeAnimation<dynamic, double> end;
final BaseKeyframeAnimation<dynamic, double> offset;
final ShapeTrimPathType? type;
final BaseKeyframeAnimation<Object, double> start;
final BaseKeyframeAnimation<Object, double> end;
final BaseKeyframeAnimation<Object, double> offset;
TrimPathContent(BaseLayer layer, ShapeTrimPath trimPath)
: name = trimPath.name,

View File

@ -5,16 +5,16 @@ import '../../value/lottie_value_callback.dart';
/// @param <K> Keyframe type
/// @param <A> Animation type
abstract class BaseKeyframeAnimation<K, A> {
abstract class BaseKeyframeAnimation<K extends Object, A extends Object?> {
// This is not a Set because we don't want to create an iterator object on every setProgress.
final listeners = <void Function()>[];
bool _isDiscrete = false;
final _KeyframesWrapper<K> _keyframesWrapper;
double _progress = 0;
LottieValueCallback<A> /*?*/ valueCallback;
LottieValueCallback<A>? valueCallback;
A /*?*/ _cachedGetValue;
A? _cachedGetValue;
double _cachedStartDelayProgress = -1.0;
double _cachedEndProgress = -1.0;
@ -85,7 +85,7 @@ abstract class BaseKeyframeAnimation<K, A> {
if (keyframe.isStatic) {
return 0.0;
}
return keyframe.interpolator.transform(getLinearCurrentKeyframeProgress());
return keyframe.interpolator!.transform(getLinearCurrentKeyframeProgress());
}
double getStartDelayProgress() {
@ -106,7 +106,7 @@ abstract class BaseKeyframeAnimation<K, A> {
var progress = getInterpolatedCurrentKeyframeProgress();
if (valueCallback == null &&
_keyframesWrapper.isCachedValueEnabled(progress)) {
return _cachedGetValue;
return _cachedGetValue!;
}
final keyframe = getCurrentKeyframe();
@ -125,9 +125,9 @@ abstract class BaseKeyframeAnimation<K, A> {
_progress = value;
}
void setValueCallback(LottieValueCallback<A> /*?*/ valueCallback) {
void setValueCallback(LottieValueCallback<A>? valueCallback) {
if (this.valueCallback != null) {
this.valueCallback.setAnimation(null);
this.valueCallback!.setAnimation(null);
}
this.valueCallback = valueCallback;
if (valueCallback != null) {
@ -240,8 +240,8 @@ class _SingleKeyframeWrapper<T> implements _KeyframesWrapper<T> {
class _KeyframesWrapperImpl<T> implements _KeyframesWrapper<T> {
final List<Keyframe<T>> keyframes;
Keyframe<T> _currentKeyframe;
Keyframe<T> _cachedCurrentKeyframe;
Keyframe<T>? _currentKeyframe;
Keyframe<T>? _cachedCurrentKeyframe;
double _cachedInterpolatedProgress = -1;
_KeyframesWrapperImpl(this.keyframes) {
@ -255,8 +255,8 @@ class _KeyframesWrapperImpl<T> implements _KeyframesWrapper<T> {
@override
bool isValueChanged(double progress) {
if (_currentKeyframe.containsProgress(progress)) {
return !_currentKeyframe.isStatic;
if (_currentKeyframe!.containsProgress(progress)) {
return !_currentKeyframe!.isStatic;
}
_currentKeyframe = findKeyframe(progress);
return true;
@ -281,7 +281,7 @@ class _KeyframesWrapperImpl<T> implements _KeyframesWrapper<T> {
@override
Keyframe<T> getCurrentKeyframe() {
return _currentKeyframe;
return _currentKeyframe!;
}
@override

View File

@ -15,7 +15,7 @@ class ColorKeyframeAnimation extends KeyframeAnimation<Color> {
var endColor = keyframe.endValue;
if (valueCallback != null) {
var value = valueCallback.getValueInternal(
var value = valueCallback!.getValueInternal(
keyframe.startFrame,
keyframe.endFrame,
startColor,
@ -29,6 +29,6 @@ class ColorKeyframeAnimation extends KeyframeAnimation<Color> {
}
return GammaEvaluator.evaluate(
keyframeProgress.clamp(0, 1).toDouble(), startColor, endColor);
keyframeProgress.clamp(0, 1).toDouble(), startColor!, endColor!);
}
}

View File

@ -12,7 +12,7 @@ class DoubleKeyframeAnimation extends KeyframeAnimation<double> {
}
if (valueCallback != null) {
var value = valueCallback.getValueInternal(
var value = valueCallback!.getValueInternal(
keyframe.startFrame,
keyframe.endFrame,
keyframe.startValue,
@ -25,6 +25,7 @@ class DoubleKeyframeAnimation extends KeyframeAnimation<double> {
}
}
return lerpDouble(keyframe.startValue, keyframe.endValue, keyframeProgress);
return lerpDouble(
keyframe.startValue, keyframe.endValue, keyframeProgress)!;
}
}

View File

@ -4,7 +4,7 @@ import '../../value/keyframe.dart';
import 'keyframe_animation.dart';
class GradientColorKeyframeAnimation extends KeyframeAnimation<GradientColor> {
GradientColor _gradientColor;
late GradientColor _gradientColor;
GradientColorKeyframeAnimation(List<Keyframe<GradientColor>> keyframes)
: super(keyframes) {
@ -18,7 +18,7 @@ class GradientColorKeyframeAnimation extends KeyframeAnimation<GradientColor> {
GradientColor getValue(
Keyframe<GradientColor> keyframe, double keyframeProgress) {
_gradientColor.lerp(
keyframe.startValue, keyframe.endValue, keyframeProgress);
keyframe.startValue!, keyframe.endValue!, keyframeProgress);
return _gradientColor;
}
}

View File

@ -12,7 +12,7 @@ class IntegerKeyframeAnimation extends KeyframeAnimation<int> {
}
if (valueCallback != null) {
var value = valueCallback.getValueInternal(
var value = valueCallback!.getValueInternal(
keyframe.startFrame,
keyframe.endFrame,
keyframe.startValue,
@ -25,7 +25,7 @@ class IntegerKeyframeAnimation extends KeyframeAnimation<int> {
}
}
return lerpDouble(keyframe.startValue, keyframe.endValue, keyframeProgress)
return lerpDouble(keyframe.startValue, keyframe.endValue, keyframeProgress)!
.round();
}
}

View File

@ -1,6 +1,7 @@
import '../../value/keyframe.dart';
import 'base_keyframe_animation.dart';
abstract class KeyframeAnimation<T> extends BaseKeyframeAnimation<T, T> {
abstract class KeyframeAnimation<T extends Object>
extends BaseKeyframeAnimation<T, T> {
KeyframeAnimation(List<Keyframe<T>> keyframes) : super(keyframes);
}

View File

@ -4,7 +4,7 @@ import '../../utils/utils.dart';
import '../../value/keyframe.dart';
class PathKeyframe extends Keyframe<Offset> {
Path _path;
Path? _path;
final Keyframe<Offset> _pointKeyFrame;
PathKeyframe(LottieComposition composition, Keyframe<Offset> keyframe)
@ -22,13 +22,13 @@ class PathKeyframe extends Keyframe<Offset> {
var equals =
endValue != null && startValue != null && startValue == endValue;
if (endValue != null && !equals) {
_path = Utils.createPath(
startValue, endValue, _pointKeyFrame.pathCp1, _pointKeyFrame.pathCp2);
_path = Utils.createPath(startValue!, endValue!, _pointKeyFrame.pathCp1,
_pointKeyFrame.pathCp2);
}
}
/// This will be null if the startValue and endValue are the same. */
Path /*?*/ getPath() {
Path? getPath() {
return _path;
}
}

View File

@ -4,8 +4,8 @@ import 'keyframe_animation.dart';
import 'path_keyframe.dart';
class PathKeyframeAnimation extends KeyframeAnimation<Offset> {
PathKeyframe _pathMeasureKeyframe;
PathMetric _pathMeasure;
PathKeyframe? _pathMeasureKeyframe;
late PathMetric _pathMeasure;
PathKeyframeAnimation(List<Keyframe<Offset>> keyframes) : super(keyframes);
@ -14,11 +14,11 @@ class PathKeyframeAnimation extends KeyframeAnimation<Offset> {
var pathKeyframe = keyframe as PathKeyframe;
var path = pathKeyframe.getPath();
if (path == null) {
return keyframe.startValue;
return keyframe.startValue!;
}
if (valueCallback != null) {
var value = valueCallback.getValueInternal(
var value = valueCallback!.getValueInternal(
pathKeyframe.startFrame,
pathKeyframe.endFrame,
pathKeyframe.startValue,
@ -37,7 +37,7 @@ class PathKeyframeAnimation extends KeyframeAnimation<Offset> {
}
return _pathMeasure
.getTangentForOffset(keyframeProgress * _pathMeasure.length)
.getTangentForOffset(keyframeProgress * _pathMeasure.length)!
.position;
}
}

View File

@ -15,7 +15,7 @@ class PointKeyframeAnimation extends KeyframeAnimation<Offset> {
var endPoint = keyframe.endValue;
if (valueCallback != null) {
var value = valueCallback.getValueInternal(
var value = valueCallback!.getValueInternal(
keyframe.startFrame,
keyframe.endFrame,
startPoint,
@ -28,6 +28,6 @@ class PointKeyframeAnimation extends KeyframeAnimation<Offset> {
}
}
return Offset.lerp(startPoint, endPoint, keyframeProgress);
return Offset.lerp(startPoint, endPoint, keyframeProgress)!;
}
}

View File

@ -14,8 +14,8 @@ class ShapeKeyframeAnimation extends BaseKeyframeAnimation<ShapeData, Path> {
@override
Path getValue(Keyframe<ShapeData> keyframe, double keyframeProgress) {
var startShapeData = keyframe.startValue;
var endShapeData = keyframe.endValue;
var startShapeData = keyframe.startValue!;
var endShapeData = keyframe.endValue!;
_tempShapeData.interpolateBetween(
startShapeData, endShapeData, keyframeProgress);

View File

@ -4,7 +4,7 @@ import 'base_keyframe_animation.dart';
class SplitDimensionPathKeyframeAnimation
extends BaseKeyframeAnimation<Offset, Offset> {
Offset _point;
late Offset _point;
final BaseKeyframeAnimation<double, double> _xAnimation;
final BaseKeyframeAnimation<double, double> _yAnimation;
@ -26,7 +26,7 @@ class SplitDimensionPathKeyframeAnimation
@override
Offset get value {
return getValue(null, 0);
return _point;
}
@override

View File

@ -9,6 +9,6 @@ class TextKeyframeAnimation extends KeyframeAnimation<DocumentData> {
@override
DocumentData getValue(
Keyframe<DocumentData> keyframe, double keyframeProgress) {
return keyframe.startValue;
return keyframe.startValue!;
}
}

View File

@ -30,25 +30,25 @@ class TransformKeyframeAnimation {
_endOpacity = animatableTransform.endOpacity?.createAnimation();
final _matrix = Matrix4.identity();
final Matrix4 _skewMatrix1;
final Matrix4 _skewMatrix2;
final Matrix4 _skewMatrix3;
final Matrix4? _skewMatrix1;
final Matrix4? _skewMatrix2;
final Matrix4? _skewMatrix3;
BaseKeyframeAnimation<Offset, Offset> /*?*/ _anchorPoint;
BaseKeyframeAnimation<Offset, Offset> /*?*/ _position;
BaseKeyframeAnimation<Offset, Offset> /*?*/ _scale;
BaseKeyframeAnimation<double, double> /*?*/ _rotation;
DoubleKeyframeAnimation /*?*/ _skew;
DoubleKeyframeAnimation /*?*/ _skewAngle;
BaseKeyframeAnimation<Offset, Offset>? _anchorPoint;
BaseKeyframeAnimation<Offset, Offset>? _position;
BaseKeyframeAnimation<Offset, Offset>? _scale;
BaseKeyframeAnimation<double, double>? _rotation;
DoubleKeyframeAnimation? _skew;
DoubleKeyframeAnimation? _skewAngle;
BaseKeyframeAnimation<int, int> /*?*/ _opacity;
BaseKeyframeAnimation<int, int> /*?*/ get opacity => _opacity;
BaseKeyframeAnimation<int, int>? _opacity;
BaseKeyframeAnimation<int, int>? get opacity => _opacity;
BaseKeyframeAnimation<double, double> /*?*/ _startOpacity;
BaseKeyframeAnimation<double, double> /*?*/ get startOpacity => _startOpacity;
BaseKeyframeAnimation<double, double>? _startOpacity;
BaseKeyframeAnimation<double, double>? get startOpacity => _startOpacity;
BaseKeyframeAnimation<double, double> /*?*/ _endOpacity;
BaseKeyframeAnimation<double, double> /*?*/ get endOpacity => _endOpacity;
BaseKeyframeAnimation<double, double>? _endOpacity;
BaseKeyframeAnimation<double, double>? get endOpacity => _endOpacity;
void addAnimationsToLayer(BaseLayer layer) {
layer.addAnimation(_opacity);
@ -91,14 +91,14 @@ class TransformKeyframeAnimation {
_matrix.reset();
if (_position != null) {
final position = _position.value;
final position = _position!.value;
if (position.dx != 0 || position.dy != 0) {
_matrix.translate(position.dx, position.dy);
}
}
if (_rotation != null) {
final rotation = _rotation.value;
final rotation = _rotation!.value;
if (rotation != 0) {
_matrix.rotateZ(rotation * pi / 180.0);
}
@ -106,46 +106,46 @@ class TransformKeyframeAnimation {
if (_skew != null) {
final mCos =
_skewAngle == null ? 0.0 : cos(radians(-_skewAngle.value + 90));
_skewAngle == null ? 0.0 : cos(radians(-_skewAngle!.value + 90));
final mSin =
_skewAngle == null ? 1.0 : sin(radians(-_skewAngle.value + 90));
final aTan = tan(radians(_skew.value));
_skewAngle == null ? 1.0 : sin(radians(-_skewAngle!.value + 90));
final aTan = tan(radians(_skew!.value));
_skewMatrix1.setValues(
_skewMatrix1!.setValues(
mCos, mSin, 0, 0,
-mSin, mCos, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1, //
);
_skewMatrix2.setValues(
_skewMatrix2!.setValues(
1, 0, 0, 0,
aTan, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1, //
);
_skewMatrix3.setValues(
_skewMatrix3!.setValues(
mCos, -mSin, 0, 0,
mSin, mCos, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1, //
);
_skewMatrix2.multiply(_skewMatrix1);
_skewMatrix3.multiply(_skewMatrix2);
_matrix.multiply(_skewMatrix3);
_skewMatrix2!.multiply(_skewMatrix1!);
_skewMatrix3!.multiply(_skewMatrix2!);
_matrix.multiply(_skewMatrix3!);
}
if (_scale != null) {
final scale = _scale.value;
final scale = _scale!.value;
if (scale.dx != 1 || scale.dy != 1) {
_matrix.scale(scale.dx, scale.dy);
}
}
if (_anchorPoint != null) {
final anchorPoint = _anchorPoint.value;
final anchorPoint = _anchorPoint!.value;
if (anchorPoint.dx != 0 || anchorPoint.dy != 0) {
_matrix.translate(-anchorPoint.dx, -anchorPoint.dy);
}
@ -171,7 +171,7 @@ class TransformKeyframeAnimation {
}
if (_rotation != null) {
var rotation = _rotation.value;
var rotation = _rotation!.value;
var anchorPoint = _anchorPoint?.value;
_matrix.rotate(
Vector3(anchorPoint == null ? 0.0 : anchorPoint.dx,
@ -182,62 +182,64 @@ class TransformKeyframeAnimation {
return _matrix;
}
bool applyValueCallback<T>(T property, LottieValueCallback<T> callback) {
bool applyValueCallback<T>(T property, LottieValueCallback<T>? callback) {
if (property == LottieProperty.transformAnchorPoint) {
if (_anchorPoint == null) {
_anchorPoint = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<Offset>, Offset.zero);
callback as LottieValueCallback<Offset>?, Offset.zero);
} else {
_anchorPoint.setValueCallback(callback as LottieValueCallback<Offset>);
_anchorPoint!
.setValueCallback(callback as LottieValueCallback<Offset>?);
}
} else if (property == LottieProperty.transformPosition) {
if (_position == null) {
_position = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<Offset>, Offset.zero);
callback as LottieValueCallback<Offset>?, Offset.zero);
} else {
_position.setValueCallback(callback as LottieValueCallback<Offset>);
_position!.setValueCallback(callback as LottieValueCallback<Offset>?);
}
} else if (property == LottieProperty.transformScale) {
if (_scale == null) {
_scale = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<Offset>, Offset(1, 1));
callback as LottieValueCallback<Offset>?, Offset(1, 1));
} else {
_scale.setValueCallback(callback as LottieValueCallback<Offset>);
_scale!.setValueCallback(callback as LottieValueCallback<Offset>?);
}
} else if (property == LottieProperty.transformRotation) {
if (_rotation == null) {
_rotation = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<double>, 0.0);
callback as LottieValueCallback<double>?, 0.0);
} else {
_rotation.setValueCallback(callback as LottieValueCallback<double>);
_rotation!.setValueCallback(callback as LottieValueCallback<double>?);
}
} else if (property == LottieProperty.transformOpacity) {
if (_opacity == null) {
_opacity = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<int>, 100);
callback as LottieValueCallback<int>?, 100);
} else {
_opacity.setValueCallback(callback as LottieValueCallback<int>);
_opacity!.setValueCallback(callback as LottieValueCallback<int>?);
}
} else if (property == LottieProperty.transformStartOpacity) {
if (_startOpacity == null) {
_startOpacity = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<double>, 100);
callback as LottieValueCallback<double>?, 100);
} else {
_startOpacity.setValueCallback(callback as LottieValueCallback<double>);
_startOpacity!
.setValueCallback(callback as LottieValueCallback<double>?);
}
} else if (property == LottieProperty.transformEndOpacity) {
if (_endOpacity == null) {
_endOpacity = ValueCallbackKeyframeAnimation(
callback as LottieValueCallback<double>, 100);
callback as LottieValueCallback<double>?, 100);
} else {
_endOpacity.setValueCallback(callback as LottieValueCallback<double>);
_endOpacity!.setValueCallback(callback as LottieValueCallback<double>?);
}
} else if (property == LottieProperty.transformSkew) {
_skew ??= DoubleKeyframeAnimation([Keyframe.nonAnimated(0.0)]);
_skew.setValueCallback(callback as LottieValueCallback<double>);
_skew!.setValueCallback(callback as LottieValueCallback<double>?);
} else if (property == LottieProperty.transformSkewAngle) {
_skewAngle ??= DoubleKeyframeAnimation([Keyframe.nonAnimated(0.0)]);
_skewAngle.setValueCallback(callback as LottieValueCallback<double>);
_skewAngle!.setValueCallback(callback as LottieValueCallback<double>?);
} else {
return false;
}

View File

@ -2,11 +2,12 @@ import '../../value/keyframe.dart';
import '../../value/lottie_value_callback.dart';
import 'base_keyframe_animation.dart';
class ValueCallbackKeyframeAnimation<K, A> extends BaseKeyframeAnimation<K, A> {
class ValueCallbackKeyframeAnimation<K extends Object, A extends Object?>
extends BaseKeyframeAnimation<K, A> {
final A valueCallbackValue;
ValueCallbackKeyframeAnimation(LottieValueCallback<A> valueCallback,
[A /*?*/ valueCallbackValue])
ValueCallbackKeyframeAnimation(
LottieValueCallback<A>? valueCallback, A valueCallbackValue)
: valueCallbackValue = valueCallbackValue,
super([]) {
setValueCallback(valueCallback);
@ -33,7 +34,7 @@ class ValueCallbackKeyframeAnimation<K, A> extends BaseKeyframeAnimation<K, A> {
@override
A get value {
return valueCallback.getValueInternal(0.0, 0.0, valueCallbackValue,
return valueCallback!.getValueInternal(0.0, 0.0, valueCallbackValue,
valueCallbackValue, progress, progress, progress) ??
valueCallbackValue;
}

View File

@ -1,6 +1,7 @@
import 'dart:math';
import 'dart:typed_data';
import 'package:archive/archive.dart';
import 'package:collection/collection.dart' show IterableExtension;
import 'package:flutter/widgets.dart';
import 'package:path/path.dart' as p;
import 'frame_rate.dart';
@ -15,43 +16,31 @@ import 'parser/moshi/json_reader.dart';
import 'performance_tracker.dart';
import 'providers/load_image.dart';
void internalInit(
LottieComposition composition,
Rectangle<int> bounds,
double startFrame,
double endFrame,
double frameRate,
List<Layer> layers,
Map<int, Layer> layerMap,
Map<String, List<Layer>> precomps,
Map<String, LottieImageAsset> images,
Map<int, FontCharacter> characters,
Map<String, Font> fonts,
List<Marker> markers) {
assert(startFrame != endFrame, 'startFrame == endFrame ($startFrame)');
assert(frameRate > 0, 'invalid framerate: $frameRate');
composition
.._bounds = bounds
.._startFrame = startFrame
.._endFrame = endFrame
.._frameRate = frameRate
.._layers = layers
.._layerMap = layerMap
.._precomps = precomps
.._images = images
.._characters = characters
.._fonts = fonts
.._markers = markers;
class CompositionParameters {
MutableRectangle<int> bounds = MutableRectangle<int>(0, 0, 0, 0);
double startFrame = 0.0;
double endFrame = 0;
double frameRate = 0;
final layers = <Layer>[];
final layerMap = <int, Layer>{};
final precomps = <String, List<Layer>>{};
final images = <String, LottieImageAsset>{};
final characters = <int, FontCharacter>{};
final fonts = <String, Font>{};
final markers = <Marker>[];
static CompositionParameters forComposition(LottieComposition composition) =>
composition._parameters;
}
class LottieComposition {
static Future<LottieComposition> fromByteData(ByteData data, {String name}) {
static Future<LottieComposition> fromByteData(ByteData data, {String? name}) {
return fromBytes(data.buffer.asUint8List(), name: name);
}
static Future<LottieComposition> fromBytes(Uint8List bytes,
{String name}) async {
Archive archive;
{String? name}) async {
Archive? archive;
if (bytes[0] == 0x50 && bytes[1] == 0x4B) {
archive = ZipDecoder().decodeBytes(bytes);
var jsonFile = archive.files.firstWhere((e) => e.name.endsWith('.json'));
@ -64,9 +53,8 @@ class LottieComposition {
if (archive != null) {
for (var image in composition.images.values) {
var imagePath = p.posix.join(image.dirName, image.fileName);
var found = archive.files.firstWhere(
(f) => f.name.toLowerCase() == imagePath.toLowerCase(),
orElse: () => null);
var found = archive.files.firstWhereOrNull(
(f) => f.name.toLowerCase() == imagePath.toLowerCase());
if (found != null) {
image.loadedImage = await loadImage(
composition, image, MemoryImage(found.content as Uint8List));
@ -79,23 +67,13 @@ class LottieComposition {
LottieComposition._(this.name);
final String name;
final String? name;
final _performanceTracker = PerformanceTracker();
// This is stored as a set to avoid duplicates.
final _warnings = <String>{};
Map<String, List<Layer>> _precomps;
Map<String, LottieImageAsset> _images;
/// Map of font names to fonts */
Map<String, Font> _fonts;
List<Marker> _markers;
Map<int, FontCharacter> _characters;
Map<int, Layer> _layerMap;
List<Layer> _layers;
Rectangle<int> _bounds;
double _startFrame;
double _endFrame;
double _frameRate;
final _parameters = CompositionParameters();
/// Used to determine if an animation can be drawn with hardware acceleration.
bool hasDashPattern = false;
@ -106,7 +84,7 @@ class LottieComposition {
int _maskAndMatteCount = 0;
void addWarning(String warning) {
var prefix = name != null && name.isNotEmpty ? '$name: ' : '';
var prefix = name != null && name!.isNotEmpty ? '$name: ' : '';
logger.warning('$prefix$warning');
_warnings.add(warning);
}
@ -127,39 +105,39 @@ class LottieComposition {
PerformanceTracker get performanceTracker => _performanceTracker;
Layer layerModelForId(int id) {
return _layerMap[id];
Layer? layerModelForId(int id) {
return _parameters.layerMap[id];
}
Rectangle<int> get bounds => _bounds;
Rectangle<int> get bounds => _parameters.bounds;
Duration get duration {
return Duration(milliseconds: (seconds * 1000).round());
}
double get seconds => durationFrames / _frameRate;
double get seconds => durationFrames / frameRate;
double get startFrame => _startFrame;
double get startFrame => _parameters.startFrame;
double get endFrame => _endFrame;
double get endFrame => _parameters.endFrame;
double get frameRate => _frameRate;
double get frameRate => _parameters.frameRate;
List<Layer> get layers => _layers;
List<Layer> get layers => _parameters.layers;
List<Layer> /*?*/ getPrecomps(String id) {
return _precomps[id];
List<Layer>? getPrecomps(String? id) {
return _parameters.precomps[id];
}
Map<int, FontCharacter> get characters => _characters;
Map<int, FontCharacter> get characters => _parameters.characters;
Map<String, Font> get fonts => _fonts;
Map<String, Font> get fonts => _parameters.fonts;
List<Marker> get markers => _markers;
List<Marker> get markers => _parameters.markers;
Marker /*?*/ getMarker(String markerName) {
for (var i = 0; i < _markers.length; i++) {
var marker = _markers[i];
Marker? getMarker(String markerName) {
for (var i = 0; i < markers.length; i++) {
var marker = markers[i];
if (marker.matchesName(markerName)) {
return marker;
}
@ -168,20 +146,20 @@ class LottieComposition {
}
bool get hasImages {
return _images.isNotEmpty;
return images.isNotEmpty;
}
Map<String, LottieImageAsset> get images {
return _images;
return _parameters.images;
}
double get durationFrames {
return _endFrame - _startFrame;
return endFrame - startFrame;
}
/// Returns a "rounded" progress value according to the frameRate
double roundProgress(double progress, {@required FrameRate frameRate}) {
num fps;
double roundProgress(double progress, {required FrameRate frameRate}) {
num? fps;
if (frameRate == FrameRate.max) {
return progress;
} else if (frameRate == FrameRate.composition) {
@ -200,7 +178,7 @@ class LottieComposition {
@override
String toString() {
final sb = StringBuffer('LottieComposition:\n');
for (var layer in _layers) {
for (var layer in layers) {
sb.write(layer.toStringWithPrefix('\t'));
}
return sb.toString();

View File

@ -3,8 +3,8 @@ import 'dart:developer';
class L {
static final int _maxDepth = 20;
static bool _traceEnabled = false;
static List<String> _sections;
static List<int> _startTimeNs;
static late List<String?> _sections;
static late List<int> _startTimeNs;
static int _traceDepth = 0;
static int _depthPastMaxDepth = 0;

View File

@ -15,20 +15,20 @@ import 'providers/load_image.dart';
/// [repeat] and [reverse].
class Lottie extends StatefulWidget {
Lottie({
Key key,
@required this.composition,
Key? key,
required this.composition,
this.controller,
this.width,
this.height,
this.alignment,
this.fit,
bool animate,
bool? animate,
this.frameRate,
bool repeat,
bool reverse,
bool? repeat,
bool? reverse,
this.delegates,
this.options,
bool addRepaintBoundary,
bool? addRepaintBoundary,
}) : animate = animate ?? true,
reverse = reverse ?? false,
repeat = repeat ?? true,
@ -38,24 +38,24 @@ class Lottie extends StatefulWidget {
/// Creates a widget that displays an [LottieComposition] obtained from an [AssetBundle].
static LottieBuilder asset(
String name, {
Animation<double> controller,
bool animate,
FrameRate frameRate,
bool repeat,
bool reverse,
LottieDelegates delegates,
LottieOptions options,
void Function(LottieComposition) onLoaded,
LottieImageProviderFactory imageProviderFactory,
Key key,
AssetBundle bundle,
LottieFrameBuilder frameBuilder,
double width,
double height,
BoxFit fit,
Alignment alignment,
String package,
bool addRepaintBoundary,
Animation<double>? controller,
bool? animate,
FrameRate? frameRate,
bool? repeat,
bool? reverse,
LottieDelegates? delegates,
LottieOptions? options,
void Function(LottieComposition)? onLoaded,
LottieImageProviderFactory? imageProviderFactory,
Key? key,
AssetBundle? bundle,
LottieFrameBuilder? frameBuilder,
double? width,
double? height,
BoxFit? fit,
Alignment? alignment,
String? package,
bool? addRepaintBoundary,
}) =>
LottieBuilder.asset(
name,
@ -82,22 +82,22 @@ class Lottie extends StatefulWidget {
/// Creates a widget that displays an [LottieComposition] obtained from a [File].
static LottieBuilder file(
Object /*io.File|html.File*/ file, {
Animation<double> controller,
FrameRate frameRate,
bool animate,
bool repeat,
bool reverse,
LottieDelegates delegates,
LottieOptions options,
LottieImageProviderFactory imageProviderFactory,
void Function(LottieComposition) onLoaded,
Key key,
LottieFrameBuilder frameBuilder,
double width,
double height,
BoxFit fit,
Alignment alignment,
bool addRepaintBoundary,
Animation<double>? controller,
FrameRate? frameRate,
bool? animate,
bool? repeat,
bool? reverse,
LottieDelegates? delegates,
LottieOptions? options,
LottieImageProviderFactory? imageProviderFactory,
void Function(LottieComposition)? onLoaded,
Key? key,
LottieFrameBuilder? frameBuilder,
double? width,
double? height,
BoxFit? fit,
Alignment? alignment,
bool? addRepaintBoundary,
}) =>
LottieBuilder.file(
file,
@ -122,22 +122,22 @@ class Lottie extends StatefulWidget {
/// Creates a widget that displays an [LottieComposition] obtained from a [Uint8List].
static LottieBuilder memory(
Uint8List bytes, {
Animation<double> controller,
FrameRate frameRate,
bool animate,
bool repeat,
bool reverse,
LottieDelegates delegates,
LottieOptions options,
LottieImageProviderFactory imageProviderFactory,
void Function(LottieComposition) onLoaded,
Key key,
LottieFrameBuilder frameBuilder,
double width,
double height,
BoxFit fit,
Alignment alignment,
bool addRepaintBoundary,
Animation<double>? controller,
FrameRate? frameRate,
bool? animate,
bool? repeat,
bool? reverse,
LottieDelegates? delegates,
LottieOptions? options,
LottieImageProviderFactory? imageProviderFactory,
void Function(LottieComposition)? onLoaded,
Key? key,
LottieFrameBuilder? frameBuilder,
double? width,
double? height,
BoxFit? fit,
Alignment? alignment,
bool? addRepaintBoundary,
}) =>
LottieBuilder.memory(
bytes,
@ -162,22 +162,22 @@ class Lottie extends StatefulWidget {
/// Creates a widget that displays an [LottieComposition] obtained from the network.
static LottieBuilder network(
String url, {
Animation<double> controller,
FrameRate frameRate,
bool animate,
bool repeat,
bool reverse,
LottieDelegates delegates,
LottieOptions options,
LottieImageProviderFactory imageProviderFactory,
void Function(LottieComposition) onLoaded,
Key key,
LottieFrameBuilder frameBuilder,
double width,
double height,
BoxFit fit,
Alignment alignment,
bool addRepaintBoundary,
Animation<double>? controller,
FrameRate? frameRate,
bool? animate,
bool? repeat,
bool? reverse,
LottieDelegates? delegates,
LottieOptions? options,
LottieImageProviderFactory? imageProviderFactory,
void Function(LottieComposition)? onLoaded,
Key? key,
LottieFrameBuilder? frameBuilder,
double? width,
double? height,
BoxFit? fit,
Alignment? alignment,
bool? addRepaintBoundary,
}) =>
LottieBuilder.network(
url,
@ -201,12 +201,12 @@ class Lottie extends StatefulWidget {
/// The Lottie composition to animate.
/// It could be parsed asynchronously with `LottieComposition.fromBytes`.
final LottieComposition composition;
final LottieComposition? composition;
/// The animation controller to animate the Lottie animation.
/// If null, a controller is automatically created by this class and is configured
/// with the properties [animate], [reverse]
final Animation<double> controller;
final Animation<double>? controller;
/// The number of frames per second to render.
/// Use `FrameRate.composition` to use the original frame rate of the Lottie composition (default)
@ -214,7 +214,7 @@ class Lottie extends StatefulWidget {
///
/// The advantage of using a low frame rate is to preserve the device battery
/// by doing less rendering work.
final FrameRate frameRate;
final FrameRate? frameRate;
/// If no controller is specified, this value indicate whether or not the
/// Lottie animation should be played automatically (default to true).
@ -237,16 +237,16 @@ class Lottie extends StatefulWidget {
///
/// If null, the composition will pick a size that best preserves its intrinsic
/// aspect ratio.
final double width;
final double? width;
/// If non-null, require the composition to have this height.
///
/// If null, the composition will pick a size that best preserves its intrinsic
/// aspect ratio.
final double height;
final double? height;
/// How to inscribe the Lottie composition into the space allocated during layout.
final BoxFit fit;
final BoxFit? fit;
/// How to align the composition within its bounds.
///
@ -266,18 +266,18 @@ class Lottie extends StatefulWidget {
/// specify an [AlignmentGeometry].
/// * [AlignmentDirectional], like [Alignment] for specifying alignments
/// relative to text direction.
final AlignmentGeometry alignment;
final AlignmentGeometry? alignment;
/// A group of callbacks to further customize the lottie animation.
/// - A [text] delegate to dynamically change some text displayed in the animation
/// - A value callback to change the properties of the animation at runtime.
/// - A text style factory to map between a font family specified in the animation
/// and the font family in your assets.
final LottieDelegates delegates;
final LottieDelegates? delegates;
/// Some options to enable/disable some feature of Lottie
/// - enableMergePaths: Enable merge path support
final LottieOptions options;
final LottieOptions? options;
/// Indicate to automatically add a `RepaintBoundary` widget around the animation.
/// This allows to optimize the app performance by isolating the animation in its
@ -296,7 +296,7 @@ class Lottie extends StatefulWidget {
}
class _LottieState extends State<Lottie> with TickerProviderStateMixin {
AnimationController _autoAnimation;
late AnimationController _autoAnimation;
@override
void initState() {

View File

@ -16,7 +16,7 @@ import 'providers/network_provider.dart';
typedef LottieFrameBuilder = Widget Function(
BuildContext context,
Widget child,
LottieComposition composition,
LottieComposition? composition,
);
/// A widget that displays a Lottie animation.
@ -33,8 +33,8 @@ typedef LottieFrameBuilder = Widget Function(
///
class LottieBuilder extends StatefulWidget {
const LottieBuilder({
Key key,
@required this.lottie,
Key? key,
required this.lottie,
this.controller,
this.frameRate,
this.animate,
@ -49,13 +49,12 @@ class LottieBuilder extends StatefulWidget {
this.fit,
this.alignment,
this.addRepaintBoundary,
}) : assert(lottie != null),
super(key: key);
}) : super(key: key);
/// Creates a widget that displays an [LottieComposition] obtained from the network.
LottieBuilder.network(
String src, {
Map<String, String> headers,
Map<String, String>? headers,
this.controller,
this.frameRate,
this.animate,
@ -63,9 +62,9 @@ class LottieBuilder extends StatefulWidget {
this.repeat,
this.delegates,
this.options,
LottieImageProviderFactory imageProviderFactory,
LottieImageProviderFactory? imageProviderFactory,
this.onLoaded,
Key key,
Key? key,
this.frameBuilder,
this.width,
this.height,
@ -95,9 +94,9 @@ class LottieBuilder extends StatefulWidget {
this.repeat,
this.delegates,
this.options,
LottieImageProviderFactory imageProviderFactory,
LottieImageProviderFactory? imageProviderFactory,
this.onLoaded,
Key key,
Key? key,
this.frameBuilder,
this.width,
this.height,
@ -117,16 +116,16 @@ class LottieBuilder extends StatefulWidget {
this.repeat,
this.delegates,
this.options,
LottieImageProviderFactory imageProviderFactory,
LottieImageProviderFactory? imageProviderFactory,
this.onLoaded,
Key key,
AssetBundle bundle,
Key? key,
AssetBundle? bundle,
this.frameBuilder,
this.width,
this.height,
this.fit,
this.alignment,
String package,
String? package,
this.addRepaintBoundary,
}) : lottie = AssetLottie(name,
bundle: bundle,
@ -144,9 +143,9 @@ class LottieBuilder extends StatefulWidget {
this.repeat,
this.delegates,
this.options,
LottieImageProviderFactory imageProviderFactory,
LottieImageProviderFactory? imageProviderFactory,
this.onLoaded,
Key key,
Key? key,
this.frameBuilder,
this.width,
this.height,
@ -164,45 +163,45 @@ class LottieBuilder extends StatefulWidget {
/// A callback called when the LottieComposition has been loaded.
/// You can use this callback to set the correct duration on the AnimationController
/// with `composition.duration`
final void Function(LottieComposition) onLoaded;
final void Function(LottieComposition)? onLoaded;
/// The animation controller of the Lottie animation.
/// The animated value will be mapped to the `progress` property of the
/// Lottie animation.
final Animation<double> controller;
final Animation<double>? controller;
/// The number of frames per second to render.
/// Use `FrameRate.composition` to use the original frame rate of the Lottie composition (default)
/// Use `FrameRate.max` to advance the animation progression at every frame.
final FrameRate frameRate;
final FrameRate? frameRate;
/// If no controller is specified, this value indicate whether or not the
/// Lottie animation should be played automatically (default to true).
/// If there is an animation controller specified, this property has no effect.
///
/// See [repeat] to control whether the animation should repeat.
final bool animate;
final bool? animate;
/// Specify that the automatic animation should repeat in a loop (default to true).
/// The property has no effect if [animate] is false or [controller] is not null.
final bool repeat;
final bool? repeat;
/// Specify that the automatic animation should repeat in a loop in a "reverse"
/// mode (go from start to end and then continuously from end to start).
/// It default to false.
/// The property has no effect if [animate] is false, [repeat] is false or [controller] is not null.
final bool reverse;
final bool? reverse;
/// A group of options to further customize the lottie animation.
/// - A [text] delegate to dynamically change some text displayed in the animation
/// - A value callback to change the properties of the animation at runtime.
/// - A text style factory to map between a font family specified in the animation
/// and the font family in your assets.
final LottieDelegates delegates;
final LottieDelegates? delegates;
/// Some options to enable/disable some feature of Lottie
/// - enableMergePaths: Enable merge path support
final LottieOptions options;
final LottieOptions? options;
/// A builder function responsible for creating the widget that represents
/// this lottie animation.
@ -277,7 +276,7 @@ class LottieBuilder extends StatefulWidget {
/// ```
/// {@end-tool}
///
final LottieFrameBuilder frameBuilder;
final LottieFrameBuilder? frameBuilder;
/// If non-null, require the lottie animation to have this width.
///
@ -289,7 +288,7 @@ class LottieBuilder extends StatefulWidget {
/// layout constraints, so that the animation does not change size as it loads.
/// Consider using [fit] to adapt the animation's rendering to fit the given width
/// and height if the exact animation dimensions are not known in advance.
final double width;
final double? width;
/// If non-null, require the lottie animation to have this height.
///
@ -301,13 +300,13 @@ class LottieBuilder extends StatefulWidget {
/// layout constraints, so that the animation does not change size as it loads.
/// Consider using [fit] to adapt the animation's rendering to fit the given width
/// and height if the exact animation dimensions are not known in advance.
final double height;
final double? height;
/// How to inscribe the animation into the space allocated during layout.
///
/// The default varies based on the other fields. See the discussion at
/// [paintImage].
final BoxFit fit;
final BoxFit? fit;
/// How to align the animation within its bounds.
///
@ -334,14 +333,14 @@ class LottieBuilder extends StatefulWidget {
/// specify an [AlignmentGeometry].
/// * [AlignmentDirectional], like [Alignment] for specifying alignments
/// relative to text direction.
final AlignmentGeometry alignment;
final AlignmentGeometry? alignment;
/// Indicate to automatically add a `RepaintBoundary` widget around the animation.
/// This allows to optimize the app performance by isolating the animation in its
/// own `Layer`.
///
/// This property is `true` by default.
final bool addRepaintBoundary;
final bool? addRepaintBoundary;
@override
_LottieBuilderState createState() => _LottieBuilderState();
@ -361,7 +360,7 @@ class LottieBuilder extends StatefulWidget {
}
class _LottieBuilderState extends State<LottieBuilder> {
Future<LottieComposition> _loadingFuture;
Future<LottieComposition>? _loadingFuture;
@override
void initState() {
@ -382,11 +381,14 @@ class _LottieBuilderState extends State<LottieBuilder> {
void _load() {
var provider = widget.lottie;
_loadingFuture = widget.lottie.load().then((composition) {
print('Loaded');
if (mounted && widget.onLoaded != null && widget.lottie == provider) {
widget.onLoaded(composition);
widget.onLoaded!(composition);
}
return composition;
}, onError: (Object e, StackTrace t) {
print('Load error $e $t');
});
}
@ -397,7 +399,7 @@ class _LottieBuilderState extends State<LottieBuilder> {
builder: (context, snapshot) {
if (snapshot.hasError) {
if (kDebugMode) {
return ErrorWidget(snapshot.error);
return ErrorWidget(snapshot.error!);
}
}
@ -420,7 +422,7 @@ class _LottieBuilderState extends State<LottieBuilder> {
);
if (widget.frameBuilder != null) {
result = widget.frameBuilder(context, result, composition);
result = widget.frameBuilder!(context, result, composition);
}
return result;

View File

@ -11,7 +11,7 @@ class LottieDelegates {
/// Specify a callback to dynamically changes the text displayed in the lottie
/// animation.
/// For instance, this is useful when you want to translate the text in the animation.
final String Function(String) /*?*/ text;
final String Function(String)? text;
/// A callback to map between a font family specified in the json animation
/// with the font family in your assets.
@ -24,7 +24,7 @@ class LottieDelegates {
/// Given an object containing the font family and style specified in the json
/// return a configured `TextStyle` that will be used as the base style when
/// painting the text.
final TextStyle Function(LottieFontStyle) textStyle;
final TextStyle Function(LottieFontStyle)? textStyle;
/// A list of value delegates to dynamically modify the animation
/// properties at runtime.
@ -41,13 +41,13 @@ class LottieDelegates {
/// ),
/// );
/// ```
final List<ValueDelegate> values;
final List<ValueDelegate>? values;
//TODO(xha): imageDelegate to change the image to display?
LottieDelegates({
this.text,
TextStyle Function(LottieFontStyle) textStyle,
TextStyle Function(LottieFontStyle)? textStyle,
this.values,
}) : textStyle = textStyle;

View File

@ -1,4 +1,5 @@
import 'dart:ui' as ui;
import 'package:collection/collection.dart' show IterableExtension;
import 'package:flutter/rendering.dart';
import 'package:vector_math/vector_math_64.dart';
import 'composition.dart';
@ -12,9 +13,9 @@ import 'value_delegate.dart';
class LottieDrawable {
final LottieComposition composition;
final _matrix = Matrix4.identity();
CompositionLayer _compositionLayer;
late CompositionLayer _compositionLayer;
final Size size;
LottieDelegates _delegates;
LottieDelegates? _delegates;
bool _isDirty = true;
final bool enableMergePaths;
@ -22,7 +23,7 @@ class LottieDrawable {
bool antiAliasingSuggested = true;
LottieDrawable(this.composition,
{LottieDelegates delegates, bool enableMergePaths})
{LottieDelegates? delegates, bool? enableMergePaths})
: size = Size(composition.bounds.width.toDouble(),
composition.bounds.height.toDouble()),
enableMergePaths = enableMergePaths ?? false {
@ -48,8 +49,8 @@ class LottieDrawable {
}
double get progress => _progress ?? 0.0;
double _progress;
bool setProgress(double value, {FrameRate frameRate}) {
double? _progress;
bool setProgress(double value, {FrameRate? frameRate}) {
frameRate ??= FrameRate.composition;
var roundedProgress =
composition.roundProgress(value, frameRate: frameRate);
@ -63,8 +64,8 @@ class LottieDrawable {
}
}
LottieDelegates get delegates => _delegates;
set delegates(LottieDelegates delegates) {
LottieDelegates? get delegates => _delegates;
set delegates(LottieDelegates? delegates) {
if (_delegates != delegates) {
_delegates = delegates;
_updateValueDelegates(delegates?.values);
@ -75,7 +76,7 @@ class LottieDrawable {
return delegates?.text == null && composition.characters.isNotEmpty;
}
ui.Image getImageAsset(String ref) {
ui.Image? getImageAsset(String? ref) {
var imageAsset = composition.images[ref];
if (imageAsset != null) {
return imageAsset.loadedImage;
@ -90,7 +91,7 @@ class LottieDrawable {
}
List<ValueDelegate> _valueDelegates = <ValueDelegate>[];
void _updateValueDelegates(List<ValueDelegate> newDelegates) {
void _updateValueDelegates(List<ValueDelegate>? newDelegates) {
if (identical(_valueDelegates, newDelegates)) return;
newDelegates ??= const [];
@ -99,14 +100,14 @@ class LottieDrawable {
for (var newDelegate in newDelegates) {
var existingDelegate = _valueDelegates
.firstWhere((f) => f.isSameProperty(newDelegate), orElse: () => null);
.firstWhereOrNull((f) => f.isSameProperty(newDelegate));
if (existingDelegate != null) {
var resolved = internalResolved(existingDelegate);
resolved.updateDelegate(newDelegate);
delegates.add(existingDelegate);
} else {
var keyPaths = _resolveKeyPath(KeyPath(newDelegate.keyPath));
var resolvedValueDelegate = internalResolve(newDelegate, keyPaths);
var resolvedValueDelegate = internalResolve(newDelegate, keyPaths)!;
resolvedValueDelegate.addValueCallback(this);
delegates.add(newDelegate);
}
@ -132,7 +133,8 @@ class LottieDrawable {
return keyPaths;
}
void draw(ui.Canvas canvas, ui.Rect rect, {BoxFit fit, Alignment alignment}) {
void draw(ui.Canvas canvas, ui.Rect rect,
{BoxFit? fit, Alignment? alignment}) {
if (rect.isEmpty) {
return;
}
@ -165,5 +167,5 @@ class LottieDrawable {
class LottieFontStyle {
final String fontFamily, style;
LottieFontStyle({this.fontFamily, this.style});
LottieFontStyle({required this.fontFamily, required this.style});
}

View File

@ -6,10 +6,14 @@ class LottieImageAsset {
final String id;
final String fileName;
final String dirName;
ui.Image loadedImage;
ui.Image? loadedImage;
LottieImageAsset(
{this.width, this.height, this.id, this.fileName, this.dirName});
{required this.width,
required this.height,
required this.id,
required this.fileName,
required this.dirName});
@override
String toString() =>

View File

@ -2,10 +2,10 @@ import 'animatable_color_value.dart';
import 'animatable_double_value.dart';
class AnimatableTextProperties {
final AnimatableColorValue /*?*/ color;
final AnimatableColorValue /*?*/ stroke;
final AnimatableDoubleValue /*?*/ strokeWidth;
final AnimatableDoubleValue /*?*/ tracking;
final AnimatableColorValue? color;
final AnimatableColorValue? stroke;
final AnimatableDoubleValue? strokeWidth;
final AnimatableDoubleValue? tracking;
AnimatableTextProperties(
{this.color, this.stroke, this.strokeWidth, this.tracking});

View File

@ -12,25 +12,25 @@ import 'animatable_scale_value.dart';
import 'animatable_value.dart';
class AnimatableTransform implements ModifierContent, ContentModel {
final AnimatablePathValue /*?*/ anchorPoint;
final AnimatablePathValue? anchorPoint;
final AnimatableValue<Offset, Offset> /*?*/ position;
final AnimatableValue<Offset, Offset>? position;
final AnimatableScaleValue /*?*/ scale;
final AnimatableScaleValue? scale;
final AnimatableDoubleValue /*?*/ rotation;
final AnimatableDoubleValue? rotation;
final AnimatableIntegerValue /*?*/ opacity;
final AnimatableIntegerValue? opacity;
final AnimatableDoubleValue /*?*/ skew;
final AnimatableDoubleValue? skew;
final AnimatableDoubleValue /*?*/ skewAngle;
final AnimatableDoubleValue? skewAngle;
// Used for repeaters
final AnimatableDoubleValue /*?*/ startOpacity;
final AnimatableDoubleValue? startOpacity;
final AnimatableDoubleValue /*?*/ endOpacity;
final AnimatableDoubleValue? endOpacity;
AnimatableTransform(
{this.anchorPoint,
@ -48,7 +48,7 @@ class AnimatableTransform implements ModifierContent, ContentModel {
}
@override
Content /*?*/ toContent(LottieDrawable drawable, BaseLayer layer) {
Content? toContent(LottieDrawable drawable, BaseLayer layer) {
return null;
}
}

View File

@ -1,7 +1,7 @@
import '../../animation/keyframe/base_keyframe_animation.dart';
import '../../value/keyframe.dart';
abstract class AnimatableValue<K, A> {
abstract class AnimatableValue<K extends Object, A extends Object> {
List<Keyframe<K>> get keyframes;
bool get isStatic;
BaseKeyframeAnimation<K, A> createAnimation();

View File

@ -1,7 +1,8 @@
import '../../value/keyframe.dart';
import 'animatable_value.dart';
abstract class BaseAnimatableValue<V, O> implements AnimatableValue<V, O> {
abstract class BaseAnimatableValue<V extends Object, O extends Object>
implements AnimatableValue<V, O> {
@override
final List<Keyframe<V>> keyframes;

View File

@ -8,14 +8,18 @@ import '../layer/base_layer.dart';
import 'content_model.dart';
class CircleShape implements ContentModel {
final String name;
final String? name;
final AnimatableValue<Offset, Offset> position;
final AnimatablePointValue size;
final bool isReversed;
final bool hidden;
CircleShape(
{this.name, this.position, this.size, this.isReversed, this.hidden});
{this.name,
required this.position,
required this.size,
required this.isReversed,
required this.hidden});
@override
Content toContent(LottieDrawable drawable, BaseLayer layer) {

View File

@ -3,5 +3,5 @@ import '../../lottie_drawable.dart';
import '../layer/base_layer.dart';
abstract class ContentModel {
Content /*?*/ toContent(LottieDrawable drawable, BaseLayer layer);
Content? toContent(LottieDrawable drawable, BaseLayer layer);
}

View File

@ -16,7 +16,7 @@ class GradientColor {
}
for (var i = 0; i < gc1.colors.length; i++) {
positions[i] = lerpDouble(gc1.positions[i], gc2.positions[i], progress);
positions[i] = lerpDouble(gc1.positions[i], gc2.positions[i], progress)!;
colors[i] =
GammaEvaluator.evaluate(progress, gc1.colors[i], gc2.colors[i]);
}

View File

@ -11,28 +11,28 @@ import 'content_model.dart';
import 'gradient_type.dart';
class GradientFill implements ContentModel {
final String name;
final String? name;
final GradientType gradientType;
final PathFillType fillType;
final AnimatableGradientColorValue gradientColor;
final AnimatableIntegerValue opacity;
final AnimatablePointValue startPoint;
final AnimatablePointValue endPoint;
final AnimatableDoubleValue /*?*/ highlightLength;
final AnimatableDoubleValue /*?*/ highlightAngle;
final AnimatableDoubleValue? highlightLength;
final AnimatableDoubleValue? highlightAngle;
final bool hidden;
GradientFill({
this.name,
this.gradientType,
this.fillType,
this.gradientColor,
this.opacity,
this.startPoint,
this.endPoint,
required this.gradientType,
required this.fillType,
required this.gradientColor,
required this.opacity,
required this.startPoint,
required this.endPoint,
this.highlightLength,
this.highlightAngle,
this.hidden,
required this.hidden,
});
@override

View File

@ -11,34 +11,34 @@ import 'gradient_type.dart';
import 'shape_stroke.dart';
class GradientStroke implements ContentModel {
final String name;
final String? name;
final GradientType gradientType;
final AnimatableGradientColorValue gradientColor;
final AnimatableIntegerValue opacity;
final AnimatablePointValue startPoint;
final AnimatablePointValue endPoint;
final AnimatableDoubleValue width;
final LineCapType capType;
final LineJoinType joinType;
final LineCapType? capType;
final LineJoinType? joinType;
final double miterLimit;
final List<AnimatableDoubleValue> lineDashPattern;
final AnimatableDoubleValue /*?*/ dashOffset;
final AnimatableDoubleValue? dashOffset;
final bool hidden;
GradientStroke({
this.name,
this.gradientType,
this.gradientColor,
this.opacity,
this.startPoint,
this.endPoint,
this.width,
required this.gradientType,
required this.gradientColor,
required this.opacity,
required this.startPoint,
required this.endPoint,
required this.width,
this.capType,
this.joinType,
this.miterLimit,
this.lineDashPattern,
required this.miterLimit,
required this.lineDashPattern,
this.dashOffset,
this.hidden,
required this.hidden,
});
@override

View File

@ -1,4 +1,3 @@
import 'package:meta/meta.dart';
import '../animatable/animatable_integer_value.dart';
import '../animatable/animatable_shape_value.dart';
@ -16,8 +15,8 @@ class Mask {
final bool isInverted;
Mask(
{@required this.maskMode,
@required this.maskPath,
@required this.opacity,
@required this.isInverted});
{required this.maskMode,
required this.maskPath,
required this.opacity,
required this.isInverted});
}

View File

@ -12,10 +12,10 @@ class MergePaths implements ContentModel {
final MergePathsMode mode;
final bool hidden;
MergePaths({this.name, this.mode, this.hidden});
MergePaths({required this.name, required this.mode, required this.hidden});
@override
Content /*?*/ toContent(LottieDrawable drawable, BaseLayer layer) {
Content? toContent(LottieDrawable drawable, BaseLayer layer) {
if (!drawable.enableMergePaths) {
logger.warning('Animation contains merge paths but they are disabled.');
return null;

View File

@ -16,7 +16,7 @@ class PolystarShapeType {
const PolystarShapeType(this.value);
static PolystarShapeType forValue(int value) {
static PolystarShapeType? forValue(int value) {
for (var type in values) {
if (type.value == value) {
return type;
@ -27,28 +27,28 @@ class PolystarShapeType {
}
class PolystarShape implements ContentModel {
final String name;
final PolystarShapeType type;
final String? name;
final PolystarShapeType? type;
final AnimatableDoubleValue points;
final AnimatableValue<Offset, Offset> position;
final AnimatableDoubleValue rotation;
final AnimatableDoubleValue innerRadius;
final AnimatableDoubleValue? innerRadius;
final AnimatableDoubleValue outerRadius;
final AnimatableDoubleValue innerRoundedness;
final AnimatableDoubleValue? innerRoundedness;
final AnimatableDoubleValue outerRoundedness;
final bool hidden;
PolystarShape({
this.name,
this.type,
this.points,
this.position,
this.rotation,
required this.points,
required this.position,
required this.rotation,
this.innerRadius,
this.outerRadius,
required this.outerRadius,
this.innerRoundedness,
this.outerRoundedness,
this.hidden,
required this.outerRoundedness,
required this.hidden,
});
@override

View File

@ -9,14 +9,18 @@ import '../layer/base_layer.dart';
import 'content_model.dart';
class RectangleShape implements ContentModel {
final String name;
final String? name;
final AnimatableValue<Offset, Offset> position;
final AnimatablePointValue size;
final AnimatableDoubleValue cornerRadius;
final bool hidden;
RectangleShape(
{this.name, this.position, this.size, this.cornerRadius, this.hidden});
{this.name,
required this.position,
required this.size,
required this.cornerRadius,
required this.hidden});
@override
Content toContent(LottieDrawable drawable, BaseLayer layer) {

View File

@ -7,16 +7,21 @@ import '../layer/base_layer.dart';
import 'content_model.dart';
class Repeater implements ContentModel {
final String name;
final String? name;
final AnimatableDoubleValue copies;
final AnimatableDoubleValue offset;
final AnimatableTransform transform;
final bool hidden;
Repeater({this.name, this.copies, this.offset, this.transform, this.hidden});
Repeater(
{this.name,
required this.copies,
required this.offset,
required this.transform,
required this.hidden});
@override
Content /*?*/ toContent(LottieDrawable drawable, BaseLayer layer) {
Content? toContent(LottieDrawable drawable, BaseLayer layer) {
return RepeaterContent(drawable, layer, this);
}
}

View File

@ -8,7 +8,7 @@ class ShapeData {
Offset _initialPoint;
bool _closed;
ShapeData(List<CubicCurveData> curves, {Offset initialPoint, bool closed})
ShapeData(List<CubicCurveData> curves, {Offset? initialPoint, bool? closed})
: curves = curves.toList(),
_initialPoint = initialPoint ?? Offset.zero,
_closed = closed ?? false;
@ -51,8 +51,8 @@ class ShapeData {
var initialPoint1 = shapeData1.initialPoint;
var initialPoint2 = shapeData2.initialPoint;
setInitialPoint(lerpDouble(initialPoint1.dx, initialPoint2.dx, percentage),
lerpDouble(initialPoint1.dy, initialPoint2.dy, percentage));
setInitialPoint(lerpDouble(initialPoint1.dx, initialPoint2.dx, percentage)!,
lerpDouble(initialPoint1.dy, initialPoint2.dy, percentage)!);
for (var i = curves.length - 1; i >= 0; i--) {
var curve1 = shapeData1.curves[i];
@ -66,12 +66,14 @@ class ShapeData {
var cp22 = curve2.controlPoint2;
var vertex2 = curve2.vertex;
curves[i].controlPoint1 = Offset(lerpDouble(cp11.dx, cp12.dx, percentage),
lerpDouble(cp11.dy, cp12.dy, percentage));
curves[i].controlPoint2 = Offset(lerpDouble(cp21.dx, cp22.dx, percentage),
lerpDouble(cp21.dy, cp22.dy, percentage));
curves[i].vertex = Offset(lerpDouble(vertex1.dx, vertex2.dx, percentage),
lerpDouble(vertex1.dy, vertex2.dy, percentage));
curves[i].controlPoint1 = Offset(
lerpDouble(cp11.dx, cp12.dx, percentage)!,
lerpDouble(cp11.dy, cp12.dy, percentage)!);
curves[i].controlPoint2 = Offset(
lerpDouble(cp21.dx, cp22.dx, percentage)!,
lerpDouble(cp21.dy, cp22.dy, percentage)!);
curves[i].vertex = Offset(lerpDouble(vertex1.dx, vertex2.dx, percentage)!,
lerpDouble(vertex1.dy, vertex2.dy, percentage)!);
}
}

View File

@ -10,18 +10,18 @@ import 'content_model.dart';
class ShapeFill implements ContentModel {
final bool fillEnabled;
final PathFillType fillType;
final String name;
final AnimatableColorValue /*?*/ color;
final AnimatableIntegerValue /*?*/ opacity;
final String? name;
final AnimatableColorValue? color;
final AnimatableIntegerValue? opacity;
final bool hidden;
ShapeFill(
{this.fillEnabled,
this.fillType,
{required this.fillEnabled,
required this.fillType,
this.name,
this.color,
this.opacity,
this.hidden});
required this.hidden});
@override
Content toContent(LottieDrawable drawable, BaseLayer layer) {

Some files were not shown because too many files have changed in this diff Show More