Compare commits

..

2 Commits

Author SHA1 Message Date
0715f6a402 Export the Marker class (#63)
And add an example to play the animation between 2 markers
2020-05-19 22:22:27 +02:00
7e81ec3f69 Fix bug with matrix.mapRect (#61)
Fix a bug in the matrix transformation applied to a rect. We now use the MatrixUtils class from Flutter.
2020-05-18 12:55:53 +02:00
24 changed files with 2719 additions and 102 deletions

View File

@ -1,3 +1,9 @@
## [0.3.6]
- Export the `Marker` class
## [0.3.5]
- Fix a bug with a wrongly clipped rectangle.
## [0.3.4] ## [0.3.4]
- Fix a bug with dashed path - Fix a bug with dashed path

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -5,23 +5,15 @@ void main() async {
runApp(App()); runApp(App());
} }
class App extends StatefulWidget { class App extends StatelessWidget {
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 {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
color: Colors.lightBlue, color: Colors.lightBlue,
home: Scaffold( home: Scaffold(
backgroundColor: Colors.lightBlue, backgroundColor: Colors.lightBlue,
appBar: AppBar(
title: Text(''),
),
body: Center( body: Center(
child: SizedBox( child: SizedBox(
width: 300, width: 300,

View File

@ -0,0 +1,122 @@
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';
/// This example shows how to play the animation between two markers.
/// It is based on this article for lottie-ios:
/// https://medium.com/swlh/controlling-lottie-animation-with-markers-5e9035d94623
void main() async {
runApp(App());
}
class App extends StatefulWidget {
const App({Key key}) : super(key: key);
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {
Future<LottieComposition> _composition;
@override
void initState() {
super.initState();
_composition = AssetLottie('assets/TwitterHeartButton.json').load();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: Scaffold(
appBar: AppBar(
title: Text('Markers'),
),
body: FutureBuilder<LottieComposition>(
future: _composition,
builder: (context, snapshot) {
if (snapshot.hasError) return ErrorWidget(snapshot.error);
if (!snapshot.hasData) return CircularProgressIndicator();
return _LottieDetails(snapshot.data);
},
),
),
);
}
}
class _LottieDetails extends StatefulWidget {
final LottieComposition composition;
const _LottieDetails(this.composition, {Key key}) : super(key: key);
@override
_LottieDetailsState createState() => _LottieDetailsState();
}
class _LottieDetailsState extends State<_LottieDetails>
with TickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView(
children: [
Lottie(
composition: widget.composition,
controller: _controller,
height: 150,
),
ListTile(
title: Text('Composition start frame'),
trailing: Text(widget.composition.startFrame.toStringAsFixed(1)),
),
ListTile(
title: Text('Composition duration'),
trailing: Text(widget.composition.durationFrames.toStringAsFixed(1)),
),
RaisedButton(
child: Text('touchDownEnd - touchUpCancel'),
onPressed: () => _playBetween('touchDownEnd', 'touchUpCancel'),
),
RaisedButton(
child: Text('touchDownStart - touchDownEnd'),
onPressed: () => _playBetween('touchDownStart', 'touchDownEnd'),
),
RaisedButton(
child: Text('touchDownEnd - touchUpEnd'),
onPressed: () => _playBetween('touchDownEnd', 'touchUpEnd'),
),
for (var marker in widget.composition.markers)
ListTile(
title: Text(marker.name),
subtitle: Text(
'${marker.startFrame.toStringAsFixed(1)} ${marker.durationFrames.toStringAsFixed(1)}'),
trailing: Text(
'[${marker.start.toStringAsFixed(2)}-${marker.end.toStringAsFixed(2)}]'),
),
],
);
}
void _playBetween(String marker1, String marker2) {
var start = widget.composition.getMarker(marker1).start;
var end = widget.composition.getMarker(marker2).start;
_controller.value = start;
_controller.animateTo(end,
duration: widget.composition.duration * (end - start).abs());
}
}

View File

@ -20,7 +20,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
FlutterMacOS: 15bea8a44d2fa024068daa0140371c020b4b6ff9 FlutterMacOS: 15bea8a44d2fa024068daa0140371c020b4b6ff9
path_provider: e0848572d1d38b9a7dd099e79cf83f5b7e2cde9f path_provider: e0848572d1d38b9a7dd099e79cf83f5b7e2cde9f
path_provider_macos: adb94ae6c253c45ef2aac146fbf1f4504d74b0f8 path_provider_macos: a0a3fd666cb7cd0448e936fb4abad4052961002b
PODFILE CHECKSUM: d8ba9b3e9e93c62c74a660b46c6fcb09f03991a7 PODFILE CHECKSUM: d8ba9b3e9e93c62c74a660b46c6fcb09f03991a7

View File

@ -43,6 +43,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.3" version: "1.1.3"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
collection: collection:
dependency: transitive dependency: transitive
description: description:
@ -64,6 +71,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.4" version: "2.1.4"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -102,13 +116,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.4" version: "3.1.4"
image:
dependency: transitive
description:
name: image
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.12"
logging: logging:
dependency: transitive dependency: transitive
description: description:
@ -122,7 +129,7 @@ packages:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "0.3.4" version: "0.3.6"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@ -143,7 +150,7 @@ packages:
name: path name: path
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.6.4" version: "1.7.0"
path_provider: path_provider:
dependency: "direct main" dependency: "direct main"
description: description:
@ -172,13 +179,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.9.0" version: "1.9.0"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.0"
platform: platform:
dependency: transitive dependency: transitive
description: description:
@ -193,13 +193,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.2" version: "1.0.2"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -261,13 +254,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.8" version: "2.0.8"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "3.6.1"
sdks: sdks:
dart: ">=2.7.0 <3.0.0" dart: ">=2.7.0 <3.0.0"
flutter: ">=1.12.13+hotfix.5 <2.0.0" flutter: ">=1.12.13+hotfix.5 <2.0.0"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -4,6 +4,7 @@ export 'src/lottie_builder.dart' show LottieBuilder;
export 'src/lottie_delegates.dart' show LottieDelegates; export 'src/lottie_delegates.dart' show LottieDelegates;
export 'src/lottie_drawable.dart' show LottieDrawable, LottieFontStyle; export 'src/lottie_drawable.dart' show LottieDrawable, LottieFontStyle;
export 'src/lottie_image_asset.dart' show LottieImageAsset; export 'src/lottie_image_asset.dart' show LottieImageAsset;
export 'src/model/marker.dart' show Marker;
export 'src/providers/asset_provider.dart' show AssetLottie; export 'src/providers/asset_provider.dart' show AssetLottie;
export 'src/providers/file_provider.dart' show FileLottie; export 'src/providers/file_provider.dart' show FileLottie;
export 'src/providers/lottie_provider.dart' show LottieProvider; export 'src/providers/lottie_provider.dart' show LottieProvider;

View File

@ -1,26 +1,23 @@
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import '../../lottie.dart';
class Marker { class Marker {
static const String _carriageReturn = '\r'; final LottieComposition _composition;
final String name; final String name;
final double startFrame; final double startFrame;
final double durationFrames; final double durationFrames;
Marker(this.name, {@required this.startFrame, @required this.durationFrames}); Marker(this._composition, this.name,
{@required this.startFrame, @required this.durationFrames});
bool matchesName(String name) { bool matchesName(String name) {
if (this.name.toLowerCase() == name.toLowerCase()) { return this.name.trim().toLowerCase() == name.toLowerCase();
return true;
}
// It is easy for a designer to accidentally include an extra newline which will cause the name to not match what they would
// expect. This is a convenience to precent unneccesary confusion.
if (this.name.endsWith(_carriageReturn) &&
this.name.substring(0, this.name.length - 1).toLowerCase() ==
name.toLowerCase()) {
return true;
}
return false;
} }
double get start =>
(startFrame - _composition.startFrame) / _composition.durationFrames;
double get end =>
(startFrame + durationFrames - _composition.startFrame) /
_composition.durationFrames;
} }

View File

@ -254,8 +254,8 @@ class LottieCompositionParser {
} }
} }
reader.endObject(); reader.endObject();
markers.add( markers.add(Marker(composition, comment,
Marker(comment, startFrame: frame, durationFrames: durationFrames)); startFrame: frame, durationFrames: durationFrames));
} }
reader.endArray(); reader.endArray();
} }

View File

@ -34,28 +34,20 @@ extension Matrix4Extension on Matrix4 {
} }
Rect mapRect(Rect rect) { Rect mapRect(Rect rect) {
var topLeft = Vector3(rect.left, rect.top, 0.0)..applyMatrix4(this); return MatrixUtils.transformRect(this, rect);
var topRight = Vector3(rect.right, rect.top, 0.0)..applyMatrix4(this);
var bottomLeft = Vector3(rect.left, rect.bottom, 0.0)..applyMatrix4(this);
var bottomRight = Vector3(rect.right, rect.bottom, 0.0)..applyMatrix4(this);
var newLeft = min(topLeft.x, bottomLeft.x);
var newTop = min(topLeft.y, topRight.y);
var newRight = max(topRight.x, bottomRight.x);
var newBottom = max(bottomLeft.y, bottomRight.y);
return Rect.fromLTRB(newLeft, newTop, newRight, newBottom);
} }
/// Apply this matrix to the array of 2D points, and write the transformed points back into the /// Apply this matrix to the array of 2D points, and write the transformed points back into the
/// array /// array
/// ///
/// @param pts The array [x0, y0, x1, y1, ...] of points to transform. /// @param pts The array [x0, y0, x1, y1, ...] of points to transform.
void mapPoints(List<double> array, [int offset]) { void mapPoints(List<double> array) {
for (var i = 0; i < array.length; i += 2) { for (var i = 0; i < array.length; i += 2) {
final v = Vector3(array[i], array[i + 1], 0.0)..applyMatrix4(this); final v =
array[i] = v.storage[0]; MatrixUtils.transformPoint(this, Offset(array[i], array[i + 1]));
array[i + 1] = v.storage[1];
array[i] = v.dx;
array[i + 1] = v.dy;
} }
} }

