Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
c0bc257f4f | |||
0e7499d82e | |||
4cd9ec759a | |||
d8f5b872ef | |||
bc3eb4621b |
13
.github/workflows/analyze-and-test.yaml
vendored
@ -10,11 +10,11 @@ jobs:
|
|||||||
name: Flutter analyze
|
name: Flutter analyze
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
flutter: ['beta']
|
flutter: ['stable']
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: subosito/flutter-action@v1
|
- uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: ${{ matrix.flutter }}
|
channel: ${{ matrix.flutter }}
|
||||||
- run: flutter doctor
|
- run: flutter doctor
|
||||||
@ -22,8 +22,8 @@ jobs:
|
|||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
working-directory: example
|
working-directory: example
|
||||||
- run: flutter analyze
|
- run: flutter analyze
|
||||||
- run: flutter test test # https://github.com/flutter/flutter/issues/20907
|
- run: flutter test
|
||||||
- run: flutter test test
|
- run: flutter test
|
||||||
working-directory: example
|
working-directory: example
|
||||||
- run: flutter pub run tool/prepare_submit.dart
|
- run: flutter pub run tool/prepare_submit.dart
|
||||||
- name: "check for uncommitted changes"
|
- name: "check for uncommitted changes"
|
||||||
@ -38,10 +38,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: subosito/flutter-action@v1
|
- uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: 'beta'
|
channel: 'stable'
|
||||||
- run: flutter config --enable-web
|
|
||||||
- run: flutter precache web
|
- run: flutter precache web
|
||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
working-directory: example
|
working-directory: example
|
||||||
|
4
.github/workflows/publish-on-pub.yaml
vendored
@ -8,9 +8,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: subosito/flutter-action@v1
|
- uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: 'beta'
|
channel: 'stable'
|
||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
- run: flutter pub run tool/publish/comment_dependency_overrides.dart
|
- run: flutter pub run tool/publish/comment_dependency_overrides.dart
|
||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
|
31
CHANGELOG.md
@ -1,3 +1,34 @@
|
|||||||
|
## [1.4.2]
|
||||||
|
- Use `FilterQuality.low` as default to draw image layers.
|
||||||
|
|
||||||
|
## [1.4.1]
|
||||||
|
- Allow `AlignmentGeometry` for `alignment`.
|
||||||
|
|
||||||
|
## [1.4.0]
|
||||||
|
- Added `filterQuality` property to control the performance vs quality trade-off to use when drawing images
|
||||||
|
|
||||||
|
## [1.3.0]
|
||||||
|
- Added support for rounded corners on shapes and rects
|
||||||
|
- Add support for text in dynamic properties (`ValueDelegate`)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Lottie.asset(
|
||||||
|
'assets/DynamicText.json',
|
||||||
|
delegates: LottieDelegates(values: [
|
||||||
|
ValueDelegate.text(
|
||||||
|
['Text layer'], // The path to the text element to change
|
||||||
|
value: 'The new text',
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
- Improve stroke with offset
|
||||||
|
- Add support for reversed polystar paths
|
||||||
|
- Enforce order of operations to avoid rounding errors
|
||||||
|
|
||||||
## [1.2.2]
|
## [1.2.2]
|
||||||
- Internal maintenance: fix lints for Flutter 2.10
|
- Internal maintenance: fix lints for Flutter 2.10
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ class MyApp extends StatefulWidget {
|
|||||||
const MyApp({Key? key}) : super(key: key);
|
const MyApp({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MyAppState createState() => _MyAppState();
|
State<MyApp> createState() => _MyAppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||||
@ -139,7 +139,7 @@ class MyWidget extends StatefulWidget {
|
|||||||
const MyWidget({Key? key}) : super(key: key);
|
const MyWidget({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MyWidgetState createState() => _MyWidgetState();
|
State<MyWidget> createState() => _MyWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyWidgetState extends State<MyWidget> {
|
class _MyWidgetState extends State<MyWidget> {
|
||||||
|
3512
example/assets/Tests/GradientOneColor.json
Normal file
288
example/assets/Tests/ReversedStar.json
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
{
|
||||||
|
"v": "5.8.2",
|
||||||
|
"fr": 24,
|
||||||
|
"ip": 0,
|
||||||
|
"op": 94,
|
||||||
|
"w": 150,
|
||||||
|
"h": 150,
|
||||||
|
"nm": "Anim_load",
|
||||||
|
"ddd": 0,
|
||||||
|
"assets": [],
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"ddd": 0,
|
||||||
|
"ind": 1,
|
||||||
|
"ty": 4,
|
||||||
|
"nm": "LF03",
|
||||||
|
"sr": 1,
|
||||||
|
"ks": {
|
||||||
|
"o": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 100,
|
||||||
|
"ix": 11
|
||||||
|
},
|
||||||
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": -19,
|
||||||
|
"ix": 10
|
||||||
|
},
|
||||||
|
"p": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
75,
|
||||||
|
76.005,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"ix": 2,
|
||||||
|
"l": 2
|
||||||
|
},
|
||||||
|
"a": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"ix": 1,
|
||||||
|
"l": 2
|
||||||
|
},
|
||||||
|
"s": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
19.986,
|
||||||
|
19.986,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"ix": 6,
|
||||||
|
"l": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ao": 0,
|
||||||
|
"shapes": [
|
||||||
|
{
|
||||||
|
"ty": "gr",
|
||||||
|
"it": [
|
||||||
|
{
|
||||||
|
"ty": "sr",
|
||||||
|
"sy": 1,
|
||||||
|
"d": 3,
|
||||||
|
"pt": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 14,
|
||||||
|
"ix": 3
|
||||||
|
},
|
||||||
|
"p": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"ix": 4
|
||||||
|
},
|
||||||
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0,
|
||||||
|
"ix": 5
|
||||||
|
},
|
||||||
|
"ir": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 91.612,
|
||||||
|
"ix": 6
|
||||||
|
},
|
||||||
|
"is": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0,
|
||||||
|
"ix": 8
|
||||||
|
},
|
||||||
|
"or": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 113.225,
|
||||||
|
"ix": 7
|
||||||
|
},
|
||||||
|
"os": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0,
|
||||||
|
"ix": 9
|
||||||
|
},
|
||||||
|
"ix": 1,
|
||||||
|
"nm": "Polystar Path 1",
|
||||||
|
"mn": "ADBE Vector Shape - Star",
|
||||||
|
"hd": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ty": "st",
|
||||||
|
"c": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0.937254905701,
|
||||||
|
0.89411765337,
|
||||||
|
0.850980401039,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"ix": 3
|
||||||
|
},
|
||||||
|
"o": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 100,
|
||||||
|
"ix": 4
|
||||||
|
},
|
||||||
|
"w": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 30,
|
||||||
|
"ix": 5
|
||||||
|
},
|
||||||
|
"lc": 1,
|
||||||
|
"lj": 1,
|
||||||
|
"ml": 4,
|
||||||
|
"bm": 0,
|
||||||
|
"nm": "Stroke 1",
|
||||||
|
"mn": "ADBE Vector Graphic - Stroke",
|
||||||
|
"hd": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ty": "tr",
|
||||||
|
"p": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
-1.979,
|
||||||
|
-0.604
|
||||||
|
],
|
||||||
|
"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": "Polystar 1",
|
||||||
|
"np": 2,
|
||||||
|
"cix": 2,
|
||||||
|
"bm": 0,
|
||||||
|
"ix": 1,
|
||||||
|
"mn": "ADBE Vector Group",
|
||||||
|
"hd": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ty": "tm",
|
||||||
|
"s": {
|
||||||
|
"a": 1,
|
||||||
|
"k": [
|
||||||
|
{
|
||||||
|
"i": {
|
||||||
|
"x": [
|
||||||
|
0.667
|
||||||
|
],
|
||||||
|
"y": [
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"o": {
|
||||||
|
"x": [
|
||||||
|
0.333
|
||||||
|
],
|
||||||
|
"y": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"t": -0.127,
|
||||||
|
"s": [
|
||||||
|
100
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 32,
|
||||||
|
"s": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ix": 1
|
||||||
|
},
|
||||||
|
"e": {
|
||||||
|
"a": 1,
|
||||||
|
"k": [
|
||||||
|
{
|
||||||
|
"i": {
|
||||||
|
"x": [
|
||||||
|
0.833
|
||||||
|
],
|
||||||
|
"y": [
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"o": {
|
||||||
|
"x": [
|
||||||
|
0.333
|
||||||
|
],
|
||||||
|
"y": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"t": 36,
|
||||||
|
"s": [
|
||||||
|
100
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 68,
|
||||||
|
"s": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ix": 2
|
||||||
|
},
|
||||||
|
"o": {
|
||||||
|
"a": 0,
|
||||||
|
"k": -43,
|
||||||
|
"ix": 3
|
||||||
|
},
|
||||||
|
"m": 1,
|
||||||
|
"ix": 2,
|
||||||
|
"nm": "Trim Paths 1",
|
||||||
|
"mn": "ADBE Vector Filter - Trim",
|
||||||
|
"hd": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ip": 0,
|
||||||
|
"op": 94,
|
||||||
|
"st": 18,
|
||||||
|
"bm": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"markers": []
|
||||||
|
}
|
390
example/assets/Tests/RoundedCorners.json
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
{
|
||||||
|
"v": "5.8.1",
|
||||||
|
"fr": 29.9700012207031,
|
||||||
|
"ip": 0,
|
||||||
|
"op": 900.000036657751,
|
||||||
|
"w": 1000,
|
||||||
|
"h": 1000,
|
||||||
|
"nm": "Rounded Corners",
|
||||||
|
"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": [
|
||||||
|
500,
|
||||||
|
500,
|
||||||
|
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,
|
||||||
|
"shapes": [
|
||||||
|
{
|
||||||
|
"ind": 0,
|
||||||
|
"ty": "sh",
|
||||||
|
"ix": 1,
|
||||||
|
"ks": {
|
||||||
|
"a": 0,
|
||||||
|
"k": {
|
||||||
|
"i": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"o": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"v": [
|
||||||
|
[
|
||||||
|
-75,
|
||||||
|
-475
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-75,
|
||||||
|
-75
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-475,
|
||||||
|
-75
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-475,
|
||||||
|
-475
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"c": true
|
||||||
|
},
|
||||||
|
"ix": 2
|
||||||
|
},
|
||||||
|
"nm": "Path 1",
|
||||||
|
"mn": "ADBE Vector Shape - Group",
|
||||||
|
"hd": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ty": "rc",
|
||||||
|
"d": 1,
|
||||||
|
"s": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
400,
|
||||||
|
400
|
||||||
|
],
|
||||||
|
"ix": 2
|
||||||
|
},
|
||||||
|
"p": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
275,
|
||||||
|
-275
|
||||||
|
],
|
||||||
|
"ix": 3
|
||||||
|
},
|
||||||
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0,
|
||||||
|
"ix": 4
|
||||||
|
},
|
||||||
|
"nm": "Rectangle Path 1",
|
||||||
|
"mn": "ADBE Vector Shape - Rect",
|
||||||
|
"hd": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ty": "sr",
|
||||||
|
"sy": 1,
|
||||||
|
"d": 1,
|
||||||
|
"pt": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 5,
|
||||||
|
"ix": 3
|
||||||
|
},
|
||||||
|
"p": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
275,
|
||||||
|
275
|
||||||
|
],
|
||||||
|
"ix": 4
|
||||||
|
},
|
||||||
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0,
|
||||||
|
"ix": 5
|
||||||
|
},
|
||||||
|
"ir": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 107,
|
||||||
|
"ix": 6
|
||||||
|
},
|
||||||
|
"is": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0,
|
||||||
|
"ix": 8
|
||||||
|
},
|
||||||
|
"or": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 275,
|
||||||
|
"ix": 7
|
||||||
|
},
|
||||||
|
"os": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0,
|
||||||
|
"ix": 9
|
||||||
|
},
|
||||||
|
"ix": 3,
|
||||||
|
"nm": "Polystar Path 1",
|
||||||
|
"mn": "ADBE Vector Shape - Star",
|
||||||
|
"hd": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ind": 3,
|
||||||
|
"ty": "sh",
|
||||||
|
"ix": 4,
|
||||||
|
"ks": {
|
||||||
|
"a": 0,
|
||||||
|
"k": {
|
||||||
|
"i": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"o": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"v": [
|
||||||
|
[
|
||||||
|
-275,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-212.107,
|
||||||
|
188.435
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-13.459,
|
||||||
|
190.02
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-173.237,
|
||||||
|
308.065
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-113.359,
|
||||||
|
497.48
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-275,
|
||||||
|
382
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-436.641,
|
||||||
|
497.48
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-376.763,
|
||||||
|
308.065
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-536.541,
|
||||||
|
190.02
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-337.893,
|
||||||
|
188.435
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"c": true
|
||||||
|
},
|
||||||
|
"ix": 2
|
||||||
|
},
|
||||||
|
"nm": "Path 2",
|
||||||
|
"mn": "ADBE Vector Shape - Group",
|
||||||
|
"hd": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ty": "rd",
|
||||||
|
"nm": "Round Corners 1",
|
||||||
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 136,
|
||||||
|
"ix": 1
|
||||||
|
},
|
||||||
|
"ix": 5,
|
||||||
|
"mn": "ADBE Vector Filter - RC",
|
||||||
|
"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": 900.000036657751,
|
||||||
|
"st": 0,
|
||||||
|
"bm": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"markers": []
|
||||||
|
}
|
4841
example/assets/Tests/TrimPathWrapAround.json
Normal file
@ -25,7 +25,7 @@ class __PageState extends State<_Page> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((_) => _showLoader());
|
SchedulerBinding.instance.addPostFrameCallback((_) => _showLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showLoader() {
|
void _showLoader() {
|
||||||
|
@ -7,7 +7,7 @@ class MyApp extends StatefulWidget {
|
|||||||
const MyApp({Key? key}) : super(key: key);
|
const MyApp({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MyAppState createState() => _MyAppState();
|
State<MyApp> createState() => _MyAppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||||
|
@ -15,7 +15,7 @@ class MyApp extends StatefulWidget {
|
|||||||
const MyApp({Key? key}) : super(key: key);
|
const MyApp({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MyAppState createState() => _MyAppState();
|
State<MyApp> createState() => _MyAppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||||
|
@ -21,7 +21,7 @@ class MyWidget extends StatefulWidget {
|
|||||||
const MyWidget({Key? key}) : super(key: key);
|
const MyWidget({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MyWidgetState createState() => _MyWidgetState();
|
State<MyWidget> createState() => _MyWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyWidgetState extends State<MyWidget> {
|
class _MyWidgetState extends State<MyWidget> {
|
||||||
|
@ -22,7 +22,7 @@ class MyWidget extends StatefulWidget {
|
|||||||
const MyWidget({Key? key}) : super(key: key);
|
const MyWidget({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MyWidgetState createState() => _MyWidgetState();
|
State<MyWidget> createState() => _MyWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyWidgetState extends State<MyWidget> {
|
class _MyWidgetState extends State<MyWidget> {
|
||||||
|
@ -10,7 +10,7 @@ class App extends StatefulWidget {
|
|||||||
const App({Key? key}) : super(key: key);
|
const App({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AppState createState() => _AppState();
|
State<App> createState() => _AppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppState extends State<App> with TickerProviderStateMixin {
|
class _AppState extends State<App> with TickerProviderStateMixin {
|
||||||
@ -71,7 +71,7 @@ class _AppState extends State<App> with TickerProviderStateMixin {
|
|||||||
_color = newColor;
|
_color = newColor;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
showLabel: false,
|
labelTypes: const [],
|
||||||
enableAlpha: false,
|
enableAlpha: false,
|
||||||
pickerAreaHeightPercent: 0.8,
|
pickerAreaHeightPercent: 0.8,
|
||||||
),
|
),
|
||||||
|
@ -10,7 +10,7 @@ class App extends StatefulWidget {
|
|||||||
const App({Key? key}) : super(key: key);
|
const App({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AppState createState() => _AppState();
|
State<App> createState() => _AppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppState extends State<App> with TickerProviderStateMixin {
|
class _AppState extends State<App> with TickerProviderStateMixin {
|
||||||
|
@ -9,7 +9,7 @@ class App extends StatefulWidget {
|
|||||||
const App({Key? key}) : super(key: key);
|
const App({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AppState createState() => _AppState();
|
State<App> createState() => _AppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppState extends State<App> with TickerProviderStateMixin {
|
class _AppState extends State<App> with TickerProviderStateMixin {
|
||||||
|
@ -12,7 +12,7 @@ class App extends StatefulWidget {
|
|||||||
const App({Key? key}) : super(key: key);
|
const App({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AppState createState() => _AppState();
|
State<App> createState() => _AppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppState extends State<App> with TickerProviderStateMixin {
|
class _AppState extends State<App> with TickerProviderStateMixin {
|
||||||
|
@ -7,7 +7,7 @@ class MyApp extends StatefulWidget {
|
|||||||
const MyApp({Key? key}) : super(key: key);
|
const MyApp({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MyAppState createState() => _MyAppState();
|
State<MyApp> createState() => _MyAppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||||
|
@ -15,7 +15,7 @@ class App extends StatefulWidget {
|
|||||||
const App({Key? key}) : super(key: key);
|
const App({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AppState createState() => _AppState();
|
State<App> createState() => _AppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppState extends State<App> with TickerProviderStateMixin {
|
class _AppState extends State<App> with TickerProviderStateMixin {
|
||||||
|
@ -13,7 +13,7 @@ class MyApp extends StatefulWidget {
|
|||||||
const MyApp({Key? key}) : super(key: key);
|
const MyApp({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MyAppState createState() => _MyAppState();
|
State<MyApp> createState() => _MyAppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyAppState extends State<MyApp> {
|
class _MyAppState extends State<MyApp> {
|
||||||
|
@ -92,7 +92,7 @@ class Detail extends StatefulWidget {
|
|||||||
const Detail(this.assetName, {Key? key}) : super(key: key);
|
const Detail(this.assetName, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_DetailState createState() => _DetailState();
|
State<Detail> createState() => _DetailState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DetailState extends State<Detail> with TickerProviderStateMixin {
|
class _DetailState extends State<Detail> with TickerProviderStateMixin {
|
||||||
|
@ -15,8 +15,8 @@ EXTERNAL SOURCES:
|
|||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
|
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
|
||||||
path_provider_macos: a0a3fd666cb7cd0448e936fb4abad4052961002b
|
path_provider_macos: 160cab0d5461f0c0e02995469a98f24bdb9a3f1f
|
||||||
|
|
||||||
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||||
|
|
||||||
COCOAPODS: 1.10.1
|
COCOAPODS: 1.11.3
|
||||||
|
@ -7,7 +7,7 @@ packages:
|
|||||||
name: archive
|
name: archive
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.3.1"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -49,28 +49,28 @@ packages:
|
|||||||
name: collection
|
name: collection
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0"
|
version: "1.16.0"
|
||||||
crypto:
|
crypto:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: crypto
|
name: crypto
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.0"
|
||||||
ffi:
|
ffi:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: ffi
|
name: ffi
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.2"
|
version: "2.0.1"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -89,14 +89,14 @@ packages:
|
|||||||
name: flutter_colorpicker
|
name: flutter_colorpicker
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0"
|
version: "1.0.3"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: flutter_lints
|
name: flutter_lints
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.3"
|
version: "2.0.1"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -108,42 +108,42 @@ packages:
|
|||||||
name: golden_toolkit
|
name: golden_toolkit
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.0"
|
version: "0.13.0"
|
||||||
http:
|
http:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.13.3"
|
version: "0.13.4"
|
||||||
http_parser:
|
http_parser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: http_parser
|
name: http_parser
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.1"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: lints
|
name: lints
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "2.0.0"
|
||||||
logging:
|
logging:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: logging
|
name: logging
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.2"
|
||||||
lottie:
|
lottie:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: ".."
|
path: ".."
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.2.2"
|
version: "1.4.2"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -157,7 +157,7 @@ packages:
|
|||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.3"
|
version: "0.1.4"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -166,75 +166,82 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "1.7.0"
|
version: "1.7.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0"
|
version: "1.8.1"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.0.11"
|
||||||
|
path_provider_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_android
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.16"
|
||||||
|
path_provider_ios:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_ios
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.10"
|
||||||
path_provider_linux:
|
path_provider_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_linux
|
name: path_provider_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.1.7"
|
||||||
path_provider_macos:
|
path_provider_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_macos
|
name: path_provider_macos
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.6"
|
||||||
path_provider_platform_interface:
|
path_provider_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_platform_interface
|
name: path_provider_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.4"
|
||||||
path_provider_windows:
|
path_provider_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_windows
|
name: path_provider_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.1.0"
|
||||||
pedantic:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pedantic
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.11.1"
|
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: platform
|
name: platform
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
version: "3.1.0"
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: plugin_platform_interface
|
name: plugin_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.1.2"
|
||||||
process:
|
process:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: process
|
name: process
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.1"
|
version: "4.2.4"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -246,7 +253,7 @@ packages:
|
|||||||
name: source_span
|
name: source_span
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.2"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -281,35 +288,35 @@ packages:
|
|||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.8"
|
version: "0.4.9"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: typed_data
|
name: typed_data
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.1"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.2"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: win32
|
name: win32
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.5"
|
version: "2.7.0"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: xdg_directories
|
name: xdg_directories
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.2.0+1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.14.0 <3.0.0"
|
dart: ">=2.17.0 <3.0.0"
|
||||||
flutter: ">=1.20.0"
|
flutter: ">=3.0.0"
|
||||||
|
@ -13,6 +13,7 @@ dependencies:
|
|||||||
logging:
|
logging:
|
||||||
lottie:
|
lottie:
|
||||||
path: ../
|
path: ../
|
||||||
|
path:
|
||||||
path_provider:
|
path_provider:
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
@ -196,7 +196,8 @@ abstract class BaseStrokeContent
|
|||||||
void _applyTrimPath(
|
void _applyTrimPath(
|
||||||
Canvas canvas, _PathGroup pathGroup, Matrix4 parentMatrix) {
|
Canvas canvas, _PathGroup pathGroup, Matrix4 parentMatrix) {
|
||||||
L.beginSection('StrokeContent#applyTrimPath');
|
L.beginSection('StrokeContent#applyTrimPath');
|
||||||
if (pathGroup.trimPath == null) {
|
var trimPath = pathGroup.trimPath;
|
||||||
|
if (trimPath == null) {
|
||||||
L.endSection('StrokeContent#applyTrimPath');
|
L.endSection('StrokeContent#applyTrimPath');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -205,13 +206,24 @@ abstract class BaseStrokeContent
|
|||||||
_path.addPath(pathGroup.paths[j].getPath(), Offset.zero,
|
_path.addPath(pathGroup.paths[j].getPath(), Offset.zero,
|
||||||
matrix4: parentMatrix.storage);
|
matrix4: parentMatrix.storage);
|
||||||
}
|
}
|
||||||
|
var animStartValue = trimPath.start.value / 100;
|
||||||
|
var animEndValue = trimPath.end.value / 100;
|
||||||
|
var animOffsetValue = trimPath.offset.value / 360;
|
||||||
|
|
||||||
|
// If the start-end is ~100, consider it to be the full path.
|
||||||
|
if (animStartValue < 0.01 && animEndValue > 0.99) {
|
||||||
|
canvas.drawPath(_path, paint);
|
||||||
|
L.endSection('StrokeContent#applyTrimPath');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var pathMetrics = _path.computeMetrics().toList();
|
var pathMetrics = _path.computeMetrics().toList();
|
||||||
var totalLength = pathMetrics.fold<double>(0.0, (a, b) => a + b.length);
|
var totalLength = pathMetrics.fold<double>(0.0, (a, b) => a + b.length);
|
||||||
|
|
||||||
var trimPath = pathGroup.trimPath!;
|
var offsetLength = totalLength * animOffsetValue;
|
||||||
var offsetLength = totalLength * trimPath.offset.value / 360.0;
|
var startLength = totalLength * animStartValue + offsetLength;
|
||||||
var startLength = totalLength * trimPath.start.value / 100.0 + offsetLength;
|
var endLength = min(totalLength * animEndValue + offsetLength,
|
||||||
var endLength = totalLength * trimPath.end.value / 100.0 + offsetLength;
|
startLength + totalLength - 1);
|
||||||
|
|
||||||
var currentLength = 0.0;
|
var currentLength = 0.0;
|
||||||
for (var j = pathGroup.paths.length - 1; j >= 0; j--) {
|
for (var j = pathGroup.paths.length - 1; j >= 0; j--) {
|
||||||
|
@ -134,6 +134,9 @@ class PolystarContent implements PathContent, KeyPathElementContent {
|
|||||||
currentAngle = radians(currentAngle);
|
currentAngle = radians(currentAngle);
|
||||||
// adjust current angle for partial points
|
// adjust current angle for partial points
|
||||||
var anglePerPoint = 2 * pi / points;
|
var anglePerPoint = 2 * pi / points;
|
||||||
|
if (_polystarShape.isReversed) {
|
||||||
|
anglePerPoint *= -1;
|
||||||
|
}
|
||||||
var halfAnglePerPoint = anglePerPoint / 2.0;
|
var halfAnglePerPoint = anglePerPoint / 2.0;
|
||||||
var partialPointAmount = points - points.toInt();
|
var partialPointAmount = points - points.toInt();
|
||||||
if (partialPointAmount != 0) {
|
if (partialPointAmount != 0) {
|
||||||
|
@ -15,6 +15,7 @@ import 'compound_trim_path_content.dart';
|
|||||||
import 'content.dart';
|
import 'content.dart';
|
||||||
import 'key_path_element_content.dart';
|
import 'key_path_element_content.dart';
|
||||||
import 'path_content.dart';
|
import 'path_content.dart';
|
||||||
|
import 'rounded_corners_content.dart';
|
||||||
import 'trim_path_content.dart';
|
import 'trim_path_content.dart';
|
||||||
|
|
||||||
class RectangleContent implements KeyPathElementContent, PathContent {
|
class RectangleContent implements KeyPathElementContent, PathContent {
|
||||||
@ -29,6 +30,9 @@ class RectangleContent implements KeyPathElementContent, PathContent {
|
|||||||
final BaseKeyframeAnimation<Object, double> _cornerRadiusAnimation;
|
final BaseKeyframeAnimation<Object, double> _cornerRadiusAnimation;
|
||||||
|
|
||||||
final CompoundTrimPathContent _trimPaths = CompoundTrimPathContent();
|
final CompoundTrimPathContent _trimPaths = CompoundTrimPathContent();
|
||||||
|
|
||||||
|
/// This corner radius is from a layer item. The first one is from the roundedness on this specific rect.
|
||||||
|
BaseKeyframeAnimation<double, double>? _roundedCornersAnimation;
|
||||||
bool _isPathValid = false;
|
bool _isPathValid = false;
|
||||||
|
|
||||||
RectangleContent(
|
RectangleContent(
|
||||||
@ -61,6 +65,8 @@ class RectangleContent implements KeyPathElementContent, PathContent {
|
|||||||
var trimPath = content;
|
var trimPath = content;
|
||||||
_trimPaths.addTrimPath(trimPath);
|
_trimPaths.addTrimPath(trimPath);
|
||||||
trimPath.addListener(invalidate);
|
trimPath.addListener(invalidate);
|
||||||
|
} else if (content is RoundedCornersContent) {
|
||||||
|
_roundedCornersAnimation = content.roundedCorners;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,6 +88,10 @@ class RectangleContent implements KeyPathElementContent, PathContent {
|
|||||||
var halfWidth = size.dx / 2.0;
|
var halfWidth = size.dx / 2.0;
|
||||||
var halfHeight = size.dy / 2.0;
|
var halfHeight = size.dy / 2.0;
|
||||||
var radius = _cornerRadiusAnimation.value;
|
var radius = _cornerRadiusAnimation.value;
|
||||||
|
var roundedCornersAnimation = _roundedCornersAnimation;
|
||||||
|
if (radius == 0 && roundedCornersAnimation != null) {
|
||||||
|
radius = min(roundedCornersAnimation.value, min(halfWidth, halfHeight));
|
||||||
|
}
|
||||||
var maxRadius = min(halfWidth, halfHeight);
|
var maxRadius = min(halfWidth, halfHeight);
|
||||||
if (radius > maxRadius) {
|
if (radius > maxRadius) {
|
||||||
radius = maxRadius;
|
radius = maxRadius;
|
||||||
|
236
lib/src/animation/content/rounded_corners_content.dart
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
import 'dart:math' as math;
|
||||||
|
import 'dart:ui';
|
||||||
|
import '../../lottie_drawable.dart';
|
||||||
|
import '../../model/content/rounded_corners.dart';
|
||||||
|
import '../../model/content/shape_data.dart';
|
||||||
|
import '../../model/cubic_curve_data.dart';
|
||||||
|
import '../../model/layer/base_layer.dart';
|
||||||
|
import '../../utils.dart';
|
||||||
|
import '../keyframe/base_keyframe_animation.dart';
|
||||||
|
import 'content.dart';
|
||||||
|
import 'shape_modifier_content.dart';
|
||||||
|
|
||||||
|
class RoundedCornersContent implements ShapeModifierContent {
|
||||||
|
/// Copied from:
|
||||||
|
/// https://github.com/airbnb/lottie-web/blob/bb71072a26e03f1ca993da60915860f39aae890b/player/js/utils/common.js#L47
|
||||||
|
static const _roundedCornerMagicNumber = 0.5519;
|
||||||
|
|
||||||
|
final LottieDrawable lottieDrawable;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
final BaseKeyframeAnimation<double, double> roundedCorners;
|
||||||
|
ShapeData? shapeData;
|
||||||
|
|
||||||
|
RoundedCornersContent(
|
||||||
|
this.lottieDrawable, BaseLayer layer, RoundedCorners roundedCorners)
|
||||||
|
: name = roundedCorners.name,
|
||||||
|
roundedCorners = roundedCorners.cornerRadius.createAnimation() {
|
||||||
|
layer.addAnimation(this.roundedCorners);
|
||||||
|
this.roundedCorners.addUpdateListener(_onValueChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onValueChanged() {
|
||||||
|
lottieDrawable.invalidateSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rounded corner algorithm:
|
||||||
|
/// Iterate through each vertex.
|
||||||
|
/// If a vertex is a sharp corner, it rounds it.
|
||||||
|
/// If a vertex has control points, it is already rounded, so it does nothing.
|
||||||
|
/// <p>
|
||||||
|
/// To round a vertex:
|
||||||
|
/// Split the vertex into two.
|
||||||
|
/// Move vertex 1 directly towards the previous vertex.
|
||||||
|
/// Set vertex 1's in control point to itself so it is not rounded on that side.
|
||||||
|
/// Extend vertex 1's out control point towards the original vertex.
|
||||||
|
/// <p>
|
||||||
|
/// Repeat for vertex 2:
|
||||||
|
/// Move vertex 2 directly towards the next vertex.
|
||||||
|
/// Set vertex 2's out point to itself so it is not rounded on that side.
|
||||||
|
/// Extend vertex 2's in control point towards the original vertex.
|
||||||
|
/// <p>
|
||||||
|
/// The distance that the vertices and control points are moved are relative to the
|
||||||
|
/// shape's vertex distances and the roundedness set in the animation.
|
||||||
|
@override
|
||||||
|
ShapeData modifyShape(ShapeData startingShapeData) {
|
||||||
|
var startingCurves = startingShapeData.curves;
|
||||||
|
if (startingCurves.length <= 2) {
|
||||||
|
return startingShapeData;
|
||||||
|
}
|
||||||
|
var roundedness = roundedCorners.value;
|
||||||
|
if (roundedness == 0) {
|
||||||
|
return startingShapeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
var modifiedShapeData = _getShapeData(startingShapeData);
|
||||||
|
modifiedShapeData.setInitialPoint(
|
||||||
|
startingShapeData.initialPoint.dx, startingShapeData.initialPoint.dy);
|
||||||
|
var modifiedCurves = modifiedShapeData.curves;
|
||||||
|
var modifiedCurvesIndex = 0;
|
||||||
|
var isClosed = startingShapeData.isClosed;
|
||||||
|
|
||||||
|
// i represents which vertex we are currently on. Refer to the docs of CubicCurveData prior to working with
|
||||||
|
// this code.
|
||||||
|
// When i == 0
|
||||||
|
// vertex=ShapeData.initialPoint
|
||||||
|
// inCp=if closed vertex else curves[size - 1].cp2
|
||||||
|
// outCp=curves[0].cp1
|
||||||
|
// When i == 1
|
||||||
|
// vertex=curves[0].vertex
|
||||||
|
// inCp=curves[0].cp2
|
||||||
|
// outCp=curves[1].cp1.
|
||||||
|
// When i == size - 1
|
||||||
|
// vertex=curves[size - 1].vertex
|
||||||
|
// inCp=curves[size - 1].cp2
|
||||||
|
// outCp=if closed vertex else curves[0].cp1
|
||||||
|
for (var i = 0; i < startingCurves.length; i++) {
|
||||||
|
var startingCurve = startingCurves[i];
|
||||||
|
var previousCurve =
|
||||||
|
startingCurves[floorMod(i - 1, startingCurves.length)];
|
||||||
|
var previousPreviousCurve =
|
||||||
|
startingCurves[floorMod(i - 2, startingCurves.length)];
|
||||||
|
var vertex = (i == 0 && !isClosed)
|
||||||
|
? startingShapeData.initialPoint
|
||||||
|
: previousCurve.vertex;
|
||||||
|
var inPoint =
|
||||||
|
(i == 0 && !isClosed) ? vertex : previousCurve.controlPoint2;
|
||||||
|
var outPoint = startingCurve.controlPoint1;
|
||||||
|
var previousVertex = previousPreviousCurve.vertex;
|
||||||
|
var nextVertex = startingCurve.vertex;
|
||||||
|
|
||||||
|
// We can't round the corner of the end of a non-closed curve.
|
||||||
|
var isEndOfCurve = !startingShapeData.isClosed &&
|
||||||
|
(i == 0 && i == startingCurves.length - 1);
|
||||||
|
if (inPoint == vertex && outPoint == vertex && !isEndOfCurve) {
|
||||||
|
// This vertex is a point. Round its corners
|
||||||
|
var dxToPreviousVertex = vertex.dx - previousVertex.dx;
|
||||||
|
var dyToPreviousVertex = vertex.dy - previousVertex.dy;
|
||||||
|
var dxToNextVertex = nextVertex.dx - vertex.dx;
|
||||||
|
var dyToNextVertex = nextVertex.dy - vertex.dy;
|
||||||
|
|
||||||
|
var dToPreviousVertex = hypot(dxToPreviousVertex, dyToPreviousVertex);
|
||||||
|
var dToNextVertex = hypot(dxToNextVertex, dyToNextVertex);
|
||||||
|
|
||||||
|
double previousVertexPercent =
|
||||||
|
math.min(roundedness / dToPreviousVertex, 0.5);
|
||||||
|
double nextVertexPercent = math.min(roundedness / dToNextVertex, 0.5);
|
||||||
|
|
||||||
|
// Split the vertex into two and move each vertex towards the previous/next vertex.
|
||||||
|
var newVertex1X =
|
||||||
|
vertex.dx + (previousVertex.dx - vertex.dx) * previousVertexPercent;
|
||||||
|
var newVertex1Y =
|
||||||
|
vertex.dy + (previousVertex.dy - vertex.dy) * previousVertexPercent;
|
||||||
|
var newVertex2X =
|
||||||
|
vertex.dx + (nextVertex.dx - vertex.dx) * nextVertexPercent;
|
||||||
|
var newVertex2Y =
|
||||||
|
vertex.dy + (nextVertex.dy - vertex.dy) * nextVertexPercent;
|
||||||
|
|
||||||
|
// Extend the new vertex control point towards the original vertex.
|
||||||
|
var newVertex1OutPointX =
|
||||||
|
newVertex1X - (newVertex1X - vertex.dx) * _roundedCornerMagicNumber;
|
||||||
|
var newVertex1OutPointY =
|
||||||
|
newVertex1Y - (newVertex1Y - vertex.dy) * _roundedCornerMagicNumber;
|
||||||
|
var newVertex2InPointX =
|
||||||
|
newVertex2X - (newVertex2X - vertex.dx) * _roundedCornerMagicNumber;
|
||||||
|
var newVertex2InPointY =
|
||||||
|
newVertex2Y - (newVertex2Y - vertex.dy) * _roundedCornerMagicNumber;
|
||||||
|
|
||||||
|
// Remap vertex/in/out point to CubicCurveData.
|
||||||
|
// Refer to the docs for CubicCurveData for more info on the difference.
|
||||||
|
var previousCurveData = modifiedCurves[
|
||||||
|
floorMod(modifiedCurvesIndex - 1, modifiedCurves.length)];
|
||||||
|
var currentCurveData = modifiedCurves[modifiedCurvesIndex];
|
||||||
|
previousCurveData.controlPoint2 = Offset(newVertex1X, newVertex1Y);
|
||||||
|
previousCurveData.vertex = Offset(newVertex1X, newVertex1Y);
|
||||||
|
if (i == 0) {
|
||||||
|
modifiedShapeData.setInitialPoint(newVertex1X, newVertex1Y);
|
||||||
|
}
|
||||||
|
currentCurveData.controlPoint1 =
|
||||||
|
Offset(newVertex1OutPointX, newVertex1OutPointY);
|
||||||
|
modifiedCurvesIndex++;
|
||||||
|
|
||||||
|
previousCurveData = currentCurveData;
|
||||||
|
currentCurveData = modifiedCurves[modifiedCurvesIndex];
|
||||||
|
previousCurveData.controlPoint2 =
|
||||||
|
Offset(newVertex2InPointX, newVertex2InPointY);
|
||||||
|
previousCurveData.vertex = Offset(newVertex2X, newVertex2Y);
|
||||||
|
currentCurveData.controlPoint1 = Offset(newVertex2X, newVertex2Y);
|
||||||
|
modifiedCurvesIndex++;
|
||||||
|
} else {
|
||||||
|
// This vertex is not a point. Don't modify it. Refer to the documentation above and for CubicCurveData for mapping a vertex
|
||||||
|
// oriented point to CubicCurveData (path segments).
|
||||||
|
var previousCurveData = modifiedCurves[
|
||||||
|
floorMod(modifiedCurvesIndex - 1, modifiedCurves.length)];
|
||||||
|
var currentCurveData = modifiedCurves[modifiedCurvesIndex];
|
||||||
|
previousCurveData.controlPoint2 =
|
||||||
|
Offset(previousCurve.vertex.dx, previousCurve.vertex.dy);
|
||||||
|
previousCurveData.vertex =
|
||||||
|
Offset(previousCurve.vertex.dx, previousCurve.vertex.dy);
|
||||||
|
currentCurveData.controlPoint1 =
|
||||||
|
Offset(startingCurve.vertex.dx, startingCurve.vertex.dy);
|
||||||
|
modifiedCurvesIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modifiedShapeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a shape data with the correct number of vertices for the rounded corners shape.
|
||||||
|
/// This just returns the object. It does not update any values within the shape.
|
||||||
|
|
||||||
|
ShapeData _getShapeData(ShapeData startingShapeData) {
|
||||||
|
var startingCurves = startingShapeData.curves;
|
||||||
|
var isClosed = startingShapeData.isClosed;
|
||||||
|
var vertices = 0;
|
||||||
|
for (var i = startingCurves.length - 1; i >= 0; i--) {
|
||||||
|
var startingCurve = startingCurves[i];
|
||||||
|
var previousCurve =
|
||||||
|
startingCurves[floorMod(i - 1, startingCurves.length)];
|
||||||
|
var vertex = (i == 0 && !isClosed)
|
||||||
|
? startingShapeData.initialPoint
|
||||||
|
: previousCurve.vertex;
|
||||||
|
var inPoint =
|
||||||
|
(i == 0 && !isClosed) ? vertex : previousCurve.controlPoint2;
|
||||||
|
var outPoint = startingCurve.controlPoint1;
|
||||||
|
|
||||||
|
var isEndOfCurve = !startingShapeData.isClosed &&
|
||||||
|
(i == 0 && i == startingCurves.length - 1);
|
||||||
|
if (inPoint == vertex && outPoint == vertex && !isEndOfCurve) {
|
||||||
|
vertices += 2;
|
||||||
|
} else {
|
||||||
|
vertices += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var shapeData = this.shapeData;
|
||||||
|
if (shapeData == null || shapeData.curves.length != vertices) {
|
||||||
|
var newCurves = <CubicCurveData>[];
|
||||||
|
for (var i = 0; i < vertices; i++) {
|
||||||
|
newCurves.add(CubicCurveData());
|
||||||
|
}
|
||||||
|
this.shapeData = shapeData =
|
||||||
|
ShapeData(newCurves, initialPoint: Offset.zero, closed: false);
|
||||||
|
}
|
||||||
|
shapeData.setClosed(isClosed);
|
||||||
|
return shapeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copied from the API 24+ AOSP source.
|
||||||
|
static int floorMod(int x, int y) {
|
||||||
|
return x - floorDiv(x, y) * y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copied from the API 24+ AOSP source.
|
||||||
|
static int floorDiv(int x, int y) {
|
||||||
|
var r = x ~/ y;
|
||||||
|
// if the signs are different and modulo not zero, round down
|
||||||
|
if ((x ^ y) < 0 && (r * y != x)) {
|
||||||
|
r--;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
@ -5,10 +5,11 @@ import '../../model/content/shape_trim_path.dart';
|
|||||||
import '../../model/layer/base_layer.dart';
|
import '../../model/layer/base_layer.dart';
|
||||||
import '../../utils.dart';
|
import '../../utils.dart';
|
||||||
import '../../utils/path_factory.dart';
|
import '../../utils/path_factory.dart';
|
||||||
import '../keyframe/base_keyframe_animation.dart';
|
import '../keyframe/shape_keyframe_animation.dart';
|
||||||
import 'compound_trim_path_content.dart';
|
import 'compound_trim_path_content.dart';
|
||||||
import 'content.dart';
|
import 'content.dart';
|
||||||
import 'path_content.dart';
|
import 'path_content.dart';
|
||||||
|
import 'shape_modifier_content.dart';
|
||||||
import 'trim_path_content.dart';
|
import 'trim_path_content.dart';
|
||||||
|
|
||||||
class ShapeContent implements PathContent {
|
class ShapeContent implements PathContent {
|
||||||
@ -17,7 +18,7 @@ class ShapeContent implements PathContent {
|
|||||||
final ShapePath _shape;
|
final ShapePath _shape;
|
||||||
|
|
||||||
final LottieDrawable lottieDrawable;
|
final LottieDrawable lottieDrawable;
|
||||||
final BaseKeyframeAnimation<Object, Path> _shapeAnimation;
|
final ShapeKeyframeAnimation _shapeAnimation;
|
||||||
|
|
||||||
bool _isPathValid = false;
|
bool _isPathValid = false;
|
||||||
final _trimPaths = CompoundTrimPathContent();
|
final _trimPaths = CompoundTrimPathContent();
|
||||||
@ -35,6 +36,7 @@ class ShapeContent implements PathContent {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
|
void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
|
||||||
|
List<ShapeModifierContent>? shapeModifierContents;
|
||||||
for (var i = 0; i < contentsBefore.length; i++) {
|
for (var i = 0; i < contentsBefore.length; i++) {
|
||||||
var content = contentsBefore[i];
|
var content = contentsBefore[i];
|
||||||
if (content is TrimPathContent &&
|
if (content is TrimPathContent &&
|
||||||
@ -43,8 +45,12 @@ class ShapeContent implements PathContent {
|
|||||||
var trimPath = content;
|
var trimPath = content;
|
||||||
_trimPaths.addTrimPath(trimPath);
|
_trimPaths.addTrimPath(trimPath);
|
||||||
trimPath.addListener(_invalidate);
|
trimPath.addListener(_invalidate);
|
||||||
|
} else if (content is ShapeModifierContent) {
|
||||||
|
shapeModifierContents ??= [];
|
||||||
|
shapeModifierContents.add(content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_shapeAnimation.setShapeModifiers(shapeModifierContents);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
6
lib/src/animation/content/shape_modifier_content.dart
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import '../../model/content/shape_data.dart';
|
||||||
|
import 'content.dart';
|
||||||
|
|
||||||
|
abstract class ShapeModifierContent extends Content {
|
||||||
|
ShapeData modifyShape(ShapeData shapeData);
|
||||||
|
}
|
@ -3,11 +3,13 @@ import '../../model/content/shape_data.dart';
|
|||||||
import '../../utils/misc.dart';
|
import '../../utils/misc.dart';
|
||||||
import '../../utils/path_factory.dart';
|
import '../../utils/path_factory.dart';
|
||||||
import '../../value/keyframe.dart';
|
import '../../value/keyframe.dart';
|
||||||
|
import '../content/shape_modifier_content.dart';
|
||||||
import 'base_keyframe_animation.dart';
|
import 'base_keyframe_animation.dart';
|
||||||
|
|
||||||
class ShapeKeyframeAnimation extends BaseKeyframeAnimation<ShapeData, Path> {
|
class ShapeKeyframeAnimation extends BaseKeyframeAnimation<ShapeData, Path> {
|
||||||
final ShapeData _tempShapeData = ShapeData.empty();
|
final ShapeData _tempShapeData = ShapeData.empty();
|
||||||
final Path _tempPath = PathFactory.create();
|
final Path _tempPath = PathFactory.create();
|
||||||
|
List<ShapeModifierContent>? _shapeModifiers;
|
||||||
|
|
||||||
ShapeKeyframeAnimation(List<Keyframe<ShapeData>> keyframes)
|
ShapeKeyframeAnimation(List<Keyframe<ShapeData>> keyframes)
|
||||||
: super(keyframes);
|
: super(keyframes);
|
||||||
@ -19,7 +21,18 @@ class ShapeKeyframeAnimation extends BaseKeyframeAnimation<ShapeData, Path> {
|
|||||||
|
|
||||||
_tempShapeData.interpolateBetween(
|
_tempShapeData.interpolateBetween(
|
||||||
startShapeData, endShapeData, keyframeProgress);
|
startShapeData, endShapeData, keyframeProgress);
|
||||||
MiscUtils.getPathFromData(_tempShapeData, _tempPath);
|
var modifiedShapeData = _tempShapeData;
|
||||||
|
var shapeModifiers = _shapeModifiers;
|
||||||
|
if (shapeModifiers != null) {
|
||||||
|
for (var i = shapeModifiers.length - 1; i >= 0; i--) {
|
||||||
|
modifiedShapeData = shapeModifiers[i].modifyShape(modifiedShapeData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MiscUtils.getPathFromData(modifiedShapeData, _tempPath);
|
||||||
return _tempPath;
|
return _tempPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setShapeModifiers(List<ShapeModifierContent>? shapeModifiers) {
|
||||||
|
_shapeModifiers = shapeModifiers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import '../../model/document_data.dart';
|
import '../../model/document_data.dart';
|
||||||
import '../../value/keyframe.dart';
|
import '../../value/keyframe.dart';
|
||||||
|
import '../../value/lottie_frame_info.dart';
|
||||||
|
import '../../value/lottie_value_callback.dart';
|
||||||
import 'keyframe_animation.dart';
|
import 'keyframe_animation.dart';
|
||||||
|
|
||||||
class TextKeyframeAnimation extends KeyframeAnimation<DocumentData> {
|
class TextKeyframeAnimation extends KeyframeAnimation<DocumentData> {
|
||||||
@ -9,10 +11,58 @@ class TextKeyframeAnimation extends KeyframeAnimation<DocumentData> {
|
|||||||
@override
|
@override
|
||||||
DocumentData getValue(
|
DocumentData getValue(
|
||||||
Keyframe<DocumentData> keyframe, double keyframeProgress) {
|
Keyframe<DocumentData> keyframe, double keyframeProgress) {
|
||||||
if (keyframeProgress != 1.0 || keyframe.endValue == null) {
|
var valueCallback = this.valueCallback;
|
||||||
|
if (valueCallback != null) {
|
||||||
|
return valueCallback.getValueInternal(
|
||||||
|
keyframe.startFrame,
|
||||||
|
keyframe.endFrame ?? double.maxFinite,
|
||||||
|
keyframe.startValue,
|
||||||
|
keyframe.endValue ?? keyframe.startValue,
|
||||||
|
keyframeProgress,
|
||||||
|
getInterpolatedCurrentKeyframeProgress(),
|
||||||
|
progress)!;
|
||||||
|
} else if (keyframeProgress != 1.0 || keyframe.endValue == null) {
|
||||||
return keyframe.startValue!;
|
return keyframe.startValue!;
|
||||||
} else {
|
} else {
|
||||||
return keyframe.endValue!;
|
return keyframe.endValue!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setStringValueCallback(LottieValueCallback<String> valueCallback) {
|
||||||
|
super.setValueCallback(_DocumentDataValueCallback(valueCallback));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DocumentDataValueCallback extends LottieValueCallback<DocumentData> {
|
||||||
|
final LottieValueCallback<String> valueCallback;
|
||||||
|
|
||||||
|
_DocumentDataValueCallback(this.valueCallback) : super(null);
|
||||||
|
|
||||||
|
@override
|
||||||
|
DocumentData getValue(LottieFrameInfo<DocumentData> frameInfo) {
|
||||||
|
var stringFrameInfo = LottieFrameInfo<String>(
|
||||||
|
frameInfo.startFrame,
|
||||||
|
frameInfo.endFrame,
|
||||||
|
frameInfo.startValue!.text,
|
||||||
|
frameInfo.endValue!.text,
|
||||||
|
frameInfo.linearKeyframeProgress,
|
||||||
|
frameInfo.interpolatedKeyframeProgress,
|
||||||
|
frameInfo.overallProgress);
|
||||||
|
var text = valueCallback.getValue(stringFrameInfo)!;
|
||||||
|
var baseDocumentData = frameInfo.interpolatedKeyframeProgress == 1
|
||||||
|
? frameInfo.endValue!
|
||||||
|
: frameInfo.startValue!;
|
||||||
|
return DocumentData(
|
||||||
|
text: text,
|
||||||
|
fontName: baseDocumentData.fontName,
|
||||||
|
size: baseDocumentData.size,
|
||||||
|
justification: baseDocumentData.justification,
|
||||||
|
tracking: baseDocumentData.tracking,
|
||||||
|
lineHeight: baseDocumentData.lineHeight,
|
||||||
|
baselineShift: baseDocumentData.baselineShift,
|
||||||
|
color: baseDocumentData.color,
|
||||||
|
strokeColor: baseDocumentData.strokeColor,
|
||||||
|
strokeWidth: baseDocumentData.strokeWidth,
|
||||||
|
strokeOverFill: baseDocumentData.strokeOverFill);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ class Lottie extends StatefulWidget {
|
|||||||
this.delegates,
|
this.delegates,
|
||||||
this.options,
|
this.options,
|
||||||
bool? addRepaintBoundary,
|
bool? addRepaintBoundary,
|
||||||
|
this.filterQuality,
|
||||||
}) : animate = animate ?? true,
|
}) : animate = animate ?? true,
|
||||||
reverse = reverse ?? false,
|
reverse = reverse ?? false,
|
||||||
repeat = repeat ?? true,
|
repeat = repeat ?? true,
|
||||||
@ -51,9 +52,10 @@ class Lottie extends StatefulWidget {
|
|||||||
double? width,
|
double? width,
|
||||||
double? height,
|
double? height,
|
||||||
BoxFit? fit,
|
BoxFit? fit,
|
||||||
Alignment? alignment,
|
AlignmentGeometry? alignment,
|
||||||
String? package,
|
String? package,
|
||||||
bool? addRepaintBoundary,
|
bool? addRepaintBoundary,
|
||||||
|
FilterQuality? filterQuality,
|
||||||
WarningCallback? onWarning,
|
WarningCallback? onWarning,
|
||||||
}) =>
|
}) =>
|
||||||
LottieBuilder.asset(
|
LottieBuilder.asset(
|
||||||
@ -77,6 +79,7 @@ class Lottie extends StatefulWidget {
|
|||||||
alignment: alignment,
|
alignment: alignment,
|
||||||
package: package,
|
package: package,
|
||||||
addRepaintBoundary: addRepaintBoundary,
|
addRepaintBoundary: addRepaintBoundary,
|
||||||
|
filterQuality: filterQuality,
|
||||||
onWarning: onWarning,
|
onWarning: onWarning,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -98,8 +101,9 @@ class Lottie extends StatefulWidget {
|
|||||||
double? width,
|
double? width,
|
||||||
double? height,
|
double? height,
|
||||||
BoxFit? fit,
|
BoxFit? fit,
|
||||||
Alignment? alignment,
|
AlignmentGeometry? alignment,
|
||||||
bool? addRepaintBoundary,
|
bool? addRepaintBoundary,
|
||||||
|
FilterQuality? filterQuality,
|
||||||
WarningCallback? onWarning,
|
WarningCallback? onWarning,
|
||||||
}) =>
|
}) =>
|
||||||
LottieBuilder.file(
|
LottieBuilder.file(
|
||||||
@ -121,6 +125,7 @@ class Lottie extends StatefulWidget {
|
|||||||
fit: fit,
|
fit: fit,
|
||||||
alignment: alignment,
|
alignment: alignment,
|
||||||
addRepaintBoundary: addRepaintBoundary,
|
addRepaintBoundary: addRepaintBoundary,
|
||||||
|
filterQuality: filterQuality,
|
||||||
onWarning: onWarning,
|
onWarning: onWarning,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -142,8 +147,9 @@ class Lottie extends StatefulWidget {
|
|||||||
double? width,
|
double? width,
|
||||||
double? height,
|
double? height,
|
||||||
BoxFit? fit,
|
BoxFit? fit,
|
||||||
Alignment? alignment,
|
AlignmentGeometry? alignment,
|
||||||
bool? addRepaintBoundary,
|
bool? addRepaintBoundary,
|
||||||
|
FilterQuality? filterQuality,
|
||||||
WarningCallback? onWarning,
|
WarningCallback? onWarning,
|
||||||
}) =>
|
}) =>
|
||||||
LottieBuilder.memory(
|
LottieBuilder.memory(
|
||||||
@ -165,6 +171,7 @@ class Lottie extends StatefulWidget {
|
|||||||
fit: fit,
|
fit: fit,
|
||||||
alignment: alignment,
|
alignment: alignment,
|
||||||
addRepaintBoundary: addRepaintBoundary,
|
addRepaintBoundary: addRepaintBoundary,
|
||||||
|
filterQuality: filterQuality,
|
||||||
onWarning: onWarning,
|
onWarning: onWarning,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -186,8 +193,9 @@ class Lottie extends StatefulWidget {
|
|||||||
double? width,
|
double? width,
|
||||||
double? height,
|
double? height,
|
||||||
BoxFit? fit,
|
BoxFit? fit,
|
||||||
Alignment? alignment,
|
AlignmentGeometry? alignment,
|
||||||
bool? addRepaintBoundary,
|
bool? addRepaintBoundary,
|
||||||
|
FilterQuality? filterQuality,
|
||||||
WarningCallback? onWarning,
|
WarningCallback? onWarning,
|
||||||
}) =>
|
}) =>
|
||||||
LottieBuilder.network(
|
LottieBuilder.network(
|
||||||
@ -209,6 +217,7 @@ class Lottie extends StatefulWidget {
|
|||||||
fit: fit,
|
fit: fit,
|
||||||
alignment: alignment,
|
alignment: alignment,
|
||||||
addRepaintBoundary: addRepaintBoundary,
|
addRepaintBoundary: addRepaintBoundary,
|
||||||
|
filterQuality: filterQuality,
|
||||||
onWarning: onWarning,
|
onWarning: onWarning,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -299,13 +308,19 @@ class Lottie extends StatefulWidget {
|
|||||||
/// This property is `true` by default.
|
/// This property is `true` by default.
|
||||||
final bool addRepaintBoundary;
|
final bool addRepaintBoundary;
|
||||||
|
|
||||||
|
/// The quality of the image layer. See [FilterQuality]
|
||||||
|
/// [FilterQuality.high] is highest quality but slowest.
|
||||||
|
///
|
||||||
|
/// Defaults to [FilterQuality.low]
|
||||||
|
final FilterQuality? filterQuality;
|
||||||
|
|
||||||
static bool get traceEnabled => L.traceEnabled;
|
static bool get traceEnabled => L.traceEnabled;
|
||||||
static set traceEnabled(bool enabled) {
|
static set traceEnabled(bool enabled) {
|
||||||
L.traceEnabled = enabled;
|
L.traceEnabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_LottieState createState() => _LottieState();
|
State<Lottie> createState() => _LottieState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LottieState extends State<Lottie> with TickerProviderStateMixin {
|
class _LottieState extends State<Lottie> with TickerProviderStateMixin {
|
||||||
@ -366,6 +381,7 @@ class _LottieState extends State<Lottie> with TickerProviderStateMixin {
|
|||||||
height: widget.height,
|
height: widget.height,
|
||||||
fit: widget.fit,
|
fit: widget.fit,
|
||||||
alignment: widget.alignment,
|
alignment: widget.alignment,
|
||||||
|
filterQuality: widget.filterQuality,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -59,6 +59,7 @@ class LottieBuilder extends StatefulWidget {
|
|||||||
this.fit,
|
this.fit,
|
||||||
this.alignment,
|
this.alignment,
|
||||||
this.addRepaintBoundary,
|
this.addRepaintBoundary,
|
||||||
|
this.filterQuality,
|
||||||
this.onWarning,
|
this.onWarning,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@ -83,6 +84,7 @@ class LottieBuilder extends StatefulWidget {
|
|||||||
this.fit,
|
this.fit,
|
||||||
this.alignment,
|
this.alignment,
|
||||||
this.addRepaintBoundary,
|
this.addRepaintBoundary,
|
||||||
|
this.filterQuality,
|
||||||
this.onWarning,
|
this.onWarning,
|
||||||
}) : lottie = NetworkLottie(src,
|
}) : lottie = NetworkLottie(src,
|
||||||
headers: headers, imageProviderFactory: imageProviderFactory),
|
headers: headers, imageProviderFactory: imageProviderFactory),
|
||||||
@ -117,6 +119,7 @@ class LottieBuilder extends StatefulWidget {
|
|||||||
this.fit,
|
this.fit,
|
||||||
this.alignment,
|
this.alignment,
|
||||||
this.addRepaintBoundary,
|
this.addRepaintBoundary,
|
||||||
|
this.filterQuality,
|
||||||
this.onWarning,
|
this.onWarning,
|
||||||
}) : lottie = FileLottie(file, imageProviderFactory: imageProviderFactory),
|
}) : lottie = FileLottie(file, imageProviderFactory: imageProviderFactory),
|
||||||
super(key: key);
|
super(key: key);
|
||||||
@ -143,6 +146,7 @@ class LottieBuilder extends StatefulWidget {
|
|||||||
this.alignment,
|
this.alignment,
|
||||||
String? package,
|
String? package,
|
||||||
this.addRepaintBoundary,
|
this.addRepaintBoundary,
|
||||||
|
this.filterQuality,
|
||||||
this.onWarning,
|
this.onWarning,
|
||||||
}) : lottie = AssetLottie(name,
|
}) : lottie = AssetLottie(name,
|
||||||
bundle: bundle,
|
bundle: bundle,
|
||||||
@ -170,6 +174,7 @@ class LottieBuilder extends StatefulWidget {
|
|||||||
this.fit,
|
this.fit,
|
||||||
this.alignment,
|
this.alignment,
|
||||||
this.addRepaintBoundary,
|
this.addRepaintBoundary,
|
||||||
|
this.filterQuality,
|
||||||
this.onWarning,
|
this.onWarning,
|
||||||
}) : lottie =
|
}) : lottie =
|
||||||
MemoryLottie(bytes, imageProviderFactory: imageProviderFactory),
|
MemoryLottie(bytes, imageProviderFactory: imageProviderFactory),
|
||||||
@ -361,6 +366,12 @@ class LottieBuilder extends StatefulWidget {
|
|||||||
/// This property is `true` by default.
|
/// This property is `true` by default.
|
||||||
final bool? addRepaintBoundary;
|
final bool? addRepaintBoundary;
|
||||||
|
|
||||||
|
/// The quality of the image layer. See [FilterQuality]
|
||||||
|
/// [FilterQuality.high] is highest quality but slowest.
|
||||||
|
///
|
||||||
|
/// Defaults to [FilterQuality.low]
|
||||||
|
final FilterQuality? filterQuality;
|
||||||
|
|
||||||
/// A callback called when there is a warning during the loading or painting
|
/// A callback called when there is a warning during the loading or painting
|
||||||
/// of the animation.
|
/// of the animation.
|
||||||
final WarningCallback? onWarning;
|
final WarningCallback? onWarning;
|
||||||
@ -398,7 +409,7 @@ class LottieBuilder extends StatefulWidget {
|
|||||||
final ImageErrorWidgetBuilder? errorBuilder;
|
final ImageErrorWidgetBuilder? errorBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_LottieBuilderState createState() => _LottieBuilderState();
|
State<LottieBuilder> createState() => _LottieBuilderState();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
@ -482,6 +493,7 @@ class _LottieBuilderState extends State<LottieBuilder> {
|
|||||||
fit: widget.fit,
|
fit: widget.fit,
|
||||||
alignment: widget.alignment,
|
alignment: widget.alignment,
|
||||||
addRepaintBoundary: widget.addRepaintBoundary,
|
addRepaintBoundary: widget.addRepaintBoundary,
|
||||||
|
filterQuality: widget.filterQuality,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (widget.frameBuilder != null) {
|
if (widget.frameBuilder != null) {
|
||||||
|
@ -16,16 +16,15 @@ class LottieDrawable {
|
|||||||
final Size size;
|
final Size size;
|
||||||
LottieDelegates? _delegates;
|
LottieDelegates? _delegates;
|
||||||
bool _isDirty = true;
|
bool _isDirty = true;
|
||||||
final bool enableMergePaths;
|
bool enableMergePaths = false;
|
||||||
|
FilterQuality? filterQuality;
|
||||||
|
|
||||||
/// Gives a suggestion whether to paint with anti-aliasing, or not. Default is true.
|
/// Gives a suggestion whether to paint with anti-aliasing, or not. Default is true.
|
||||||
bool antiAliasingSuggested = true;
|
bool antiAliasingSuggested = true;
|
||||||
|
|
||||||
LottieDrawable(this.composition,
|
LottieDrawable(this.composition, {LottieDelegates? delegates})
|
||||||
{LottieDelegates? delegates, bool? enableMergePaths})
|
|
||||||
: size = Size(composition.bounds.width.toDouble(),
|
: size = Size(composition.bounds.width.toDouble(),
|
||||||
composition.bounds.height.toDouble()),
|
composition.bounds.height.toDouble()) {
|
||||||
enableMergePaths = enableMergePaths ?? false {
|
|
||||||
this.delegates = delegates;
|
this.delegates = delegates;
|
||||||
_compositionLayer = CompositionLayer(
|
_compositionLayer = CompositionLayer(
|
||||||
this, LayerParser.parse(composition), composition.layers, composition);
|
this, LayerParser.parse(composition), composition.layers, composition);
|
||||||
|
@ -129,8 +129,12 @@ abstract class LottieProperty {
|
|||||||
static const dropShadow = DropShadow(
|
static const dropShadow = DropShadow(
|
||||||
color: Color(0x00000000), direction: 0, distance: 0, radius: 0);
|
color: Color(0x00000000), direction: 0, distance: 0, radius: 0);
|
||||||
|
|
||||||
|
/// Set the color filter for an entire drawable content. Can be applied to fills, strokes, images, and solids.
|
||||||
static const ColorFilter colorFilter =
|
static const ColorFilter colorFilter =
|
||||||
ColorFilter.mode(Color(0xFF000000), BlendMode.dst);
|
ColorFilter.mode(Color(0xFF000000), BlendMode.dst);
|
||||||
|
|
||||||
static final List<Color> gradientColor = [];
|
static final List<Color> gradientColor = [];
|
||||||
|
|
||||||
|
/// Replace the text for a text layer.
|
||||||
|
static const text = 'dynamic_text';
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
import '../../animation/keyframe/base_keyframe_animation.dart';
|
|
||||||
import '../../animation/keyframe/shape_keyframe_animation.dart';
|
import '../../animation/keyframe/shape_keyframe_animation.dart';
|
||||||
import '../../value/keyframe.dart';
|
import '../../value/keyframe.dart';
|
||||||
import '../content/shape_data.dart';
|
import '../content/shape_data.dart';
|
||||||
@ -10,7 +9,7 @@ class AnimatableShapeValue extends BaseAnimatableValue<ShapeData, Path> {
|
|||||||
: super.fromKeyframes(keyframes);
|
: super.fromKeyframes(keyframes);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
BaseKeyframeAnimation<ShapeData, Path> createAnimation() {
|
ShapeKeyframeAnimation createAnimation() {
|
||||||
return ShapeKeyframeAnimation(keyframes);
|
return ShapeKeyframeAnimation(keyframes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ class PolystarShape implements ContentModel {
|
|||||||
final AnimatableDoubleValue? innerRoundedness;
|
final AnimatableDoubleValue? innerRoundedness;
|
||||||
final AnimatableDoubleValue outerRoundedness;
|
final AnimatableDoubleValue outerRoundedness;
|
||||||
final bool hidden;
|
final bool hidden;
|
||||||
|
final bool isReversed;
|
||||||
|
|
||||||
PolystarShape({
|
PolystarShape({
|
||||||
this.name,
|
this.name,
|
||||||
@ -49,6 +50,7 @@ class PolystarShape implements ContentModel {
|
|||||||
this.innerRoundedness,
|
this.innerRoundedness,
|
||||||
required this.outerRoundedness,
|
required this.outerRoundedness,
|
||||||
required this.hidden,
|
required this.hidden,
|
||||||
|
required this.isReversed,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
18
lib/src/model/content/rounded_corners.dart
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import '../../animation/content/content.dart';
|
||||||
|
import '../../animation/content/rounded_corners_content.dart';
|
||||||
|
import '../../lottie_drawable.dart';
|
||||||
|
import '../animatable/animatable_value.dart';
|
||||||
|
import '../layer/base_layer.dart';
|
||||||
|
import 'content_model.dart';
|
||||||
|
|
||||||
|
class RoundedCorners implements ContentModel {
|
||||||
|
final String name;
|
||||||
|
final AnimatableValue<double, double> cornerRadius;
|
||||||
|
|
||||||
|
RoundedCorners(this.name, this.cornerRadius);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Content toContent(LottieDrawable drawable, BaseLayer layer) {
|
||||||
|
return RoundedCornersContent(drawable, layer, this);
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,10 @@ class ShapeData {
|
|||||||
return _initialPoint;
|
return _initialPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setClosed(bool closed) {
|
||||||
|
_closed = closed;
|
||||||
|
}
|
||||||
|
|
||||||
bool get isClosed {
|
bool get isClosed {
|
||||||
return _closed;
|
return _closed;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,44 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
|
/// One cubic path operation. CubicCurveData is structured such that it is easy to iterate through
|
||||||
|
/// it and build a path. However, it is modeled differently than most path operations.
|
||||||
|
///
|
||||||
|
/// CubicCurveData
|
||||||
|
/// | - vertex
|
||||||
|
/// | /
|
||||||
|
/// | cp1 cp2
|
||||||
|
/// | /
|
||||||
|
/// | |
|
||||||
|
/// | /
|
||||||
|
/// --------------------------
|
||||||
|
///
|
||||||
|
/// When incrementally building a path, it will already have a "current point" so that is
|
||||||
|
/// not captured in this data structure.
|
||||||
|
/// The control points here represent {@link android.graphics.Path#cubicTo(float, float, float, float, float, float)}.
|
||||||
|
///
|
||||||
|
/// Most path operations are centered around a vertex and its in control point and out control point like this:
|
||||||
|
/// | outCp
|
||||||
|
/// | /
|
||||||
|
/// | |
|
||||||
|
/// | v
|
||||||
|
/// | /
|
||||||
|
/// | inCp
|
||||||
|
/// --------------------------
|
||||||
class CubicCurveData {
|
class CubicCurveData {
|
||||||
Offset controlPoint1 = Offset.zero;
|
Offset controlPoint1 = Offset.zero;
|
||||||
Offset controlPoint2 = Offset.zero;
|
Offset controlPoint2 = Offset.zero;
|
||||||
Offset vertex = Offset.zero;
|
Offset vertex = Offset.zero;
|
||||||
|
|
||||||
|
void setFrom(CubicCurveData curveData) {
|
||||||
|
vertex = Offset(curveData.vertex.dx, curveData.vertex.dy);
|
||||||
|
controlPoint1 =
|
||||||
|
Offset(curveData.controlPoint1.dx, curveData.controlPoint1.dy);
|
||||||
|
controlPoint2 =
|
||||||
|
Offset(curveData.controlPoint2.dx, curveData.controlPoint2.dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'v=$vertex cp1$controlPoint1 cp2=$controlPoint2';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ class ImageLayer extends BaseLayer {
|
|||||||
}
|
}
|
||||||
var density = window.devicePixelRatio;
|
var density = window.devicePixelRatio;
|
||||||
|
|
||||||
|
paint.filterQuality = lottieDrawable.filterQuality ?? FilterQuality.low;
|
||||||
paint.setAlpha(parentAlpha);
|
paint.setAlpha(parentAlpha);
|
||||||
if (_colorFilterAnimation != null) {
|
if (_colorFilterAnimation != null) {
|
||||||
paint.colorFilter = _colorFilterAnimation!.value;
|
paint.colorFilter = _colorFilterAnimation!.value;
|
||||||
|
@ -484,6 +484,11 @@ class TextLayer extends BaseLayer {
|
|||||||
..addUpdateListener(invalidateSelf);
|
..addUpdateListener(invalidateSelf);
|
||||||
addAnimation(_textSizeCallbackAnimation);
|
addAnimation(_textSizeCallbackAnimation);
|
||||||
}
|
}
|
||||||
|
} else if (property == LottieProperty.text) {
|
||||||
|
if (callback != null) {
|
||||||
|
_textAnimation
|
||||||
|
.setStringValueCallback(callback as LottieValueCallback<String>);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import 'moshi/json_reader.dart';
|
|||||||
import 'polysar_shape_parser.dart';
|
import 'polysar_shape_parser.dart';
|
||||||
import 'rectangle_shape_parser.dart';
|
import 'rectangle_shape_parser.dart';
|
||||||
import 'repeat_parser.dart';
|
import 'repeat_parser.dart';
|
||||||
|
import 'rounded_corners_parser.dart';
|
||||||
import 'shape_fill_parser.dart';
|
import 'shape_fill_parser.dart';
|
||||||
import 'shape_group_parser.dart';
|
import 'shape_group_parser.dart';
|
||||||
import 'shape_path_parser.dart';
|
import 'shape_path_parser.dart';
|
||||||
@ -80,7 +81,7 @@ class ContentModelParser {
|
|||||||
model = ShapeTrimPathParser.parse(reader, composition);
|
model = ShapeTrimPathParser.parse(reader, composition);
|
||||||
break;
|
break;
|
||||||
case 'sr':
|
case 'sr':
|
||||||
model = PolystarShapeParser.parse(reader, composition);
|
model = PolystarShapeParser.parse(reader, composition, d: d);
|
||||||
break;
|
break;
|
||||||
case 'mm':
|
case 'mm':
|
||||||
model = MergePathsParser.parse(reader);
|
model = MergePathsParser.parse(reader);
|
||||||
@ -88,6 +89,9 @@ class ContentModelParser {
|
|||||||
case 'rp':
|
case 'rp':
|
||||||
model = RepeaterParser.parse(reader, composition);
|
model = RepeaterParser.parse(reader, composition);
|
||||||
break;
|
break;
|
||||||
|
case 'rd':
|
||||||
|
model = RoundedCornersParser.parse(reader, composition);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
composition.addWarning('Unknown shape type $type');
|
composition.addWarning('Unknown shape type $type');
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,19 @@ import '../model/document_data.dart';
|
|||||||
import 'json_utils.dart';
|
import 'json_utils.dart';
|
||||||
import 'moshi/json_reader.dart';
|
import 'moshi/json_reader.dart';
|
||||||
|
|
||||||
final JsonReaderOptions _names = JsonReaderOptions.of(
|
final JsonReaderOptions _names = JsonReaderOptions.of([
|
||||||
['t', 'f', 's', 'j', 'tr', 'lh', 'ls', 'fc', 'sc', 'sw', 'of']);
|
't', // 0
|
||||||
|
'f', // 1
|
||||||
|
's', // 2
|
||||||
|
'j', // 3
|
||||||
|
'tr', // 4
|
||||||
|
'lh', // 5
|
||||||
|
'ls', // 6
|
||||||
|
'fc', // 7
|
||||||
|
'sc', // 8
|
||||||
|
'sw', // 9
|
||||||
|
'of', // 10
|
||||||
|
]);
|
||||||
|
|
||||||
DocumentData documentDataParser(JsonReader reader, {required double scale}) {
|
DocumentData documentDataParser(JsonReader reader, {required double scale}) {
|
||||||
String? text;
|
String? text;
|
||||||
|
@ -37,6 +37,17 @@ class GradientColorParser {
|
|||||||
while (reader.hasNext()) {
|
while (reader.hasNext()) {
|
||||||
array.add(reader.nextDouble());
|
array.add(reader.nextDouble());
|
||||||
}
|
}
|
||||||
|
if (array.length == 4 && array[0] == 1) {
|
||||||
|
// If a gradient color only contains one color at position 1, add a second stop with the same
|
||||||
|
// color at position 0. Android's LinearGradient shader requires at least two colors.
|
||||||
|
// https://github.com/airbnb/lottie-android/issues/1967
|
||||||
|
array[0] = 0;
|
||||||
|
array.add(1);
|
||||||
|
array.add(array[1]);
|
||||||
|
array.add(array[2]);
|
||||||
|
array.add(array[3]);
|
||||||
|
_colorPoints = 2;
|
||||||
|
}
|
||||||
if (isArray) {
|
if (isArray) {
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,12 @@ import 'moshi/json_reader.dart';
|
|||||||
|
|
||||||
class PolystarShapeParser {
|
class PolystarShapeParser {
|
||||||
static final JsonReaderOptions _names = JsonReaderOptions.of(
|
static final JsonReaderOptions _names = JsonReaderOptions.of(
|
||||||
['nm', 'sy', 'pt', 'p', 'r', 'or', 'os', 'ir', 'is', 'hd']);
|
['nm', 'sy', 'pt', 'p', 'r', 'or', 'os', 'ir', 'is', 'hd', 'd']);
|
||||||
|
|
||||||
PolystarShapeParser._();
|
PolystarShapeParser._();
|
||||||
|
|
||||||
static PolystarShape parse(JsonReader reader, LottieComposition composition) {
|
static PolystarShape parse(JsonReader reader, LottieComposition composition,
|
||||||
|
{required int d}) {
|
||||||
String? name;
|
String? name;
|
||||||
PolystarShapeType? type;
|
PolystarShapeType? type;
|
||||||
late AnimatableDoubleValue points;
|
late AnimatableDoubleValue points;
|
||||||
@ -24,6 +25,7 @@ class PolystarShapeParser {
|
|||||||
AnimatableDoubleValue? innerRadius;
|
AnimatableDoubleValue? innerRadius;
|
||||||
AnimatableDoubleValue? innerRoundedness;
|
AnimatableDoubleValue? innerRoundedness;
|
||||||
var hidden = false;
|
var hidden = false;
|
||||||
|
var reversed = d == 3;
|
||||||
|
|
||||||
while (reader.hasNext()) {
|
while (reader.hasNext()) {
|
||||||
switch (reader.selectName(_names)) {
|
switch (reader.selectName(_names)) {
|
||||||
@ -64,6 +66,10 @@ class PolystarShapeParser {
|
|||||||
case 9:
|
case 9:
|
||||||
hidden = reader.nextBoolean();
|
hidden = reader.nextBoolean();
|
||||||
break;
|
break;
|
||||||
|
case 10:
|
||||||
|
// "d" is 2 for normal and 3 for reversed.
|
||||||
|
reversed = reader.nextInt() == 3;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
reader.skipName();
|
reader.skipName();
|
||||||
reader.skipValue();
|
reader.skipValue();
|
||||||
@ -81,6 +87,7 @@ class PolystarShapeParser {
|
|||||||
innerRoundedness: innerRoundedness,
|
innerRoundedness: innerRoundedness,
|
||||||
outerRoundedness: outerRoundedness,
|
outerRoundedness: outerRoundedness,
|
||||||
hidden: hidden,
|
hidden: hidden,
|
||||||
|
isReversed: reversed,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
lib/src/parser/rounded_corners_parser.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import '../composition.dart';
|
||||||
|
import '../model/animatable/animatable_value.dart';
|
||||||
|
import '../model/content/rounded_corners.dart';
|
||||||
|
import 'animatable_value_parser.dart';
|
||||||
|
import 'moshi/json_reader.dart';
|
||||||
|
|
||||||
|
class RoundedCornersParser {
|
||||||
|
static final _names = JsonReaderOptions.of([
|
||||||
|
'nm', // 0
|
||||||
|
'r', // 1
|
||||||
|
'hd' // 1
|
||||||
|
]);
|
||||||
|
|
||||||
|
static RoundedCorners? parse(
|
||||||
|
JsonReader reader, LottieComposition composition) {
|
||||||
|
String? name;
|
||||||
|
AnimatableValue<double, double>? cornerRadius;
|
||||||
|
var hidden = false;
|
||||||
|
|
||||||
|
while (reader.hasNext()) {
|
||||||
|
switch (reader.selectName(_names)) {
|
||||||
|
case 0: //nm
|
||||||
|
name = reader.nextString();
|
||||||
|
break;
|
||||||
|
case 1: // r
|
||||||
|
cornerRadius =
|
||||||
|
AnimatableValueParser.parseFloat(reader, composition, isDp: true);
|
||||||
|
break;
|
||||||
|
case 2: // hd
|
||||||
|
hidden = reader.nextBoolean();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reader.skipValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hidden ? null : RoundedCorners(name!, cornerRadius!);
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ class RawLottie extends LeafRenderObjectWidget {
|
|||||||
this.height,
|
this.height,
|
||||||
this.fit,
|
this.fit,
|
||||||
AlignmentGeometry? alignment,
|
AlignmentGeometry? alignment,
|
||||||
|
this.filterQuality,
|
||||||
}) : progress = progress ?? 0.0,
|
}) : progress = progress ?? 0.0,
|
||||||
alignment = alignment ?? Alignment.center,
|
alignment = alignment ?? Alignment.center,
|
||||||
super(key: key);
|
super(key: key);
|
||||||
@ -78,6 +79,8 @@ class RawLottie extends LeafRenderObjectWidget {
|
|||||||
/// relative to text direction.
|
/// relative to text direction.
|
||||||
final AlignmentGeometry alignment;
|
final AlignmentGeometry alignment;
|
||||||
|
|
||||||
|
final FilterQuality? filterQuality;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
RenderLottie createRenderObject(BuildContext context) {
|
RenderLottie createRenderObject(BuildContext context) {
|
||||||
return RenderLottie(
|
return RenderLottie(
|
||||||
@ -90,17 +93,21 @@ class RawLottie extends LeafRenderObjectWidget {
|
|||||||
height: height,
|
height: height,
|
||||||
fit: fit,
|
fit: fit,
|
||||||
alignment: alignment,
|
alignment: alignment,
|
||||||
|
filterQuality: filterQuality,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void updateRenderObject(BuildContext context, RenderLottie renderObject) {
|
void updateRenderObject(BuildContext context, RenderLottie renderObject) {
|
||||||
renderObject
|
renderObject
|
||||||
..setComposition(composition,
|
..setComposition(
|
||||||
|
composition,
|
||||||
progress: progress,
|
progress: progress,
|
||||||
frameRate: frameRate,
|
frameRate: frameRate,
|
||||||
delegates: delegates,
|
delegates: delegates,
|
||||||
enableMergePaths: options?.enableMergePaths)
|
enableMergePaths: options?.enableMergePaths,
|
||||||
|
filterQuality: filterQuality,
|
||||||
|
)
|
||||||
..width = width
|
..width = width
|
||||||
..height = height
|
..height = height
|
||||||
..alignment = alignment
|
..alignment = alignment
|
||||||
|
@ -19,11 +19,14 @@ class RenderLottie extends RenderBox {
|
|||||||
double? height,
|
double? height,
|
||||||
BoxFit? fit,
|
BoxFit? fit,
|
||||||
AlignmentGeometry alignment = Alignment.center,
|
AlignmentGeometry alignment = Alignment.center,
|
||||||
|
FilterQuality? filterQuality,
|
||||||
}) : assert(progress >= 0.0 && progress <= 1.0),
|
}) : assert(progress >= 0.0 && progress <= 1.0),
|
||||||
_drawable = composition != null
|
_drawable = composition != null
|
||||||
? (LottieDrawable(composition, enableMergePaths: enableMergePaths)
|
? (LottieDrawable(composition)
|
||||||
..setProgress(progress, frameRate: frameRate)
|
..setProgress(progress, frameRate: frameRate)
|
||||||
..delegates = delegates)
|
..delegates = delegates
|
||||||
|
..enableMergePaths = enableMergePaths ?? false
|
||||||
|
..filterQuality = filterQuality)
|
||||||
: null,
|
: null,
|
||||||
_width = width,
|
_width = width,
|
||||||
_height = height,
|
_height = height,
|
||||||
@ -33,11 +36,13 @@ class RenderLottie extends RenderBox {
|
|||||||
/// The lottie composition to display.
|
/// The lottie composition to display.
|
||||||
LottieComposition? get composition => _drawable?.composition;
|
LottieComposition? get composition => _drawable?.composition;
|
||||||
LottieDrawable? _drawable;
|
LottieDrawable? _drawable;
|
||||||
|
|
||||||
void setComposition(LottieComposition? composition,
|
void setComposition(LottieComposition? composition,
|
||||||
{required double progress,
|
{required double progress,
|
||||||
required FrameRate? frameRate,
|
required FrameRate? frameRate,
|
||||||
required LottieDelegates? delegates,
|
required LottieDelegates? delegates,
|
||||||
bool? enableMergePaths}) {
|
bool? enableMergePaths,
|
||||||
|
FilterQuality? filterQuality}) {
|
||||||
var drawable = _drawable;
|
var drawable = _drawable;
|
||||||
enableMergePaths ??= false;
|
enableMergePaths ??= false;
|
||||||
|
|
||||||
@ -50,11 +55,8 @@ class RenderLottie extends RenderBox {
|
|||||||
needsLayout = true;
|
needsLayout = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (drawable == null ||
|
if (drawable == null || drawable.composition != composition) {
|
||||||
drawable.composition != composition ||
|
drawable = _drawable = LottieDrawable(composition);
|
||||||
drawable.enableMergePaths != enableMergePaths) {
|
|
||||||
drawable = _drawable =
|
|
||||||
LottieDrawable(composition, enableMergePaths: enableMergePaths);
|
|
||||||
needsLayout = true;
|
needsLayout = true;
|
||||||
needsPaint = true;
|
needsPaint = true;
|
||||||
}
|
}
|
||||||
@ -65,6 +67,14 @@ class RenderLottie extends RenderBox {
|
|||||||
drawable.delegates = delegates;
|
drawable.delegates = delegates;
|
||||||
needsPaint = true;
|
needsPaint = true;
|
||||||
}
|
}
|
||||||
|
if (enableMergePaths != drawable.enableMergePaths) {
|
||||||
|
drawable.enableMergePaths = enableMergePaths;
|
||||||
|
needsPaint = true;
|
||||||
|
}
|
||||||
|
if (filterQuality != drawable.filterQuality) {
|
||||||
|
drawable.filterQuality = filterQuality;
|
||||||
|
needsPaint = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsPaint) {
|
if (needsPaint) {
|
||||||
|
@ -254,6 +254,11 @@ class ValueDelegate<T> {
|
|||||||
double? relative}) =>
|
double? relative}) =>
|
||||||
_double(keyPath, LottieProperty.textSize, value, callback, relative);
|
_double(keyPath, LottieProperty.textSize, value, callback, relative);
|
||||||
|
|
||||||
|
static ValueDelegate<String> text(List<String> keyPath,
|
||||||
|
{String? value,
|
||||||
|
String Function(LottieFrameInfo<String>)? callback}) =>
|
||||||
|
ValueDelegate._(keyPath, LottieProperty.text, value, callback);
|
||||||
|
|
||||||
static ValueDelegate<ColorFilter> colorFilter(List<String> keyPath,
|
static ValueDelegate<ColorFilter> colorFilter(List<String> keyPath,
|
||||||
{ColorFilter? value,
|
{ColorFilter? value,
|
||||||
ColorFilter Function(LottieFrameInfo<ColorFilter>)? callback}) =>
|
ColorFilter Function(LottieFrameInfo<ColorFilter>)? callback}) =>
|
||||||
|
99
pubspec.lock
@ -7,28 +7,28 @@ packages:
|
|||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "26.0.0"
|
version: "43.0.0"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "4.3.1"
|
||||||
archive:
|
archive:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: archive
|
name: archive
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.3.1"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: args
|
name: args
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.1"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -49,42 +49,42 @@ packages:
|
|||||||
name: build
|
name: build
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.3.0"
|
||||||
build_config:
|
build_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: build_config
|
name: build_config
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.1.0"
|
||||||
build_daemon:
|
build_daemon:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: build_daemon
|
name: build_daemon
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
version: "3.1.0"
|
||||||
build_resolvers:
|
build_resolvers:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: build_resolvers
|
name: build_resolvers
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.4"
|
version: "2.0.9"
|
||||||
build_runner:
|
build_runner:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: build_runner
|
name: build_runner
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.2.0"
|
||||||
build_runner_core:
|
build_runner_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: build_runner_core
|
name: build_runner_core
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.1.0"
|
version: "7.2.3"
|
||||||
built_collection:
|
built_collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -98,7 +98,7 @@ packages:
|
|||||||
name: built_value
|
name: built_value
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.1.2"
|
version: "8.4.0"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -120,13 +120,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
cli_util:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: cli_util
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.3.3"
|
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -147,35 +140,35 @@ packages:
|
|||||||
name: collection
|
name: collection
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0"
|
version: "1.16.0"
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: convert
|
name: convert
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
crypto:
|
crypto:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: crypto
|
name: crypto
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
dart_style:
|
dart_style:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: dart_style
|
name: dart_style
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.2.3"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.0"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -189,7 +182,7 @@ packages:
|
|||||||
name: fixnum
|
name: fixnum
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.1"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -201,7 +194,7 @@ packages:
|
|||||||
name: flutter_lints
|
name: flutter_lints
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "2.0.1"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -213,14 +206,14 @@ packages:
|
|||||||
name: frontend_server_client
|
name: frontend_server_client
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.3"
|
||||||
glob:
|
glob:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: glob
|
name: glob
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.1.0"
|
||||||
graphs:
|
graphs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -234,14 +227,14 @@ packages:
|
|||||||
name: http_multi_server
|
name: http_multi_server
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.2.1"
|
||||||
http_parser:
|
http_parser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: http_parser
|
name: http_parser
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.1"
|
||||||
io:
|
io:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -255,21 +248,21 @@ packages:
|
|||||||
name: js
|
name: js
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.3"
|
version: "0.6.4"
|
||||||
json_annotation:
|
json_annotation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: json_annotation
|
name: json_annotation
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.1"
|
version: "4.6.0"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: lints
|
name: lints
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "2.0.0"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -290,7 +283,7 @@ packages:
|
|||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.3"
|
version: "0.1.4"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -304,63 +297,56 @@ packages:
|
|||||||
name: mime
|
name: mime
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.2"
|
||||||
package_config:
|
package_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: package_config
|
name: package_config
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.1.0"
|
||||||
path:
|
path:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0"
|
version: "1.8.1"
|
||||||
pedantic:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pedantic
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.11.1"
|
|
||||||
pool:
|
pool:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: pool
|
name: pool
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.0"
|
version: "1.5.1"
|
||||||
pub_semver:
|
pub_semver:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: pub_semver
|
name: pub_semver
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.1"
|
||||||
pubspec_parse:
|
pubspec_parse:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: pubspec_parse
|
name: pubspec_parse
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.2.0"
|
||||||
shelf:
|
shelf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shelf
|
name: shelf
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.1"
|
||||||
shelf_web_socket:
|
shelf_web_socket:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shelf_web_socket
|
name: shelf_web_socket
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.2"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -372,7 +358,7 @@ packages:
|
|||||||
name: source_span
|
name: source_span
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.2"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -414,7 +400,7 @@ packages:
|
|||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.8"
|
version: "0.4.9"
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -428,34 +414,35 @@ packages:
|
|||||||
name: typed_data
|
name: typed_data
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.1"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.2"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: watcher
|
name: watcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.1"
|
||||||
web_socket_channel:
|
web_socket_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: web_socket_channel
|
name: web_socket_channel
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.2.0"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: yaml
|
name: yaml
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.1.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.14.0 <3.0.0"
|
dart: ">=2.17.0 <3.0.0"
|
||||||
|
flutter: ">=2.10.0"
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
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: 1.2.2
|
version: 1.4.2
|
||||||
homepage: https://github.com/xvrh/lottie-flutter
|
homepage: https://github.com/xvrh/lottie-flutter
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.12.0 <3.0.0'
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
|
flutter: '>=2.10.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
archive: ^3.0.0
|
archive: ^3.0.0
|
||||||
|
@ -2,27 +2,83 @@ import 'dart:io';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:lottie/lottie.dart';
|
import 'package:lottie/lottie.dart';
|
||||||
|
import 'utils.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Dynamic test', (tester) async {
|
late LottieComposition composition;
|
||||||
var composition = await LottieComposition.fromBytes(
|
|
||||||
File('example/assets/Tests/DynamicText.json').readAsBytesSync());
|
|
||||||
|
|
||||||
|
setUpAll(() async {
|
||||||
|
composition = await LottieComposition.fromBytes(
|
||||||
|
File('example/assets/Tests/DynamicText.json').readAsBytesSync());
|
||||||
|
});
|
||||||
|
|
||||||
|
void testGolden(String description, LottieDelegates delegates) async {
|
||||||
|
var screenshotName = description
|
||||||
|
.toLowerCase()
|
||||||
|
.replaceAll(RegExp('[^a-z0-9 ]'), '')
|
||||||
|
.replaceAll(' ', '_');
|
||||||
|
|
||||||
|
var size = const Size(500, 400);
|
||||||
|
testWidgets(description, (tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
home: Lottie(
|
home: FilmStrip(
|
||||||
composition: composition,
|
composition,
|
||||||
animate: false,
|
delegates: delegates,
|
||||||
delegates: LottieDelegates(
|
size: size,
|
||||||
text: (input) => '🔥c️🔥👮🏿🔥',
|
|
||||||
textStyle: (font) => const TextStyle(
|
|
||||||
fontFamily: 'Roboto', fontFamilyFallback: ['Noto Emoji']),
|
|
||||||
values: const []),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
await tester.pump();
|
||||||
await expectLater(
|
await expectLater(find.byType(FilmStrip),
|
||||||
find.byType(Lottie), matchesGoldenFile('goldens/dynamic_text.png'));
|
matchesGoldenFile('goldens/dynamic_text/$screenshotName.png'));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
testGolden(
|
||||||
|
'Dynamic text delegate',
|
||||||
|
LottieDelegates(
|
||||||
|
text: (input) => '🔥c️🔥👮🏿🔥',
|
||||||
|
textStyle: (font) => const TextStyle(
|
||||||
|
fontFamily: 'Roboto', fontFamilyFallback: ['Noto Emoji']),
|
||||||
|
values: const []));
|
||||||
|
|
||||||
|
testGolden(
|
||||||
|
'Dynamic Text ValueDelegate',
|
||||||
|
LottieDelegates(values: [
|
||||||
|
ValueDelegate.text(['NAME'], value: 'Text with ValueDelegate')
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
testGolden(
|
||||||
|
'Dynamic Text ValueDelegate overallProgress',
|
||||||
|
LottieDelegates(values: [
|
||||||
|
ValueDelegate.text(['NAME'],
|
||||||
|
callback: (frame) => '${frame.overallProgress}')
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
testGolden(
|
||||||
|
'Dynamic Text ValueDelegate startValue',
|
||||||
|
LottieDelegates(values: [
|
||||||
|
ValueDelegate.text(['NAME'], callback: (frame) => '${frame.startValue}!!')
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
testGolden(
|
||||||
|
'Dynamic Text ValueDelegate endValue',
|
||||||
|
LottieDelegates(values: [
|
||||||
|
ValueDelegate.text(['NAME'], callback: (frame) => '${frame.endValue}!!')
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
testGolden(
|
||||||
|
'Dynamic Text Emoji',
|
||||||
|
LottieDelegates(
|
||||||
|
textStyle: (font) => const TextStyle(
|
||||||
|
fontFamily: 'Roboto', fontFamilyFallback: ['Noto Emoji']),
|
||||||
|
values: [
|
||||||
|
ValueDelegate.text(['NAME'], value: '🔥💪💯'),
|
||||||
|
]),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 101 KiB |
BIN
test/goldens/all/Tests/gradientonecolor.png
Normal file
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 5.3 KiB |
BIN
test/goldens/all/Tests/reversedstar.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
test/goldens/all/Tests/roundedcorners.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
test/goldens/all/Tests/trimpathwraparound.png
Normal file
After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 196 KiB After Width: | Height: | Size: 194 KiB |
Before Width: | Height: | Size: 196 KiB After Width: | Height: | Size: 194 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 139 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 63 KiB |
BIN
test/goldens/dynamic_text/dynamic_text_delegate.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
test/goldens/dynamic_text/dynamic_text_emoji.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
test/goldens/dynamic_text/dynamic_text_valuedelegate.png
Normal file
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 25 KiB |