Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
340f0d2f27 | |||
34fef26eb2 | |||
89c62122bf |
37
CHANGELOG.md
@ -1,3 +1,40 @@
|
||||
## [1.2.0]
|
||||
- Add support for gaussian blurs.
|
||||
|
||||
Example to blur some elements dynamically:
|
||||
|
||||
```dart
|
||||
Lottie.asset(
|
||||
'assets/AndroidWave.json',
|
||||
delegates: LottieDelegates(values: [
|
||||
ValueDelegate.blurRadius(
|
||||
['**'], // The path to the element to blur
|
||||
value: 20,
|
||||
),
|
||||
]),
|
||||
)
|
||||
```
|
||||
|
||||
- Add support for drop shadows.
|
||||
|
||||
Example to add a shadow dynamically:
|
||||
```dart
|
||||
Lottie.asset(
|
||||
'assets/animation.json',
|
||||
delegates: LottieDelegates(values: [
|
||||
ValueDelegate.dropShadow(
|
||||
['**'], // The path to the elements with shadow
|
||||
value: const DropShadow(
|
||||
color: Colors.blue,
|
||||
direction: 140,
|
||||
distance: 60,
|
||||
radius: 10,
|
||||
),
|
||||
),
|
||||
]),
|
||||
)
|
||||
```
|
||||
|
||||
## [1.1.0]
|
||||
- Add `errorBuilder` callback to provide an alternative widget in case an error occurs during loading.
|
||||
```dart
|
||||
|
@ -6,7 +6,6 @@ analyzer:
|
||||
linter:
|
||||
rules:
|
||||
avoid_print: false
|
||||
unnecessary_overrides: false # remove when mockito is fixed
|
||||
|
||||
always_declare_return_types: true
|
||||
avoid_dynamic_calls: true
|
||||
|
1
example/assets/Tests/AnimatedShadow.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":181.000007372281,"w":375,"h":375,"nm":"Square","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,187.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow2","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0,0,0,1]},{"t":151.000006150356,"s":[0,0.371857702732,1,1]}],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[127.5]},{"t":151.000006150356,"s":[127.5]}],"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":151.000006150356,"s":[360]}],"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[10]},{"t":151.000006150356,"s":[15]}],"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[20]},{"t":151.000006150356,"s":[50]}],"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[217.641,217.641],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.68,-1.68],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":184.000007494474,"st":0,"bm":0}],"markers":[]}
|
1
example/assets/Tests/FillBlur.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":121.000004928431,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":29,"nm":"Gaussian Blur2","np":5,"mn":"ADBE Gaussian Blur 2","ix":1,"en":1,"ef":[{"ty":0,"nm":"Blurriness","mn":"ADBE Gaussian Blur 2-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24.00000097754,"s":[120.7]}],"ix":1}},{"ty":7,"nm":"Blur Dimensions","mn":"ADBE Gaussian Blur 2-0002","ix":2,"v":{"a":0,"k":1,"ix":2}},{"ty":7,"nm":"Repeat Edge Pixels","mn":"ADBE Gaussian Blur 2-0003","ix":3,"v":{"a":0,"k":0,"ix":3}}]},{"ty":5,"nm":"Bulge","np":9,"mn":"ADBE Bulge","ix":2,"en":1,"ef":[{"ty":0,"nm":"Horizontal Radius","mn":"ADBE Bulge-0001","ix":1,"v":{"a":0,"k":50,"ix":1}},{"ty":0,"nm":"Vertical Radius","mn":"ADBE Bulge-0002","ix":2,"v":{"a":0,"k":50,"ix":2}},{"ty":3,"nm":"Bulge Center","mn":"ADBE Bulge-0003","ix":3,"v":{"a":0,"k":[200,200],"ix":3}},{"ty":0,"nm":"Bulge Height","mn":"ADBE Bulge-0004","ix":4,"v":{"a":0,"k":1,"ix":4}},{"ty":0,"nm":"Taper Radius","mn":"ADBE Bulge-0005","ix":5,"v":{"a":0,"k":0,"ix":5}},{"ty":7,"nm":"Antialiasing (Best Qual Only)","mn":"ADBE Bulge-0006","ix":6,"v":{"a":0,"k":1,"ix":6}},{"ty":7,"nm":"Pinning","mn":"ADBE Bulge-0007","ix":7,"v":{"a":0,"k":0,"ix":7}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[274.975,274.975],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.513,7.487],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":121.000004928431,"st":0,"bm":0}],"markers":[]}
|
1
example/assets/Tests/GradientFillBlur.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":121.000004928431,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":29,"nm":"Gaussian Blur2","np":5,"mn":"ADBE Gaussian Blur 2","ix":1,"en":1,"ef":[{"ty":0,"nm":"Blurriness","mn":"ADBE Gaussian Blur 2-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24.00000097754,"s":[120.7]}],"ix":1}},{"ty":7,"nm":"Blur Dimensions","mn":"ADBE Gaussian Blur 2-0002","ix":2,"v":{"a":0,"k":1,"ix":2}},{"ty":7,"nm":"Repeat Edge Pixels","mn":"ADBE Gaussian Blur 2-0003","ix":3,"v":{"a":0,"k":0,"ix":3}}]},{"ty":5,"nm":"Bulge","np":9,"mn":"ADBE Bulge","ix":2,"en":1,"ef":[{"ty":0,"nm":"Horizontal Radius","mn":"ADBE Bulge-0001","ix":1,"v":{"a":0,"k":50,"ix":1}},{"ty":0,"nm":"Vertical Radius","mn":"ADBE Bulge-0002","ix":2,"v":{"a":0,"k":50,"ix":2}},{"ty":3,"nm":"Bulge Center","mn":"ADBE Bulge-0003","ix":3,"v":{"a":0,"k":[200,200],"ix":3}},{"ty":0,"nm":"Bulge Height","mn":"ADBE Bulge-0004","ix":4,"v":{"a":0,"k":1,"ix":4}},{"ty":0,"nm":"Taper Radius","mn":"ADBE Bulge-0005","ix":5,"v":{"a":0,"k":0,"ix":5}},{"ty":7,"nm":"Antialiasing (Best Qual Only)","mn":"ADBE Bulge-0006","ix":6,"v":{"a":0,"k":1,"ix":6}},{"ty":7,"nm":"Pinning","mn":"ADBE Bulge-0007","ix":7,"v":{"a":0,"k":0,"ix":7}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[274.975,274.975],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.513,7.487],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,0,0,0.5,0.505,0,0.5,1,0.009,0,1],"ix":9}},"s":{"a":0,"k":[-125,0],"ix":5},"e":{"a":0,"k":[100,0],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false}],"ip":0,"op":121.000004928431,"st":0,"bm":0}],"markers":[]}
|
1
example/assets/Tests/GradientStrokeBlur.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":121.000004928431,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":29,"nm":"Gaussian Blur2","np":5,"mn":"ADBE Gaussian Blur 2","ix":1,"en":1,"ef":[{"ty":0,"nm":"Blurriness","mn":"ADBE Gaussian Blur 2-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24.00000097754,"s":[120.7]}],"ix":1}},{"ty":7,"nm":"Blur Dimensions","mn":"ADBE Gaussian Blur 2-0002","ix":2,"v":{"a":0,"k":1,"ix":2}},{"ty":7,"nm":"Repeat Edge Pixels","mn":"ADBE Gaussian Blur 2-0003","ix":3,"v":{"a":0,"k":0,"ix":3}}]},{"ty":5,"nm":"Bulge","np":9,"mn":"ADBE Bulge","ix":2,"en":1,"ef":[{"ty":0,"nm":"Horizontal Radius","mn":"ADBE Bulge-0001","ix":1,"v":{"a":0,"k":50,"ix":1}},{"ty":0,"nm":"Vertical Radius","mn":"ADBE Bulge-0002","ix":2,"v":{"a":0,"k":50,"ix":2}},{"ty":3,"nm":"Bulge Center","mn":"ADBE Bulge-0003","ix":3,"v":{"a":0,"k":[200,200],"ix":3}},{"ty":0,"nm":"Bulge Height","mn":"ADBE Bulge-0004","ix":4,"v":{"a":0,"k":1,"ix":4}},{"ty":0,"nm":"Taper Radius","mn":"ADBE Bulge-0005","ix":5,"v":{"a":0,"k":0,"ix":5}},{"ty":7,"nm":"Antialiasing (Best Qual Only)","mn":"ADBE Bulge-0006","ix":6,"v":{"a":0,"k":1,"ix":6}},{"ty":7,"nm":"Pinning","mn":"ADBE Bulge-0007","ix":7,"v":{"a":0,"k":0,"ix":7}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[274.975,274.975],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.513,7.487],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":41,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.01,0,1,0.5,0.496,0,0.5,1,0.982,0,0],"ix":8}},"s":{"a":0,"k":[-45,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":1,"lj":1,"ml":4,"ml2":{"a":0,"k":4,"ix":13},"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false}],"ip":0,"op":121.000004928431,"st":0,"bm":0}],"markers":[]}
|
1
example/assets/Tests/PrecompBlur.json
Normal file
1
example/assets/Tests/StaticShadow.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":181.000007372281,"w":375,"h":375,"nm":"Square","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,187.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow2","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,1,0.609851837158,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":127.5,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":0,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":10,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":20,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[217.641,217.641],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.68,-1.68],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":184.000007494474,"st":0,"bm":0}],"markers":[]}
|
1
example/assets/Tests/StrokeBlur.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":121.000004928431,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":29,"nm":"Gaussian Blur2","np":5,"mn":"ADBE Gaussian Blur 2","ix":1,"en":1,"ef":[{"ty":0,"nm":"Blurriness","mn":"ADBE Gaussian Blur 2-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24.00000097754,"s":[120.7]}],"ix":1}},{"ty":7,"nm":"Blur Dimensions","mn":"ADBE Gaussian Blur 2-0002","ix":2,"v":{"a":0,"k":1,"ix":2}},{"ty":7,"nm":"Repeat Edge Pixels","mn":"ADBE Gaussian Blur 2-0003","ix":3,"v":{"a":0,"k":0,"ix":3}}]},{"ty":5,"nm":"Bulge","np":9,"mn":"ADBE Bulge","ix":2,"en":1,"ef":[{"ty":0,"nm":"Horizontal Radius","mn":"ADBE Bulge-0001","ix":1,"v":{"a":0,"k":50,"ix":1}},{"ty":0,"nm":"Vertical Radius","mn":"ADBE Bulge-0002","ix":2,"v":{"a":0,"k":50,"ix":2}},{"ty":3,"nm":"Bulge Center","mn":"ADBE Bulge-0003","ix":3,"v":{"a":0,"k":[200,200],"ix":3}},{"ty":0,"nm":"Bulge Height","mn":"ADBE Bulge-0004","ix":4,"v":{"a":0,"k":1,"ix":4}},{"ty":0,"nm":"Taper Radius","mn":"ADBE Bulge-0005","ix":5,"v":{"a":0,"k":0,"ix":5}},{"ty":7,"nm":"Antialiasing (Best Qual Only)","mn":"ADBE Bulge-0006","ix":6,"v":{"a":0,"k":1,"ix":6}},{"ty":7,"nm":"Pinning","mn":"ADBE Bulge-0007","ix":7,"v":{"a":0,"k":0,"ix":7}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[274.975,274.975],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.513,7.487],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":46,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":121.000004928431,"st":0,"bm":0}],"markers":[]}
|
30
example/lib/examples/blur.dart
Normal file
@ -0,0 +1,30 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
void main() => runApp(const MyApp());
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: ListView(
|
||||
children: [
|
||||
Lottie.asset(
|
||||
'assets/AndroidWave.json',
|
||||
height: 300,
|
||||
delegates: LottieDelegates(values: [
|
||||
ValueDelegate.blurRadius(
|
||||
['**'],
|
||||
value: 20,
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
35
example/lib/examples/drop_shadow.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
void main() => runApp(const MyApp());
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: ListView(
|
||||
children: [
|
||||
Lottie.asset(
|
||||
'assets/Tests/Fill.json',
|
||||
height: 300,
|
||||
delegates: LottieDelegates(values: [
|
||||
ValueDelegate.dropShadow(
|
||||
['**'],
|
||||
value: const DropShadow(
|
||||
color: Colors.blue,
|
||||
direction: 140,
|
||||
distance: 60,
|
||||
radius: 10,
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -143,7 +143,7 @@ packages:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.1.0"
|
||||
version: "1.2.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -14,4 +14,5 @@ export 'src/providers/lottie_provider.dart' show LottieProvider;
|
||||
export 'src/providers/memory_provider.dart' show MemoryLottie;
|
||||
export 'src/providers/network_provider.dart' show NetworkLottie;
|
||||
export 'src/raw_lottie.dart' show RawLottie;
|
||||
export 'src/value/drop_shadow.dart' show DropShadow;
|
||||
export 'src/value_delegate.dart' show ValueDelegate;
|
||||
|
@ -7,6 +7,7 @@ import '../../lottie_drawable.dart';
|
||||
import '../../lottie_property.dart';
|
||||
import '../../model/animatable/animatable_double_value.dart';
|
||||
import '../../model/animatable/animatable_integer_value.dart';
|
||||
import '../../model/content/drop_shadow_effect.dart';
|
||||
import '../../model/content/shape_trim_path.dart';
|
||||
import '../../model/key_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
@ -15,8 +16,10 @@ import '../../utils/dash_path.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../utils/utils.dart';
|
||||
import '../../value/drop_shadow.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import '../keyframe/drop_shadow_keyframe_animation.dart';
|
||||
import '../keyframe/value_callback_keyframe_animation.dart';
|
||||
import 'content.dart';
|
||||
import 'drawing_content.dart';
|
||||
@ -39,6 +42,9 @@ abstract class BaseStrokeContent
|
||||
final List<BaseKeyframeAnimation<Object, double>> _dashPatternAnimations;
|
||||
final BaseKeyframeAnimation<Object, double>? _dashPatternOffsetAnimation;
|
||||
BaseKeyframeAnimation<ColorFilter, ColorFilter?>? _colorFilterAnimation;
|
||||
BaseKeyframeAnimation<double, double>? _blurAnimation;
|
||||
double _blurMaskFilterRadius = 0;
|
||||
DropShadowKeyframeAnimation? dropShadowAnimation;
|
||||
|
||||
BaseStrokeContent(this.lottieDrawable, this.layer,
|
||||
{required StrokeCap cap,
|
||||
@ -77,6 +83,17 @@ abstract class BaseStrokeContent
|
||||
if (_dashPatternOffsetAnimation != null) {
|
||||
_dashPatternOffsetAnimation!.addUpdateListener(onUpdateListener);
|
||||
}
|
||||
var blurEffect = layer.blurEffect;
|
||||
if (blurEffect != null) {
|
||||
_blurAnimation = blurEffect.blurriness.createAnimation()
|
||||
..addUpdateListener(onUpdateListener);
|
||||
layer.addAnimation(_blurAnimation);
|
||||
}
|
||||
var dropShadowEffect = layer.dropShadowEffect;
|
||||
if (dropShadowEffect != null) {
|
||||
dropShadowAnimation = DropShadowKeyframeAnimation(
|
||||
onUpdateListener, layer, dropShadowEffect);
|
||||
}
|
||||
}
|
||||
|
||||
void onUpdateListener() {
|
||||
@ -139,6 +156,18 @@ abstract class BaseStrokeContent
|
||||
paint.colorFilter = _colorFilterAnimation!.value;
|
||||
}
|
||||
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
var blurRadius = blurAnimation.value;
|
||||
if (blurRadius == 0) {
|
||||
paint.maskFilter = null;
|
||||
} else if (blurRadius != _blurMaskFilterRadius) {
|
||||
var blur = layer.getBlurMaskFilter(blurRadius);
|
||||
paint.maskFilter = blur;
|
||||
}
|
||||
_blurMaskFilterRadius = blurRadius;
|
||||
}
|
||||
|
||||
for (var i = 0; i < _pathGroups.length; i++) {
|
||||
var pathGroup = _pathGroups[i];
|
||||
|
||||
@ -153,6 +182,10 @@ abstract class BaseStrokeContent
|
||||
}
|
||||
L.endSection('StrokeContent#buildPath');
|
||||
L.beginSection('StrokeContent#drawPath');
|
||||
var dropShadow = dropShadowAnimation;
|
||||
if (dropShadow != null) {
|
||||
dropShadow.draw(canvas, _path);
|
||||
}
|
||||
canvas.drawPath(_withDashPattern(_path, parentMatrix), paint);
|
||||
L.endSection('StrokeContent#drawPath');
|
||||
}
|
||||
@ -308,10 +341,31 @@ abstract class BaseStrokeContent
|
||||
} else {
|
||||
_colorFilterAnimation =
|
||||
ValueCallbackKeyframeAnimation<ColorFilter, ColorFilter?>(
|
||||
callback as LottieValueCallback<ColorFilter>, null);
|
||||
_colorFilterAnimation!.addUpdateListener(onUpdateListener);
|
||||
callback as LottieValueCallback<ColorFilter>, null)
|
||||
..addUpdateListener(onUpdateListener);
|
||||
layer.addAnimation(_colorFilterAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.blurRadius) {
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
blurAnimation
|
||||
.setValueCallback(callback as LottieValueCallback<double>?);
|
||||
} else {
|
||||
_blurAnimation = blurAnimation = ValueCallbackKeyframeAnimation(
|
||||
callback as LottieValueCallback<double>?, 0)
|
||||
..addUpdateListener(onUpdateListener);
|
||||
layer.addAnimation(blurAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.dropShadow) {
|
||||
var dropShadowAnimation = this.dropShadowAnimation;
|
||||
if (dropShadowAnimation == null) {
|
||||
var effect = DropShadowEffect.createEmpty();
|
||||
this.dropShadowAnimation = dropShadowAnimation = dropShadowAnimation =
|
||||
DropShadowKeyframeAnimation(onUpdateListener, layer, effect);
|
||||
}
|
||||
|
||||
dropShadowAnimation
|
||||
.setCallback(callback as LottieValueCallback<DropShadow>?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,17 @@ import 'package:vector_math/vector_math_64.dart';
|
||||
import '../../l.dart';
|
||||
import '../../lottie_drawable.dart';
|
||||
import '../../lottie_property.dart';
|
||||
import '../../model/content/drop_shadow_effect.dart';
|
||||
import '../../model/content/shape_fill.dart';
|
||||
import '../../model/key_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/drop_shadow.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import '../keyframe/drop_shadow_keyframe_animation.dart';
|
||||
import '../keyframe/value_callback_keyframe_animation.dart';
|
||||
import 'content.dart';
|
||||
import 'drawing_content.dart';
|
||||
@ -29,10 +32,25 @@ class FillContent implements DrawingContent, KeyPathElementContent {
|
||||
late final BaseKeyframeAnimation<int, int> _opacityAnimation;
|
||||
BaseKeyframeAnimation<ColorFilter, ColorFilter?>? _colorFilterAnimation;
|
||||
final LottieDrawable lottieDrawable;
|
||||
BaseKeyframeAnimation<double, double>? _blurAnimation;
|
||||
double _blurMaskFilterRadius = 0;
|
||||
DropShadowKeyframeAnimation? dropShadowAnimation;
|
||||
|
||||
FillContent(this.lottieDrawable, this.layer, ShapeFill fill)
|
||||
: name = fill.name,
|
||||
_hidden = fill.hidden {
|
||||
var blurEffect = layer.blurEffect;
|
||||
if (blurEffect != null) {
|
||||
_blurAnimation = blurEffect.blurriness.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_blurAnimation);
|
||||
}
|
||||
var dropShadowEffect = layer.dropShadowEffect;
|
||||
if (dropShadowEffect != null) {
|
||||
dropShadowAnimation =
|
||||
DropShadowKeyframeAnimation(onValueChanged, layer, dropShadowEffect);
|
||||
}
|
||||
|
||||
if (fill.color == null || fill.opacity == null) {
|
||||
return;
|
||||
}
|
||||
@ -80,6 +98,18 @@ class FillContent implements DrawingContent, KeyPathElementContent {
|
||||
_paint.colorFilter = _colorFilterAnimation!.value;
|
||||
}
|
||||
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
var blurRadius = blurAnimation.value;
|
||||
if (blurRadius == 0) {
|
||||
_paint.maskFilter = null;
|
||||
} else if (blurRadius != _blurMaskFilterRadius) {
|
||||
var blur = layer.getBlurMaskFilter(blurRadius);
|
||||
_paint.maskFilter = blur;
|
||||
}
|
||||
_blurMaskFilterRadius = blurRadius;
|
||||
}
|
||||
|
||||
_path.reset();
|
||||
for (var i = 0; i < _paths.length; i++) {
|
||||
_path.addPath(_paths[i].getPath(), Offset.zero);
|
||||
@ -87,6 +117,10 @@ class FillContent implements DrawingContent, KeyPathElementContent {
|
||||
|
||||
canvas.save();
|
||||
canvas.transform(parentMatrix.storage);
|
||||
var dropShadow = dropShadowAnimation;
|
||||
if (dropShadow != null) {
|
||||
dropShadow.draw(canvas, _path);
|
||||
}
|
||||
canvas.drawPath(_path, _paint);
|
||||
canvas.restore();
|
||||
|
||||
@ -132,6 +166,28 @@ class FillContent implements DrawingContent, KeyPathElementContent {
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_colorFilterAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.blurRadius) {
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
blurAnimation
|
||||
.setValueCallback(callback as LottieValueCallback<double>?);
|
||||
} else {
|
||||
var callbackBlur = callback as LottieValueCallback<double>?;
|
||||
_blurAnimation = blurAnimation = ValueCallbackKeyframeAnimation(
|
||||
callbackBlur, callbackBlur?.value ?? 0)
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(blurAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.dropShadow) {
|
||||
var dropShadowAnimation = this.dropShadowAnimation;
|
||||
if (dropShadowAnimation == null) {
|
||||
var effect = DropShadowEffect.createEmpty();
|
||||
this.dropShadowAnimation = dropShadowAnimation = dropShadowAnimation =
|
||||
DropShadowKeyframeAnimation(onValueChanged, layer, effect);
|
||||
}
|
||||
|
||||
dropShadowAnimation
|
||||
.setCallback(callback as LottieValueCallback<DropShadow>?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import 'package:vector_math/vector_math_64.dart';
|
||||
import '../../l.dart';
|
||||
import '../../lottie_drawable.dart';
|
||||
import '../../lottie_property.dart';
|
||||
import '../../model/content/drop_shadow_effect.dart';
|
||||
import '../../model/content/gradient_color.dart';
|
||||
import '../../model/content/gradient_fill.dart';
|
||||
import '../../model/content/gradient_type.dart';
|
||||
@ -11,8 +12,10 @@ import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/drop_shadow.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import '../keyframe/drop_shadow_keyframe_animation.dart';
|
||||
import '../keyframe/value_callback_keyframe_animation.dart';
|
||||
import 'content.dart';
|
||||
import 'drawing_content.dart';
|
||||
@ -38,6 +41,9 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
_colorCallbackAnimation;
|
||||
final LottieDrawable lottieDrawable;
|
||||
final int _cacheSteps;
|
||||
BaseKeyframeAnimation<double, double>? _blurAnimation;
|
||||
double _blurMaskFilterRadius = 0;
|
||||
DropShadowKeyframeAnimation? dropShadowAnimation;
|
||||
|
||||
GradientFillContent(this.lottieDrawable, this.layer, this._fill)
|
||||
: _cacheSteps =
|
||||
@ -59,6 +65,18 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
|
||||
_endPointAnimation.addUpdateListener(invalidate);
|
||||
layer.addAnimation(_endPointAnimation);
|
||||
|
||||
var blurEffect = layer.blurEffect;
|
||||
if (blurEffect != null) {
|
||||
_blurAnimation = blurEffect.blurriness.createAnimation()
|
||||
..addUpdateListener(invalidate);
|
||||
layer.addAnimation(_blurAnimation);
|
||||
}
|
||||
var dropShadowEffect = layer.dropShadowEffect;
|
||||
if (dropShadowEffect != null) {
|
||||
dropShadowAnimation =
|
||||
DropShadowKeyframeAnimation(invalidate, layer, dropShadowEffect);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -103,6 +121,18 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
_paint.colorFilter = _colorFilterAnimation!.value;
|
||||
}
|
||||
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
var blurRadius = blurAnimation.value;
|
||||
if (blurRadius == 0) {
|
||||
_paint.maskFilter = null;
|
||||
} else if (blurRadius != _blurMaskFilterRadius) {
|
||||
var blur = layer.getBlurMaskFilter(blurRadius);
|
||||
_paint.maskFilter = blur;
|
||||
}
|
||||
_blurMaskFilterRadius = blurRadius;
|
||||
}
|
||||
|
||||
var alpha =
|
||||
((parentAlpha / 255.0 * _opacityAnimation.value / 100.0) * 255).round();
|
||||
_paint.setAlpha(alpha.clamp(0, 255).toInt());
|
||||
@ -112,6 +142,10 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
|
||||
canvas.save();
|
||||
canvas.transform(parentMatrix.storage);
|
||||
var dropShadow = dropShadowAnimation;
|
||||
if (dropShadow != null) {
|
||||
dropShadow.draw(canvas, _path);
|
||||
}
|
||||
canvas.drawPath(_path, _paint);
|
||||
canvas.restore();
|
||||
L.endSection('GradientFillContent#draw');
|
||||
@ -246,6 +280,27 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
..addUpdateListener(invalidate);
|
||||
layer.addAnimation(_colorCallbackAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.blurRadius) {
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
blurAnimation
|
||||
.setValueCallback(callback as LottieValueCallback<double>?);
|
||||
} else {
|
||||
_blurAnimation = blurAnimation = ValueCallbackKeyframeAnimation(
|
||||
callback as LottieValueCallback<double>?, 0)
|
||||
..addUpdateListener(invalidate);
|
||||
layer.addAnimation(blurAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.dropShadow) {
|
||||
var dropShadowAnimation = this.dropShadowAnimation;
|
||||
if (dropShadowAnimation == null) {
|
||||
var effect = DropShadowEffect.createEmpty();
|
||||
this.dropShadowAnimation = dropShadowAnimation = dropShadowAnimation =
|
||||
DropShadowKeyframeAnimation(invalidate, layer, effect);
|
||||
}
|
||||
|
||||
dropShadowAnimation
|
||||
.setCallback(callback as LottieValueCallback<DropShadow>?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
108
lib/src/animation/keyframe/drop_shadow_keyframe_animation.dart
Normal file
@ -0,0 +1,108 @@
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui';
|
||||
import '../../lottie_property.dart';
|
||||
import '../../model/content/drop_shadow_effect.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../value/drop_shadow.dart';
|
||||
import '../../value/lottie_frame_info.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import 'base_keyframe_animation.dart';
|
||||
import 'color_keyframe_animation.dart';
|
||||
|
||||
class DropShadowKeyframeAnimation {
|
||||
static final double _degToRad = math.pi / 180.0;
|
||||
|
||||
final void Function() listener;
|
||||
late final ColorKeyframeAnimation _color;
|
||||
late final BaseKeyframeAnimation<double, double> _opacity;
|
||||
late final BaseKeyframeAnimation<double, double> _direction;
|
||||
late final BaseKeyframeAnimation<double, double> _distance;
|
||||
late final BaseKeyframeAnimation<double, double> _radius;
|
||||
|
||||
Paint? _paint;
|
||||
|
||||
DropShadowKeyframeAnimation(
|
||||
this.listener, BaseLayer layer, DropShadowEffect dropShadowEffect) {
|
||||
_color = dropShadowEffect.color.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_color);
|
||||
_opacity = dropShadowEffect.opacity.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_opacity);
|
||||
_direction = dropShadowEffect.direction.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_direction);
|
||||
_distance = dropShadowEffect.distance.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_distance);
|
||||
_radius = dropShadowEffect.radius.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_radius);
|
||||
}
|
||||
|
||||
void onValueChanged() {
|
||||
_paint = null;
|
||||
listener();
|
||||
}
|
||||
|
||||
void draw(Canvas canvas, Path path) {
|
||||
var directionRad = _direction.value * _degToRad;
|
||||
var distance = _distance.value;
|
||||
var x = math.sin(directionRad) * distance;
|
||||
var y = math.cos(directionRad + math.pi) * distance;
|
||||
var baseColor = _color.value;
|
||||
var opacity = _opacity.value.round();
|
||||
var color = baseColor.withAlpha(opacity);
|
||||
var radius = _radius.value;
|
||||
|
||||
var sigma = radius * 0.57735 + 0.5;
|
||||
|
||||
var paint = _paint;
|
||||
paint ??= _paint = Paint()
|
||||
..color = color
|
||||
..maskFilter = MaskFilter.blur(BlurStyle.normal, sigma);
|
||||
|
||||
canvas.drawPath(path.shift(Offset(x, y)), paint);
|
||||
}
|
||||
|
||||
void setCallback(LottieValueCallback<DropShadow>? callback) {
|
||||
if (callback != null) {
|
||||
_color.setValueCallback(_createCallback(
|
||||
callback, (c) => c?.color ?? const Color(0xff000000)));
|
||||
_opacity.setValueCallback(
|
||||
_createCallback(callback, (c) => c?.color.alpha.toDouble() ?? 255));
|
||||
_direction.setValueCallback(
|
||||
_createCallback(callback, (c) => c?.direction ?? 0));
|
||||
_distance
|
||||
.setValueCallback(_createCallback(callback, (c) => c?.distance ?? 0));
|
||||
_radius
|
||||
.setValueCallback(_createCallback(callback, (c) => c?.radius ?? 0));
|
||||
} else {
|
||||
_color.setValueCallback(null);
|
||||
_opacity.setValueCallback(null);
|
||||
_direction.setValueCallback(null);
|
||||
_distance.setValueCallback(null);
|
||||
_radius.setValueCallback(null);
|
||||
}
|
||||
}
|
||||
|
||||
LottieValueCallback<T> _createCallback<T>(
|
||||
LottieValueCallback<DropShadow> callback,
|
||||
T Function(DropShadow?) selector) {
|
||||
return LottieValueCallback<T>(null)
|
||||
..callback = (info) {
|
||||
onValueChanged();
|
||||
var frameInfo = LottieFrameInfo<DropShadow>(
|
||||
info.startFrame,
|
||||
info.endFrame,
|
||||
LottieProperty.dropShadow,
|
||||
LottieProperty.dropShadow,
|
||||
info.linearKeyframeProgress,
|
||||
info.interpolatedKeyframeProgress,
|
||||
info.overallProgress,
|
||||
);
|
||||
var dropShadow = callback.getValue(frameInfo);
|
||||
return selector(dropShadow);
|
||||
};
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import 'dart:ui';
|
||||
import 'value/drop_shadow.dart';
|
||||
|
||||
/// Property values are the same type as the generic type of their corresponding
|
||||
/// {@link LottieValueCallback}. With this, we can use generics to maintain type safety
|
||||
@ -122,6 +123,12 @@ abstract class LottieProperty {
|
||||
/// In Dp
|
||||
static const double textSize = 28.0;
|
||||
|
||||
/// In Px
|
||||
static const double blurRadius = 29.0;
|
||||
|
||||
static const dropShadow = DropShadow(
|
||||
color: Color(0x00000000), direction: 0, distance: 0, radius: 0);
|
||||
|
||||
static const ColorFilter colorFilter =
|
||||
ColorFilter.mode(Color(0xFF000000), BlendMode.dst);
|
||||
|
||||
|
@ -22,7 +22,9 @@ abstract class BaseAnimatableValue<V extends Object, O extends Object>
|
||||
String toString() {
|
||||
final sb = StringBuffer();
|
||||
if (keyframes.isNotEmpty) {
|
||||
sb..write('values=')..write('$keyframes');
|
||||
sb
|
||||
..write('values=')
|
||||
..write('$keyframes');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
7
lib/src/model/content/blur_effect.dart
Normal file
@ -0,0 +1,7 @@
|
||||
import '../animatable/animatable_double_value.dart';
|
||||
|
||||
class BlurEffect {
|
||||
final AnimatableDoubleValue blurriness;
|
||||
|
||||
BlurEffect(this.blurriness);
|
||||
}
|
29
lib/src/model/content/drop_shadow_effect.dart
Normal file
@ -0,0 +1,29 @@
|
||||
import 'package:flutter/painting.dart';
|
||||
import '../../value/keyframe.dart';
|
||||
import '../animatable/animatable_color_value.dart';
|
||||
import '../animatable/animatable_double_value.dart';
|
||||
|
||||
class DropShadowEffect {
|
||||
final AnimatableColorValue color;
|
||||
final AnimatableDoubleValue opacity;
|
||||
final AnimatableDoubleValue direction;
|
||||
final AnimatableDoubleValue distance;
|
||||
final AnimatableDoubleValue radius;
|
||||
|
||||
DropShadowEffect({
|
||||
required this.color,
|
||||
required this.opacity,
|
||||
required this.direction,
|
||||
required this.distance,
|
||||
required this.radius,
|
||||
});
|
||||
|
||||
static DropShadowEffect createEmpty() => DropShadowEffect(
|
||||
color: AnimatableColorValue.fromKeyframes(
|
||||
[Keyframe.nonAnimated(const Color(0x00000000))]),
|
||||
direction: AnimatableDoubleValue(),
|
||||
radius: AnimatableDoubleValue(),
|
||||
distance: AnimatableDoubleValue(),
|
||||
opacity: AnimatableDoubleValue(),
|
||||
);
|
||||
}
|
@ -14,6 +14,8 @@ import '../../l.dart';
|
||||
import '../../lottie_drawable.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../content/blur_effect.dart';
|
||||
import '../content/drop_shadow_effect.dart';
|
||||
import '../content/mask.dart';
|
||||
import '../content/shape_data.dart';
|
||||
import '../key_path.dart';
|
||||
@ -27,11 +29,14 @@ import 'solid_layer.dart';
|
||||
import 'text_layer.dart';
|
||||
|
||||
abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
static BaseLayer? forModel(Layer layerModel, LottieDrawable drawable,
|
||||
static BaseLayer? forModel(
|
||||
CompositionLayer compositionLayer,
|
||||
Layer layerModel,
|
||||
LottieDrawable drawable,
|
||||
LottieComposition composition) {
|
||||
switch (layerModel.layerType) {
|
||||
case LayerType.shape:
|
||||
return ShapeLayer(drawable, layerModel);
|
||||
return ShapeLayer(drawable, layerModel, compositionLayer);
|
||||
case LayerType.preComp:
|
||||
return CompositionLayer(drawable, layerModel,
|
||||
composition.getPrecomps(layerModel.refId)!, composition);
|
||||
@ -77,6 +82,9 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
final TransformKeyframeAnimation transform;
|
||||
bool _visible = true;
|
||||
|
||||
double blurMaskFilterRadius = 0;
|
||||
MaskFilter? blurMaskFilter;
|
||||
|
||||
BaseLayer(this.lottieDrawable, this.layerModel)
|
||||
: _drawTraceName = '${layerModel.name}#draw',
|
||||
transform = layerModel.transform.createAnimation() {
|
||||
@ -547,6 +555,22 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
return layerModel.name;
|
||||
}
|
||||
|
||||
BlurEffect? get blurEffect {
|
||||
return layerModel.blurEffect;
|
||||
}
|
||||
|
||||
MaskFilter? getBlurMaskFilter(double radius) {
|
||||
if (blurMaskFilterRadius == radius) {
|
||||
return blurMaskFilter;
|
||||
}
|
||||
var sigma = radius * 0.57735 + 0.5;
|
||||
blurMaskFilter = MaskFilter.blur(BlurStyle.normal, sigma);
|
||||
blurMaskFilterRadius = radius;
|
||||
return blurMaskFilter;
|
||||
}
|
||||
|
||||
DropShadowEffect? get dropShadowEffect => layerModel.dropShadowEffect;
|
||||
|
||||
@override
|
||||
void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
|
||||
// Do nothing
|
||||
|
@ -36,7 +36,7 @@ class CompositionLayer extends BaseLayer {
|
||||
BaseLayer? mattedLayer;
|
||||
for (var i = layerModels.length - 1; i >= 0; i--) {
|
||||
var lm = layerModels[i];
|
||||
var layer = BaseLayer.forModel(lm, lottieDrawable, composition);
|
||||
var layer = BaseLayer.forModel(this, lm, lottieDrawable, composition);
|
||||
if (layer == null) {
|
||||
continue;
|
||||
}
|
||||
|
@ -5,7 +5,9 @@ import '../animatable/animatable_double_value.dart';
|
||||
import '../animatable/animatable_text_frame.dart';
|
||||
import '../animatable/animatable_text_properties.dart';
|
||||
import '../animatable/animatable_transform.dart';
|
||||
import '../content/blur_effect.dart';
|
||||
import '../content/content_model.dart';
|
||||
import '../content/drop_shadow_effect.dart';
|
||||
import '../content/mask.dart';
|
||||
|
||||
enum LayerType { preComp, solid, image, nullLayer, shape, text, unknown }
|
||||
@ -35,6 +37,8 @@ class Layer {
|
||||
final MatteType matteType;
|
||||
final AnimatableDoubleValue? timeRemapping;
|
||||
final bool isHidden;
|
||||
final BlurEffect? blurEffect;
|
||||
final DropShadowEffect? dropShadowEffect;
|
||||
|
||||
double get startProgress {
|
||||
return startFrame / composition.durationFrames;
|
||||
@ -63,6 +67,8 @@ class Layer {
|
||||
required this.matteType,
|
||||
this.timeRemapping,
|
||||
required this.isHidden,
|
||||
this.blurEffect,
|
||||
this.dropShadowEffect,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -71,19 +77,32 @@ class Layer {
|
||||
}
|
||||
|
||||
String toStringWithPrefix(String prefix) {
|
||||
var sb = StringBuffer()..write(prefix)..write(name)..write('\n');
|
||||
var sb = StringBuffer()
|
||||
..write(prefix)
|
||||
..write(name)
|
||||
..write('\n');
|
||||
var parent = composition.layerModelForId(parentId);
|
||||
if (parent != null) {
|
||||
sb..write('\t\tParents: ')..write(parent.name);
|
||||
sb
|
||||
..write('\t\tParents: ')
|
||||
..write(parent.name);
|
||||
parent = composition.layerModelForId(parent.parentId);
|
||||
while (parent != null) {
|
||||
sb..write('->')..write(parent.name);
|
||||
sb
|
||||
..write('->')
|
||||
..write(parent.name);
|
||||
parent = composition.layerModelForId(parent.parentId);
|
||||
}
|
||||
sb..write(prefix)..write('\n');
|
||||
sb
|
||||
..write(prefix)
|
||||
..write('\n');
|
||||
}
|
||||
if (masks.isNotEmpty) {
|
||||
sb..write(prefix)..write('\tMasks: ')..write(masks.length)..write('\n');
|
||||
sb
|
||||
..write(prefix)
|
||||
..write('\tMasks: ')
|
||||
..write(masks.length)
|
||||
..write('\n');
|
||||
}
|
||||
if (solidWidth != 0 && solidHeight != 0) {
|
||||
sb
|
||||
@ -92,9 +111,15 @@ class Layer {
|
||||
..write('${solidWidth}x$solidHeight $solidColor');
|
||||
}
|
||||
if (shapes.isNotEmpty) {
|
||||
sb..write(prefix)..write('\tShapes:\n');
|
||||
sb
|
||||
..write(prefix)
|
||||
..write('\tShapes:\n');
|
||||
for (Object shape in shapes) {
|
||||
sb..write(prefix)..write('\t\t')..write(shape)..write('\n');
|
||||
sb
|
||||
..write(prefix)
|
||||
..write('\t\t')
|
||||
..write(shape)
|
||||
..write('\n');
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
|
@ -3,15 +3,20 @@ import 'package:vector_math/vector_math_64.dart';
|
||||
import '../../animation/content/content.dart';
|
||||
import '../../animation/content/content_group.dart';
|
||||
import '../../lottie_drawable.dart';
|
||||
import '../content/blur_effect.dart';
|
||||
import '../content/drop_shadow_effect.dart';
|
||||
import '../content/shape_group.dart';
|
||||
import '../key_path.dart';
|
||||
import 'base_layer.dart';
|
||||
import 'composition_layer.dart';
|
||||
import 'layer.dart';
|
||||
|
||||
class ShapeLayer extends BaseLayer {
|
||||
late ContentGroup _contentGroup;
|
||||
final CompositionLayer _compositionLayer;
|
||||
|
||||
ShapeLayer(LottieDrawable lottieDrawable, Layer layerModel)
|
||||
ShapeLayer(
|
||||
LottieDrawable lottieDrawable, Layer layerModel, this._compositionLayer)
|
||||
: super(lottieDrawable, layerModel) {
|
||||
// Naming this __container allows it to be ignored in KeyPath matching.
|
||||
var shapeGroup =
|
||||
@ -34,6 +39,24 @@ class ShapeLayer extends BaseLayer {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@override
|
||||
BlurEffect? get blurEffect {
|
||||
var layerBlur = super.blurEffect;
|
||||
if (layerBlur != null) {
|
||||
return layerBlur;
|
||||
}
|
||||
return _compositionLayer.blurEffect;
|
||||
}
|
||||
|
||||
@override
|
||||
DropShadowEffect? get dropShadowEffect {
|
||||
var layerDropShadow = super.dropShadowEffect;
|
||||
if (layerDropShadow != null) {
|
||||
return layerDropShadow;
|
||||
}
|
||||
return _compositionLayer.dropShadowEffect;
|
||||
}
|
||||
|
||||
@override
|
||||
void resolveChildKeyPath(KeyPath keyPath, int depth,
|
||||
List<KeyPath> accumulator, KeyPath currentPartialKeyPath) {
|
||||
|
60
lib/src/parser/blur_effect_parser.dart
Normal file
@ -0,0 +1,60 @@
|
||||
import '../composition.dart';
|
||||
import '../model/content/blur_effect.dart';
|
||||
import 'animatable_value_parser.dart';
|
||||
import 'moshi/json_reader.dart';
|
||||
|
||||
class BlurEffectParser {
|
||||
static final JsonReaderOptions _blurEffectNames =
|
||||
JsonReaderOptions.of(['ef']);
|
||||
static final JsonReaderOptions _innerBlurEffectNames =
|
||||
JsonReaderOptions.of(['ty', 'v']);
|
||||
|
||||
static BlurEffect? parse(JsonReader reader, LottieComposition composition) {
|
||||
BlurEffect? blurEffect;
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_blurEffectNames)) {
|
||||
case 0:
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
var be = _maybeParseInnerEffect(reader, composition);
|
||||
if (be != null) {
|
||||
blurEffect = be;
|
||||
}
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
return blurEffect;
|
||||
}
|
||||
|
||||
static BlurEffect? _maybeParseInnerEffect(
|
||||
JsonReader reader, LottieComposition composition) {
|
||||
BlurEffect? blurEffect;
|
||||
var isCorrectType = false;
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_innerBlurEffectNames)) {
|
||||
case 0:
|
||||
isCorrectType = reader.nextInt() == 0;
|
||||
break;
|
||||
case 1:
|
||||
if (isCorrectType) {
|
||||
blurEffect = BlurEffect(
|
||||
AnimatableValueParser.parseFloat(reader, composition));
|
||||
} else {
|
||||
reader.skipValue();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
return blurEffect;
|
||||
}
|
||||
}
|
97
lib/src/parser/drop_shadow_effect_parser.dart
Normal file
@ -0,0 +1,97 @@
|
||||
import '../composition.dart';
|
||||
import '../model/animatable/animatable_color_value.dart';
|
||||
import '../model/animatable/animatable_double_value.dart';
|
||||
import '../model/content/drop_shadow_effect.dart';
|
||||
import 'animatable_value_parser.dart';
|
||||
import 'moshi/json_reader.dart';
|
||||
|
||||
class DropShadowEffectParser {
|
||||
static final JsonReaderOptions _dropShadowEffectNames =
|
||||
JsonReaderOptions.of(['ef']);
|
||||
|
||||
static final JsonReaderOptions _innerEffectNames =
|
||||
JsonReaderOptions.of(['nm', 'v']);
|
||||
|
||||
AnimatableColorValue? _color;
|
||||
AnimatableDoubleValue? _opacity;
|
||||
AnimatableDoubleValue? _direction;
|
||||
AnimatableDoubleValue? _distance;
|
||||
AnimatableDoubleValue? _radius;
|
||||
|
||||
DropShadowEffect? parse(JsonReader reader, LottieComposition composition) {
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_dropShadowEffectNames)) {
|
||||
case 0:
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
_maybeParseInnerEffect(reader, composition);
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
|
||||
var color = _color;
|
||||
var opacity = _opacity;
|
||||
var direction = _direction;
|
||||
var distance = _distance;
|
||||
var radius = _radius;
|
||||
if (color != null &&
|
||||
opacity != null &&
|
||||
direction != null &&
|
||||
distance != null &&
|
||||
radius != null) {
|
||||
return DropShadowEffect(
|
||||
color: color,
|
||||
opacity: opacity,
|
||||
direction: direction,
|
||||
distance: distance,
|
||||
radius: radius);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void _maybeParseInnerEffect(
|
||||
JsonReader reader, LottieComposition composition) {
|
||||
var currentEffectName = '';
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_innerEffectNames)) {
|
||||
case 0:
|
||||
currentEffectName = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
switch (currentEffectName) {
|
||||
case 'Shadow Color':
|
||||
_color = AnimatableValueParser.parseColor(reader, composition);
|
||||
break;
|
||||
case 'Opacity':
|
||||
_opacity = AnimatableValueParser.parseFloat(reader, composition,
|
||||
isDp: false);
|
||||
break;
|
||||
case 'Direction':
|
||||
_direction = AnimatableValueParser.parseFloat(reader, composition,
|
||||
isDp: false);
|
||||
break;
|
||||
case 'Distance':
|
||||
_distance = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 'Softness':
|
||||
_radius = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
}
|
||||
}
|
@ -4,7 +4,9 @@ import '../model/animatable/animatable_double_value.dart';
|
||||
import '../model/animatable/animatable_text_frame.dart';
|
||||
import '../model/animatable/animatable_text_properties.dart';
|
||||
import '../model/animatable/animatable_transform.dart';
|
||||
import '../model/content/blur_effect.dart';
|
||||
import '../model/content/content_model.dart';
|
||||
import '../model/content/drop_shadow_effect.dart';
|
||||
import '../model/content/mask.dart';
|
||||
import '../model/layer/layer.dart';
|
||||
import '../utils/misc.dart';
|
||||
@ -12,7 +14,9 @@ import '../value/keyframe.dart';
|
||||
import 'animatable_text_properties_parser.dart';
|
||||
import 'animatable_transform_parser.dart';
|
||||
import 'animatable_value_parser.dart';
|
||||
import 'blur_effect_parser.dart';
|
||||
import 'content_model_parser.dart';
|
||||
import 'drop_shadow_effect_parser.dart';
|
||||
import 'mask_parser.dart';
|
||||
import 'moshi/json_reader.dart';
|
||||
|
||||
@ -74,7 +78,8 @@ class LayerParser {
|
||||
|
||||
static final JsonReaderOptions _textNames = JsonReaderOptions.of(['d', 'a']);
|
||||
|
||||
static final JsonReaderOptions _effectsNames = JsonReaderOptions.of(['nm']);
|
||||
static final JsonReaderOptions _effectsNames =
|
||||
JsonReaderOptions.of(['ty', 'nm']);
|
||||
|
||||
static Layer parseJson(JsonReader reader, LottieComposition composition) {
|
||||
// This should always be set by After Effects. However, if somebody wants to minify
|
||||
@ -95,6 +100,8 @@ class LayerParser {
|
||||
var outFrame = 0.0;
|
||||
String? cl;
|
||||
var hidden = false;
|
||||
BlurEffect? blurEffect;
|
||||
DropShadowEffect? dropShadowEffect;
|
||||
|
||||
var matteType = MatteType.none;
|
||||
AnimatableTransform? transform;
|
||||
@ -207,7 +214,17 @@ class LayerParser {
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_effectsNames)) {
|
||||
case 0:
|
||||
effectNames.add(reader.nextString());
|
||||
var type = reader.nextInt();
|
||||
if (type == 29) {
|
||||
blurEffect = BlurEffectParser.parse(reader, composition);
|
||||
} else if (type == 25) {
|
||||
dropShadowEffect =
|
||||
DropShadowEffectParser().parse(reader, composition);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
var effectName = reader.nextString();
|
||||
effectNames.add(effectName);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
@ -313,6 +330,9 @@ class LayerParser {
|
||||
inOutKeyframes: inOutKeyframes,
|
||||
matteType: matteType,
|
||||
timeRemapping: timeRemapping,
|
||||
isHidden: hidden);
|
||||
isHidden: hidden,
|
||||
blurEffect: blurEffect,
|
||||
dropShadowEffect: dropShadowEffect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,10 @@ class JsonScope {
|
||||
switch (stack[i]) {
|
||||
case emptyArray:
|
||||
case nonEmptyArray:
|
||||
result..write('[')..write(pathIndices[i])..write(']');
|
||||
result
|
||||
..write('[')
|
||||
..write(pathIndices[i])
|
||||
..write(']');
|
||||
break;
|
||||
|
||||
case emptyObject:
|
||||
|
@ -88,8 +88,6 @@ extension IterableExtension<T> on Iterable<T> {
|
||||
}
|
||||
|
||||
class ListEquality<E> {
|
||||
static const int _hashMask = 0x7fffffff;
|
||||
|
||||
const ListEquality();
|
||||
|
||||
bool equals(List<E>? list1, List<E>? list2) {
|
||||
@ -102,22 +100,4 @@ class ListEquality<E> {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int hash(List<E>? list) {
|
||||
if (list == null) return null.hashCode;
|
||||
// Jenkins's one-at-a-time hash function.
|
||||
// This code is almost identical to the one in IterableEquality, except
|
||||
// that it uses indexing instead of iterating to get the elements.
|
||||
var hash = 0;
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var c = list[i].hashCode;
|
||||
hash = (hash + c) & _hashMask;
|
||||
hash = (hash + (hash << 10)) & _hashMask;
|
||||
hash ^= hash >> 6;
|
||||
}
|
||||
hash = (hash + (hash << 3)) & _hashMask;
|
||||
hash ^= hash >> 11;
|
||||
hash = (hash + (hash << 15)) & _hashMask;
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
41
lib/src/value/drop_shadow.dart
Normal file
@ -0,0 +1,41 @@
|
||||
import 'package:flutter/painting.dart';
|
||||
|
||||
class DropShadow {
|
||||
final Color color;
|
||||
final double direction;
|
||||
final double distance;
|
||||
final double radius;
|
||||
|
||||
const DropShadow({
|
||||
required this.color,
|
||||
required this.direction,
|
||||
required this.distance,
|
||||
required this.radius,
|
||||
});
|
||||
|
||||
DropShadow copyWith(
|
||||
{Color? color, double? direction, double? distance, double? radius}) {
|
||||
return DropShadow(
|
||||
color: color ?? this.color,
|
||||
direction: direction ?? this.direction,
|
||||
distance: distance ?? this.distance,
|
||||
radius: radius ?? this.radius,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
return other is DropShadow &&
|
||||
other.color == color &&
|
||||
other.direction == direction &&
|
||||
other.distance == distance &&
|
||||
other.radius == radius;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(color, direction, distance, radius);
|
||||
|
||||
@override
|
||||
String toString() => 'DropShadow(color: $color, direction: $direction, '
|
||||
'distance: $distance, radius: $radius)';
|
||||
}
|
@ -3,6 +3,7 @@ import 'lottie_drawable.dart';
|
||||
import 'lottie_property.dart';
|
||||
import 'model/key_path.dart';
|
||||
import 'utils.dart';
|
||||
import 'value/drop_shadow.dart';
|
||||
import 'value/lottie_frame_info.dart';
|
||||
import 'value/lottie_relative_double_value_callback.dart';
|
||||
import 'value/lottie_relative_integer_value_callback.dart';
|
||||
@ -263,6 +264,16 @@ class ValueDelegate<T> {
|
||||
List<Color> Function(LottieFrameInfo<List<Color>>)? callback}) =>
|
||||
ValueDelegate._(keyPath, LottieProperty.gradientColor, value, callback);
|
||||
|
||||
static ValueDelegate<double> blurRadius(List<String> keyPath,
|
||||
{double? value,
|
||||
double Function(LottieFrameInfo<double>)? callback}) =>
|
||||
ValueDelegate._(keyPath, LottieProperty.blurRadius, value, callback);
|
||||
|
||||
static ValueDelegate<DropShadow> dropShadow(List<String> keyPath,
|
||||
{DropShadow? value,
|
||||
DropShadow Function(LottieFrameInfo<DropShadow>)? callback}) =>
|
||||
ValueDelegate._(keyPath, LottieProperty.dropShadow, value, callback);
|
||||
|
||||
ResolvedValueDelegate<T>? _resolved;
|
||||
ResolvedValueDelegate _resolve(List<KeyPath> resolvedPaths) {
|
||||
_resolved = ResolvedValueDelegate<T>(this, resolvedPaths);
|
||||
|
48
pubspec.lock
@ -7,14 +7,14 @@ packages:
|
||||
name: _fe_analyzer_shared
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "22.0.0"
|
||||
version: "26.0.0"
|
||||
analyzer:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: analyzer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.1"
|
||||
version: "2.3.0"
|
||||
archive:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -28,14 +28,14 @@ packages:
|
||||
name: args
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.3.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
version: "2.8.1"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -49,7 +49,7 @@ packages:
|
||||
name: build
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
version: "2.1.0"
|
||||
build_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -70,35 +70,35 @@ packages:
|
||||
name: build_resolvers
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
version: "2.0.4"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
version: "2.1.2"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
version: "7.1.0"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.1.0"
|
||||
version: "5.1.1"
|
||||
built_value:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "8.1.0"
|
||||
version: "8.1.2"
|
||||
characters:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -112,7 +112,7 @@ packages:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.1"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -126,7 +126,7 @@ packages:
|
||||
name: cli_util
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.2"
|
||||
version: "0.3.3"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -140,7 +140,7 @@ packages:
|
||||
name: code_builder
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
version: "4.1.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -168,7 +168,7 @@ packages:
|
||||
name: dart_style
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "2.1.0"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -201,7 +201,7 @@ packages:
|
||||
name: flutter_lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
version: "1.0.4"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@ -213,7 +213,7 @@ packages:
|
||||
name: frontend_server_client
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.2"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -227,7 +227,7 @@ packages:
|
||||
name: graphs
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.1.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -248,7 +248,7 @@ packages:
|
||||
name: io
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
version: "1.0.3"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -276,7 +276,7 @@ packages:
|
||||
name: logging
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
version: "1.0.2"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -290,7 +290,7 @@ packages:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.7.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -304,7 +304,7 @@ packages:
|
||||
name: package_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.0.2"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -332,7 +332,7 @@ packages:
|
||||
name: pub_semver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.1.0"
|
||||
pubspec_parse:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -346,7 +346,7 @@ packages:
|
||||
name: shelf
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.4"
|
||||
version: "1.2.0"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -407,7 +407,7 @@ packages:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "0.4.2"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1,10 +1,10 @@
|
||||
name: lottie
|
||||
description: Render After Effects animations natively on Flutter. This package is a pure Dart implementation of a Lottie player.
|
||||
version: 1.1.0
|
||||
version: 1.2.0
|
||||
homepage: https://github.com/xvrh/lottie-flutter
|
||||
|
||||
environment:
|
||||
sdk: '>=2.12.0-0 <3.0.0'
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
archive: ^3.0.0
|
||||
|
@ -288,6 +288,27 @@ void main() {
|
||||
filePath: 'Tests/TrackMattes.json',
|
||||
);
|
||||
|
||||
testGolden(
|
||||
'Blur',
|
||||
ValueDelegate.blurRadius(
|
||||
['**'],
|
||||
value: 22,
|
||||
),
|
||||
);
|
||||
|
||||
testGolden(
|
||||
'Drop shadow',
|
||||
ValueDelegate.dropShadow(
|
||||
['Shape Layer 1', '**'],
|
||||
value: const DropShadow(
|
||||
color: Colors.green,
|
||||
direction: 150,
|
||||
distance: 20,
|
||||
radius: 10,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
for (var progress in [0.0, 0.5, 1.0]) {
|
||||
testGolden(
|
||||
'Opacity interpolation ($progress)',
|
||||
|
BIN
test/goldens/all/Tests/animatedshadow.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
test/goldens/all/Tests/fillblur.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
test/goldens/all/Tests/gradientfillblur.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
test/goldens/all/Tests/gradientstrokeblur.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
test/goldens/all/Tests/precompblur.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
test/goldens/all/Tests/staticshadow.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
test/goldens/all/Tests/strokeblur.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 39 KiB |
BIN
test/goldens/dynamic/blur.png
Normal file
After Width: | Height: | Size: 400 KiB |
BIN
test/goldens/dynamic/drop_shadow.png
Normal file
After Width: | Height: | Size: 206 KiB |