View File

@ -57,6 +57,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.3" version: "1.1.3"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
collection: collection:
dependency: "direct main" dependency: "direct main"
description: description:
@ -92,6 +99,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.6" version: "1.3.6"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -116,13 +130,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.14.0+3" version: "0.14.0+3"
image:
dependency: transitive
description:
name: image
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.12"
js: js:
dependency: transitive dependency: transitive
description: description:
@ -185,7 +192,7 @@ packages:
name: path name: path
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.6.4" version: "1.7.0"
pedantic: pedantic:
dependency: transitive dependency: transitive
description: description:
@ -193,13 +200,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.9.0" version: "1.9.0"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.0"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
@ -207,13 +207,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.4.4" version: "1.4.4"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -282,13 +275,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.9.7+15" version: "0.9.7+15"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "3.6.1"
yaml: yaml:
dependency: "direct dev" dependency: "direct dev"
description: description:

View File

@ -1,6 +1,6 @@
name: lottie name: lottie
description: Render After Effects animations natively on Flutter. This package is a pure Dart implementation of a Lottie player. description: Render After Effects animations natively on Flutter. This package is a pure Dart implementation of a Lottie player.
version: 0.3.4 version: 0.3.6
homepage: https://github.com/xvrh/lottie-flutter homepage: https://github.com/xvrh/lottie-flutter
environment: environment: