mirror of
https://github.com/xvrh/lottie-flutter.git
synced 2025-08-06 16:39:36 +08:00
Compare commits
27 Commits
v3.0.0-alp
...
master
Author | SHA1 | Date | |
---|---|---|---|
78bbbc895f | |||
5e71dabfa3 | |||
f892a14a7e | |||
84cfa16673 | |||
61756b6613 | |||
7e4d1d3813 | |||
56a69f56d0 | |||
d0deffa2ee | |||
a2e40ecd08 | |||
5a725a064e | |||
8302c4b7e6 | |||
029cee4f0a | |||
eeda2f4de4 | |||
ba039e9423 | |||
3c58936d36 | |||
d0fed17a70 | |||
1c113d961a | |||
17449658bb | |||
e258c610f5 | |||
945285175a | |||
cfb29485b0 | |||
31ab666099 | |||
8881e357c6 | |||
1c665c7756 | |||
cad1806f2e | |||
08e9678dc3 | |||
9f4a8d74d5 |
7
.github/workflows/analyze-and-test.yaml
vendored
7
.github/workflows/analyze-and-test.yaml
vendored
@ -8,15 +8,12 @@ on:
|
||||
jobs:
|
||||
analyze_and_test:
|
||||
name: Flutter analyze
|
||||
strategy:
|
||||
matrix:
|
||||
flutter: ['stable']
|
||||
runs-on: macos-13
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: ${{ matrix.flutter }}
|
||||
channel: 'stable'
|
||||
- run: flutter doctor
|
||||
- run: flutter --version
|
||||
- run: flutter pub get
|
||||
|
22
.github/workflows/coverage.yaml
vendored
Normal file
22
.github/workflows/coverage.yaml
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
name: Coverage
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
coverage:
|
||||
name: Coverage
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: 'stable'
|
||||
- run: flutter test --coverage
|
||||
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@v5.1.1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
88
CHANGELOG.md
88
CHANGELOG.md
@ -1,37 +1,46 @@
|
||||
## 3.0.0-alpha.3
|
||||
- Reduce the max memory used when using `enableRenderCache` (now limited to 50MB)
|
||||
- Allow to configure the memory with a global settings:
|
||||
```dart
|
||||
Lottie.renderCacheMaxMemory = 75000000;
|
||||
```
|
||||
## 3.3.1
|
||||
- Update `package:archive` to `>=4.0.0` constraint
|
||||
|
||||
## 3.0.0-alpha.2
|
||||
- Implement auto-orient
|
||||
- Add support for layer blend mode
|
||||
- Require Flutter 3.16
|
||||
## 3.3.0
|
||||
- Requires Flutter 3.27 and fix lints.
|
||||
- Add conditional imports to prevent importing `dart:io` on Web targets
|
||||
|
||||
## 3.0.0-alpha.1
|
||||
- Add `enableRenderCache` parameter.
|
||||
## 3.2.0
|
||||
- Apply Blend mode at layer level
|
||||
|
||||
## 3.1.3
|
||||
- Update `package:archive` dependency constraints
|
||||
|
||||
## 3.1.2
|
||||
- Fixes for some animations generated by lottiefiles.com
|
||||
|
||||
## 3.1.1
|
||||
- Fix rounding-off error on progress calculation
|
||||
- Allow missing end values for integer animations
|
||||
|
||||
## 3.1.0
|
||||
- Use `package:http` for `Lottie.network`. This allows to drop dependency on `dart:html` and be compatible with `wasm`.
|
||||
- Fix new lints
|
||||
|
||||
## 3.0.0
|
||||
- Add `renderCache` parameter.
|
||||
|
||||
```dart
|
||||
Lottie.asset('assets/complex_animation.json',
|
||||
enableRenderCache: true,
|
||||
renderCache: RenderCache.raster,
|
||||
)
|
||||
```
|
||||
|
||||
It allows to opt into a mode where the frames of the animation are rendered lazily in an offscreen cache.
|
||||
Subsequent runs of the animation will be very cheap to render.
|
||||
Opt-in to a special render mode where the frames of the animation are lazily rendered and kept in a cache.
|
||||
Subsequent runs of the animation are cheaper to render.
|
||||
|
||||
This is useful is the animation is complex and can consume a lot of energy from the battery.
|
||||
It's a trade-off to lower the CPU usage at the cost of an increased memory usage.
|
||||
There are 2 kinds of caches:
|
||||
|
||||
The render cache is managed internally and will release the memory once the animation is disposed.
|
||||
The cache is shared between all animations. If 2 `Lottie` widget are rendered at the same size, they will render only
|
||||
once.
|
||||
|
||||
Any change in the configuration of the animation (delegates, frame rate etc...) will clear the cache.
|
||||
Any change in the size will invalidate the cache. The cache use the final size visible on the screen (with all
|
||||
transforms applied).
|
||||
**RenderCache.raster**: keep the frame rasterized in the cache (as [dart:ui.Image]).
|
||||
Subsequent runs of the animation are very cheap for both the CPU and GPU but it takes
|
||||
a lot of memory.
|
||||
**RenderCache.drawingCommands**: keep the frame as a list of graphical operations ([dart:ui.Picture]).
|
||||
Subsequent runs of the animation are cheaper for the CPU but not for the GPU.
|
||||
|
||||
- Allow to load Telegram Stickers (.tgs)
|
||||
|
||||
@ -43,7 +52,7 @@ Lottie.asset(
|
||||
```
|
||||
|
||||
- Expose a hook to customize how to decode zip archives. This is useful for dotlottie archives (.lottie) when we want
|
||||
to specify a specific .json file inside the archive
|
||||
to specify a specific .json file inside the archive
|
||||
|
||||
```dart
|
||||
Lottie.asset(
|
||||
@ -58,21 +67,46 @@ Future<LottieComposition?> customDecoder(List<int> bytes) {
|
||||
}
|
||||
```
|
||||
|
||||
- Add `backgroundLoading` parameter to `Lottie.asset|network|file|memory`.
|
||||
If `backgroundLoading` is true, the animation will be loaded in a background isolate.
|
||||
This is useful for large animations that can take a long time to parse and block the UI work.
|
||||
|
||||
- Remove the name property from `LottieComposition`
|
||||
|
||||
- `imageProviderFactory` is not used in .zip file by default anymore.
|
||||
To restore the old behaviour, use:
|
||||
To restore the old behaviour, use:
|
||||
```dart
|
||||
Future<LottieComposition?> decoder(List<int> bytes) {
|
||||
return LottieComposition.decodeZip(bytes, imageProviderFactory: imageProviderFactory);
|
||||
}
|
||||
|
||||
Lottie.asset('anim.json', imageProviderFactory: imageProviderFactory, decoder: decoder)
|
||||
Lottie.asset('anim.json', decoder: decoder)
|
||||
```
|
||||
|
||||
- Disable gradient cache optimization when `ValueDelegate.gradientColor` is used
|
||||
- Use `DefaultAssetBundle.of` in `AssetLottie` before fallback to `rootBundle`
|
||||
- Add `BuildContext` optional parameter in `LottieProvider.load`
|
||||
- Fixed varying opacity stops across keyframes in the same gradient
|
||||
- Fixed rounded corners for non-closed curves
|
||||
- Implement auto-orient
|
||||
- Add support for layer blend mode
|
||||
- Require Flutter 3.16
|
||||
|
||||
## 3.0.0-alpha.4
|
||||
|
||||
*See the latest 3.0.0 release*
|
||||
|
||||
## 3.0.0-alpha.3
|
||||
|
||||
*See the latest 3.0.0 release*
|
||||
|
||||
## 3.0.0-alpha.2
|
||||
|
||||
*See the latest 3.0.0 release*
|
||||
|
||||
## 3.0.0-alpha.1
|
||||
|
||||
*See the latest 3.0.0 release*
|
||||
|
||||
## 2.7.0
|
||||
- Support loading Fonts from a zip file
|
||||
|
2
FUNDING.yml
Normal file
2
FUNDING.yml
Normal file
@ -0,0 +1,2 @@
|
||||
github: xvrh
|
||||
custom: https://buymeacoffee.com/xvrh
|
@ -10,6 +10,8 @@ This repository is an unofficial conversion of the [Lottie-android](https://gith
|
||||
|
||||
It works on Android, iOS, macOS, linux, windows and web.
|
||||
|
||||
<a href="https://www.buymeacoffee.com/xvrh" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="60" width="217"></a>
|
||||
|
||||
## Usage
|
||||
|
||||
### Simple animation
|
||||
@ -306,10 +308,10 @@ Future<LottieComposition?> customDecoder(List<int> bytes) {
|
||||
|
||||
## Performance or excessive CPU/GPU usage
|
||||
|
||||
Version `v3.0` introduced the `enableRenderCache` parameter to help reduce an excessive energy consumption.
|
||||
Version `v3.0` introduced the `renderCache` parameter to help reduce an excessive energy consumption.
|
||||
|
||||
In this mode, the frames of the animation are rendered lazily in an offscreen cache. Subsequent runs of the animation
|
||||
are very cheap to render. It helps reduce the power usage of the application at the cost of an increased memory usage.
|
||||
are cheaper to render. It helps reduce the power usage of the application at the cost of an increased memory usage.
|
||||
|
||||
## Limitations
|
||||
This port supports the same [feature set as Lottie Android](https://airbnb.io/lottie/#/supported-features).
|
||||
|
@ -10,6 +10,8 @@ This repository is an unofficial conversion of the [Lottie-android](https://gith
|
||||
|
||||
It works on Android, iOS, macOS, linux, windows and web.
|
||||
|
||||
<a href="https://www.buymeacoffee.com/xvrh" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="60" width="217"></a>
|
||||
|
||||
## Usage
|
||||
|
||||
### Simple animation
|
||||
@ -107,10 +109,10 @@ import 'example/lib/examples/dotlottie.dart#example';
|
||||
|
||||
## Performance or excessive CPU/GPU usage
|
||||
|
||||
Version `v3.0` introduced the `enableRenderCache` parameter to help reduce an excessive energy consumption.
|
||||
Version `v3.0` introduced the `renderCache` parameter to help reduce an excessive energy consumption.
|
||||
|
||||
In this mode, the frames of the animation are rendered lazily in an offscreen cache. Subsequent runs of the animation
|
||||
are very cheap to render. It helps reduce the power usage of the application at the cost of an increased memory usage.
|
||||
are cheaper to render. It helps reduce the power usage of the application at the cost of an increased memory usage.
|
||||
|
||||
## Limitations
|
||||
This port supports the same [feature set as Lottie Android](https://airbnb.io/lottie/#/supported-features).
|
||||
|
@ -18,7 +18,6 @@ linter:
|
||||
avoid_js_rounded_ints: true
|
||||
avoid_positional_boolean_parameters: true
|
||||
avoid_redundant_argument_values: true
|
||||
avoid_returning_null_for_future: true
|
||||
avoid_setters_without_getters: true
|
||||
avoid_type_to_string: true
|
||||
avoid_unused_constructor_parameters: true
|
||||
|
1
example/.gitignore
vendored
1
example/.gitignore
vendored
@ -31,7 +31,6 @@
|
||||
/build/
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Exceptions to above rules.
|
||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||
|
1
example/assets/Animation-1700642783167.json
Normal file
1
example/assets/Animation-1700642783167.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.12.1","fr":25,"ip":0,"op":50,"w":1080,"h":2330,"nm":"Testcomp","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Top Shape With Multiply","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[540,1165,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":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[608,608],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.996078012504,0.996078012504,0.996078012504,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.108819677316,0.687484142827,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[4,-261],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":825,"st":0,"ct":1,"bm":1},{"ddd":0,"ind":2,"ty":4,"nm":"Shape With Outline","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-45,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.25,"y":1},"o":{"x":0.75,"y":0},"t":0,"s":[524,1208,0],"to":[0,39.333,0],"ti":[0,0,0]},{"i":{"x":0.25,"y":1},"o":{"x":0.75,"y":0},"t":25,"s":[524,1444,0],"to":[0,0,0],"ti":[0,39.333,0]},{"t":49,"s":[524,1208,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-74,327,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":24,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109803929048,0.686274509804,0.956862804936,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-74,327],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":825,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":1,"nm":"BKG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[540,1165,0],"ix":2,"l":2},"a":{"a":0,"k":[540,1165,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"sw":1080,"sh":2330,"sc":"#ffffff","ip":0,"op":825,"st":0,"bm":0}],"markers":[],"props":{}}
|
898
example/assets/Tests/BounceEasings.json
Normal file
898
example/assets/Tests/BounceEasings.json
Normal file
@ -0,0 +1,898 @@
|
||||
{
|
||||
"v": "5.7.5",
|
||||
"fr": 100,
|
||||
"ip": 0,
|
||||
"op": 400,
|
||||
"w": 800,
|
||||
"h": 1000,
|
||||
"nm": "Comp 1",
|
||||
"ddd": 0,
|
||||
"assets": [],
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 0,
|
||||
"ty": 4,
|
||||
"nm": "Bounce out curve",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"hd": false,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"hd": false,
|
||||
"it": [
|
||||
{
|
||||
"ty": "rc",
|
||||
"hd": false,
|
||||
"d": 1,
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"ty": "fl",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0.21176470588235294,
|
||||
0.9176470588235294,
|
||||
1
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"nm": "Fill 1",
|
||||
"mn": "ADBE Vector Graphic - Fill",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"e": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"m": 1,
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"hd": false,
|
||||
"p": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"t": 0,
|
||||
"s": [
|
||||
510,
|
||||
100
|
||||
],
|
||||
"i": {
|
||||
"x": [
|
||||
0.2
|
||||
],
|
||||
"y": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.5
|
||||
],
|
||||
"y": [
|
||||
-0.5
|
||||
]
|
||||
},
|
||||
"ti": [
|
||||
-268.19047619047615,
|
||||
-294.42857142857247
|
||||
],
|
||||
"to": [
|
||||
-268.19047619047615,
|
||||
238.90476190476068
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 400,
|
||||
"s": [
|
||||
510,
|
||||
900
|
||||
],
|
||||
"i": {
|
||||
"x": [
|
||||
1
|
||||
],
|
||||
"y": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0
|
||||
],
|
||||
"y": [
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 401,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 1,
|
||||
"ty": 4,
|
||||
"nm": "Bounce in curve",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"hd": false,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"hd": false,
|
||||
"it": [
|
||||
{
|
||||
"ty": "rc",
|
||||
"hd": false,
|
||||
"d": 1,
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"ty": "fl",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
1,
|
||||
0.3411764705882353,
|
||||
0.21176470588235294
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"nm": "Fill 1",
|
||||
"mn": "ADBE Vector Graphic - Fill",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"e": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"m": 1,
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"hd": false,
|
||||
"p": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"t": 0,
|
||||
"s": [
|
||||
360,
|
||||
100
|
||||
],
|
||||
"i": {
|
||||
"x": [
|
||||
0.5
|
||||
],
|
||||
"y": [
|
||||
1.5
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.8
|
||||
],
|
||||
"y": [
|
||||
0
|
||||
]
|
||||
},
|
||||
"ti": [
|
||||
-268.19047619047615,
|
||||
-294.42857142857247
|
||||
],
|
||||
"to": [
|
||||
-268.19047619047615,
|
||||
238.90476190476068
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 400,
|
||||
"s": [
|
||||
360,
|
||||
900
|
||||
],
|
||||
"i": {
|
||||
"x": [
|
||||
1
|
||||
],
|
||||
"y": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0
|
||||
],
|
||||
"y": [
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 401,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 2,
|
||||
"ty": 4,
|
||||
"nm": "Bounce in",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"hd": false,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"hd": false,
|
||||
"it": [
|
||||
{
|
||||
"ty": "rc",
|
||||
"hd": false,
|
||||
"d": 1,
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"ty": "fl",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
1,
|
||||
0.7254901960784313,
|
||||
0.5764705882352941
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"nm": "Fill 1",
|
||||
"mn": "ADBE Vector Graphic - Fill",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"e": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"m": 1,
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"hd": false,
|
||||
"p": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"t": 0,
|
||||
"s": [
|
||||
650,
|
||||
100
|
||||
],
|
||||
"i": {
|
||||
"x": [
|
||||
0.5
|
||||
],
|
||||
"y": [
|
||||
1.5
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.8
|
||||
],
|
||||
"y": [
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 400,
|
||||
"s": [
|
||||
650,
|
||||
900
|
||||
],
|
||||
"i": {
|
||||
"x": [
|
||||
1
|
||||
],
|
||||
"y": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0
|
||||
],
|
||||
"y": [
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 401,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 3,
|
||||
"ty": 4,
|
||||
"nm": "Bounce out",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"hd": false,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"hd": false,
|
||||
"it": [
|
||||
{
|
||||
"ty": "rc",
|
||||
"hd": false,
|
||||
"d": 1,
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"ty": "fl",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
1,
|
||||
0.8392156862745098,
|
||||
0.25098039215686274
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"nm": "Fill 1",
|
||||
"mn": "ADBE Vector Graphic - Fill",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"e": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"m": 1,
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"hd": false,
|
||||
"p": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"t": 0,
|
||||
"s": [
|
||||
150,
|
||||
100
|
||||
],
|
||||
"i": {
|
||||
"x": [
|
||||
0.2
|
||||
],
|
||||
"y": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.5
|
||||
],
|
||||
"y": [
|
||||
-0.5
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"t": 400,
|
||||
"s": [
|
||||
150,
|
||||
900
|
||||
],
|
||||
"i": {
|
||||
"x": [
|
||||
1
|
||||
],
|
||||
"y": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0
|
||||
],
|
||||
"y": [
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 401,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
}
|
||||
],
|
||||
"markers": []
|
||||
}
|
522
example/assets/Tests/GradientColorKeyframeAnimation.json
Normal file
522
example/assets/Tests/GradientColorKeyframeAnimation.json
Normal file
@ -0,0 +1,522 @@
|
||||
{
|
||||
"v": "4.8.0",
|
||||
"meta": {
|
||||
"g": "LottieFiles AE 3.5.2",
|
||||
"a": "",
|
||||
"k": "",
|
||||
"d": "",
|
||||
"tc": "#000000"
|
||||
},
|
||||
"fr": 24,
|
||||
"ip": 0,
|
||||
"op": 6912,
|
||||
"w": 312,
|
||||
"h": 312,
|
||||
"nm": "Master_1-4a- GREEN",
|
||||
"ddd": 0,
|
||||
"assets": [],
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 30,
|
||||
"ty": 4,
|
||||
"nm": "Background_Layers",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
158,
|
||||
154,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
50,
|
||||
50,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"ind": 0,
|
||||
"ty": "sh",
|
||||
"ix": 1,
|
||||
"ks": {
|
||||
"a": 0,
|
||||
"k": {
|
||||
"i": [
|
||||
[
|
||||
149.841,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
-149.841
|
||||
],
|
||||
[
|
||||
-149.841,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
149.841
|
||||
]
|
||||
],
|
||||
"o": [
|
||||
[
|
||||
-149.841,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
149.841
|
||||
],
|
||||
[
|
||||
149.841,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
-149.841
|
||||
]
|
||||
],
|
||||
"v": [
|
||||
[
|
||||
0,
|
||||
-271.311
|
||||
],
|
||||
[
|
||||
-271.311,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
271.311
|
||||
],
|
||||
[
|
||||
271.311,
|
||||
0
|
||||
]
|
||||
],
|
||||
"c": true
|
||||
},
|
||||
"ix": 2
|
||||
},
|
||||
"nm": "Path 1",
|
||||
"mn": "ADBE Vector Shape - Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 4
|
||||
},
|
||||
"w": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"lc": 1,
|
||||
"lj": 1,
|
||||
"ml": 4,
|
||||
"bm": 0,
|
||||
"nm": "Stroke 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "gf",
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 60,
|
||||
"ix": 10
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"g": {
|
||||
"p": 3,
|
||||
"k": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": {
|
||||
"x": 0.833,
|
||||
"y": 0.833
|
||||
},
|
||||
"o": {
|
||||
"x": 0.167,
|
||||
"y": 0.167
|
||||
},
|
||||
"t": 898.499,
|
||||
"s": [
|
||||
0.799,
|
||||
0.988,
|
||||
0.875,
|
||||
0.435,
|
||||
0.9,
|
||||
0.994,
|
||||
0.937,
|
||||
0.718,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.072,
|
||||
1,
|
||||
0.536,
|
||||
0.5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": 0.833,
|
||||
"y": 0.833
|
||||
},
|
||||
"o": {
|
||||
"x": 0.167,
|
||||
"y": 0.167
|
||||
},
|
||||
"t": 1112.312,
|
||||
"s": [
|
||||
0.799,
|
||||
0.988,
|
||||
0.875,
|
||||
0.435,
|
||||
0.9,
|
||||
0.994,
|
||||
0.937,
|
||||
0.718,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.072,
|
||||
1,
|
||||
0.536,
|
||||
0.5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": 0.833,
|
||||
"y": 0.833
|
||||
},
|
||||
"o": {
|
||||
"x": 0.167,
|
||||
"y": 0.167
|
||||
},
|
||||
"t": 1330.13,
|
||||
"s": [
|
||||
0.799,
|
||||
0.828,
|
||||
0.855,
|
||||
0.554,
|
||||
0.9,
|
||||
0.914,
|
||||
0.928,
|
||||
0.777,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.072,
|
||||
1,
|
||||
0.536,
|
||||
0.5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": 0.833,
|
||||
"y": 0.833
|
||||
},
|
||||
"o": {
|
||||
"x": 0.167,
|
||||
"y": 0.167
|
||||
},
|
||||
"t": 1420.621,
|
||||
"s": [
|
||||
0.799,
|
||||
0.761,
|
||||
0.847,
|
||||
0.604,
|
||||
0.9,
|
||||
0.88,
|
||||
0.924,
|
||||
0.802,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.072,
|
||||
1,
|
||||
0.536,
|
||||
0.5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": 0.833,
|
||||
"y": 0.833
|
||||
},
|
||||
"o": {
|
||||
"x": 0.167,
|
||||
"y": 0.167
|
||||
},
|
||||
"t": 4054.455,
|
||||
"s": [
|
||||
0.799,
|
||||
0.761,
|
||||
0.847,
|
||||
0.604,
|
||||
0.9,
|
||||
0.88,
|
||||
0.924,
|
||||
0.802,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.072,
|
||||
1,
|
||||
0.536,
|
||||
0.5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": 0.833,
|
||||
"y": 0.833
|
||||
},
|
||||
"o": {
|
||||
"x": 0.167,
|
||||
"y": 0.167
|
||||
},
|
||||
"t": 4311.512,
|
||||
"s": [
|
||||
0.799,
|
||||
0.675,
|
||||
0.859,
|
||||
0.894,
|
||||
0.9,
|
||||
0.837,
|
||||
0.929,
|
||||
0.947,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.072,
|
||||
1,
|
||||
0.536,
|
||||
0.5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": 0.833,
|
||||
"y": 0.833
|
||||
},
|
||||
"o": {
|
||||
"x": 0.167,
|
||||
"y": 0.167
|
||||
},
|
||||
"t": 6439.239,
|
||||
"s": [
|
||||
0.799,
|
||||
0.675,
|
||||
0.859,
|
||||
0.894,
|
||||
0.9,
|
||||
0.837,
|
||||
0.929,
|
||||
0.947,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.072,
|
||||
1,
|
||||
0.536,
|
||||
0.5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 6672.2724609375,
|
||||
"s": [
|
||||
0.799,
|
||||
0.71,
|
||||
0.098,
|
||||
0.392,
|
||||
0.9,
|
||||
0.855,
|
||||
0.549,
|
||||
0.696,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.072,
|
||||
1,
|
||||
0.536,
|
||||
0.5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"ix": 9
|
||||
}
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0.798,
|
||||
1.032
|
||||
],
|
||||
"ix": 5
|
||||
},
|
||||
"e": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
244.484,
|
||||
0
|
||||
],
|
||||
"ix": 6
|
||||
},
|
||||
"t": 2,
|
||||
"h": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 7
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 8
|
||||
},
|
||||
"nm": "Gradient Fill 1",
|
||||
"mn": "ADBE Vector Graphic - G-Fill",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
-4.865,
|
||||
2.221
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
108.71,
|
||||
108.71
|
||||
],
|
||||
"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": "Transformieren"
|
||||
}
|
||||
],
|
||||
"nm": "Ellipse 1",
|
||||
"np": 3,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": -8.80880880880881,
|
||||
"op": 7462.66266266266,
|
||||
"st": -8.80880880880881,
|
||||
"bm": 0
|
||||
}
|
||||
],
|
||||
"markers": []
|
||||
}
|
@ -0,0 +1,678 @@
|
||||
{
|
||||
"v": "5.7.5",
|
||||
"fr": 100,
|
||||
"ip": 0,
|
||||
"op": 300,
|
||||
"w": 100,
|
||||
"h": 100,
|
||||
"nm": "Comp 1",
|
||||
"ddd": 0,
|
||||
"assets": [],
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 0,
|
||||
"ty": 4,
|
||||
"nm": "Linear gradient",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"hd": false,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"hd": false,
|
||||
"it": [
|
||||
{
|
||||
"ty": "sh",
|
||||
"hd": false,
|
||||
"d": 1,
|
||||
"ks": {
|
||||
"a": 0,
|
||||
"k": {
|
||||
"c": false,
|
||||
"v": [
|
||||
[
|
||||
-17.99999846997801,
|
||||
-9
|
||||
],
|
||||
[
|
||||
17.99999846997801,
|
||||
-9
|
||||
],
|
||||
[
|
||||
17.99999846997801,
|
||||
9
|
||||
],
|
||||
[
|
||||
-17.99999846997801,
|
||||
9
|
||||
],
|
||||
[
|
||||
-17.99999846997801,
|
||||
-9
|
||||
]
|
||||
],
|
||||
"i": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"o": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ty": "gf",
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"g": {
|
||||
"p": 5,
|
||||
"k": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0.6126387150748301,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0.8114341216791559,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0.9555392466605757,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0.9977200010227434,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0.6126387150748301,
|
||||
1,
|
||||
0.8114341216791559,
|
||||
0,
|
||||
0.9555392466605757,
|
||||
0.3146550641021125,
|
||||
0.9977200010227434,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
-17.99999809265137,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"e": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
9.028081893920898,
|
||||
4.32133674621582E-7
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"t": 1,
|
||||
"nm": "Gradient Fill 1",
|
||||
"mn": "ADBE Vector Graphic - G-Fill",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"e": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"m": 1,
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"hd": false,
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
49.99999618530273,
|
||||
72.5
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
250,
|
||||
250
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 301,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 1,
|
||||
"ty": 4,
|
||||
"nm": "Radial gradient",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"hd": false,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"hd": false,
|
||||
"it": [
|
||||
{
|
||||
"ty": "rc",
|
||||
"hd": false,
|
||||
"d": 1,
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
36,
|
||||
16
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"ty": "gf",
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"g": {
|
||||
"p": 5,
|
||||
"k": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0.5371484055543164,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0.8215441678174731,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0.9571973765957152,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0.5371484055543164,
|
||||
1,
|
||||
0.8215441678174731,
|
||||
0,
|
||||
0.9571973765957152,
|
||||
0.3292524136178862,
|
||||
1,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
-18,
|
||||
-7.999999523162842
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"e": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
9.53293228149414,
|
||||
-7.999999523162842
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"t": 2,
|
||||
"nm": "Gradient Fill 1",
|
||||
"mn": "ADBE Vector Graphic - G-Fill",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"e": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"m": 1,
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"hd": false,
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
50,
|
||||
24.99999618530273
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
250,
|
||||
250
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 301,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 2,
|
||||
"ty": 4,
|
||||
"nm": "Background",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"hd": false,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"hd": false,
|
||||
"it": [
|
||||
{
|
||||
"ty": "rc",
|
||||
"hd": false,
|
||||
"d": 1,
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
39.999999658311,
|
||||
40.00000046690118
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"ty": "fl",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
1,
|
||||
0.25098039215686274,
|
||||
0.25098039215686274
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"nm": "Fill 1",
|
||||
"mn": "ADBE Vector Graphic - Fill",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"e": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"m": 1,
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"hd": false,
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
50,
|
||||
50
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
250,
|
||||
250
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 2
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 301,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
}
|
||||
],
|
||||
"markers": []
|
||||
}
|
222
example/assets/Tests/LargeSquare.json
Normal file
222
example/assets/Tests/LargeSquare.json
Normal file
@ -0,0 +1,222 @@
|
||||
{
|
||||
"v": "5.9.1",
|
||||
"fr": 25,
|
||||
"ip": 0,
|
||||
"op": 75,
|
||||
"w": 1200,
|
||||
"h": 1200,
|
||||
"nm": "square",
|
||||
"ddd": 0,
|
||||
"assets": [],
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 15,
|
||||
"ty": 4,
|
||||
"nm": "Fond Silhouettes",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
600,
|
||||
600,
|
||||
0
|
||||
],
|
||||
"ix": 2,
|
||||
"l": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
600,
|
||||
600,
|
||||
0
|
||||
],
|
||||
"ix": 1,
|
||||
"l": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 6,
|
||||
"l": 2
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"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": [
|
||||
[
|
||||
-600,
|
||||
600
|
||||
],
|
||||
[
|
||||
600,
|
||||
600
|
||||
],
|
||||
[
|
||||
600,
|
||||
-600
|
||||
],
|
||||
[
|
||||
-600,
|
||||
-600
|
||||
]
|
||||
],
|
||||
"c": true
|
||||
},
|
||||
"ix": 2
|
||||
},
|
||||
"nm": "Tracé 1",
|
||||
"mn": "ADBE Vector Shape - Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "fl",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0.561497886508,
|
||||
0.699996708889,
|
||||
0.56712066052,
|
||||
1
|
||||
],
|
||||
"ix": 4
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 5
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"nm": "Fond 1",
|
||||
"mn": "ADBE Vector Graphic - Fill",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
600,
|
||||
600
|
||||
],
|
||||
"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": "Transformer "
|
||||
}
|
||||
],
|
||||
"nm": "Groupe 1",
|
||||
"np": 2,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 76,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
}
|
||||
],
|
||||
"markers": []
|
||||
}
|
14068
example/assets/Tests/MissingEndValue.json
Normal file
14068
example/assets/Tests/MissingEndValue.json
Normal file
File diff suppressed because it is too large
Load Diff
1
example/assets/Tests/NullEndShape.json
Normal file
1
example/assets/Tests/NullEndShape.json
Normal file
File diff suppressed because one or more lines are too long
1
example/assets/Tests/kona_splash_animation.json
Normal file
1
example/assets/Tests/kona_splash_animation.json
Normal file
File diff suppressed because one or more lines are too long
@ -21,6 +21,6 @@
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>11.0</string>
|
||||
<string>12.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
platform :ios, '11.0'
|
||||
platform :ios, '12.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
@ -15,9 +15,9 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
||||
|
||||
PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d
|
||||
PODFILE CHECKSUM: 4e8f8b2be68aeea4c0d5beb6ff1e79fface1d048
|
||||
|
||||
COCOAPODS: 1.14.2
|
||||
COCOAPODS: 1.15.2
|
||||
|
@ -163,7 +163,7 @@
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1430;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
@ -351,7 +351,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@ -366,8 +366,10 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = TC6K7794M3;
|
||||
DEVELOPMENT_TEAM = PS45A9TPZ7;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@ -382,8 +384,9 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.github.xvrh.lottie.example;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
@ -437,7 +440,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -486,7 +489,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@ -502,8 +505,10 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = TC6K7794M3;
|
||||
DEVELOPMENT_TEAM = PS45A9TPZ7;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@ -518,8 +523,9 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.github.xvrh.lottie.example;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@ -533,8 +539,10 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = TC6K7794M3;
|
||||
DEVELOPMENT_TEAM = PS45A9TPZ7;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@ -549,8 +557,9 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.github.xvrh.lottie.example;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
LastUpgradeVersion = "1510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart' hide Image;
|
||||
import 'package:flutter/material.dart' as material;
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
/// This example shows how to cache the animation as a List<Image>.
|
||||
/// This example shows how to cache the animation as a `List<Image>`.
|
||||
/// After the initial cache of each frame, drawing the animation is almost free
|
||||
/// in term of CPU usage.
|
||||
/// The animation will run at a specific framerate (not FrameRate.max) and specific size
|
||||
|
@ -1,10 +1,8 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
// ignore: implementation_imports
|
||||
import 'package:lottie/src/render_cache.dart';
|
||||
|
||||
void main() {
|
||||
globalRenderCache.enableDebugBackground = true;
|
||||
runApp(const App());
|
||||
}
|
||||
|
||||
@ -45,133 +43,77 @@ class App extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _Example extends StatefulWidget {
|
||||
static String _text(a) => '';
|
||||
|
||||
@override
|
||||
State<_Example> createState() => _ExampleState();
|
||||
}
|
||||
|
||||
class _ExampleState extends State<_Example> {
|
||||
int _animationCount = 1;
|
||||
|
||||
class _Example extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
++_animationCount;
|
||||
});
|
||||
_Row(
|
||||
builder: (cache) {
|
||||
return Lottie.asset('assets/Mobilo/Z.json',
|
||||
renderCache: cache, height: 100);
|
||||
},
|
||||
child: Text('Add animation $_animationCount'),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Stack(
|
||||
children: [
|
||||
for (var i = 0; i < _animationCount; i++)
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.red, width: 2),
|
||||
),
|
||||
child: Lottie.asset(
|
||||
'assets/Mobilo/B.json',
|
||||
height: 200,
|
||||
frameRate: const FrameRate(60),
|
||||
enableRenderCache: true,
|
||||
fit: BoxFit.cover,
|
||||
delegates: LottieDelegates(
|
||||
text: _Example._text,
|
||||
values: [
|
||||
ValueDelegate.color(['*'], value: Color(i)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Lottie.asset(
|
||||
'assets/Mobilo/B.json',
|
||||
height: 200,
|
||||
frameRate: const FrameRate(10),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Lottie.asset(
|
||||
'assets/Mobilo/A.json',
|
||||
height: 200,
|
||||
frameRate: const FrameRate(10),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.red, width: 2),
|
||||
for (var fit in [BoxFit.cover, BoxFit.fill, BoxFit.contain])
|
||||
_Row(
|
||||
builder: (cache) {
|
||||
return Lottie.asset(
|
||||
'assets/lottiefiles/bb8.json',
|
||||
renderCache: cache,
|
||||
fit: fit,
|
||||
height: 60,
|
||||
);
|
||||
},
|
||||
),
|
||||
child: Lottie.asset('assets/Mobilo/A.json',
|
||||
height: 200,
|
||||
frameRate: const FrameRate(10),
|
||||
fit: BoxFit.fill,
|
||||
enableRenderCache: true),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.red, width: 2),
|
||||
),
|
||||
child: Transform.scale(
|
||||
scale: 2,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.green, width: 2),
|
||||
),
|
||||
child: Lottie.asset(
|
||||
'assets/Mobilo/A.json',
|
||||
height: 200,
|
||||
enableRenderCache: true,
|
||||
frameRate: const FrameRate(10),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.red, width: 2),
|
||||
),
|
||||
child: Transform.scale(
|
||||
scale: 0.5,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.green, width: 2),
|
||||
),
|
||||
child: Lottie.asset(
|
||||
'assets/Mobilo/A.json',
|
||||
height: 200,
|
||||
frameRate: const FrameRate(10),
|
||||
enableRenderCache: true,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
_Row(
|
||||
builder: (cache) {
|
||||
return Lottie.asset(
|
||||
'assets/lottiefiles/a_mountain.json',
|
||||
renderCache: cache,
|
||||
height: 40,
|
||||
);
|
||||
},
|
||||
),
|
||||
for (var align in [
|
||||
Alignment.bottomCenter,
|
||||
Alignment.center,
|
||||
Alignment.topRight
|
||||
])
|
||||
_Row(
|
||||
builder: (cache) {
|
||||
return Lottie.asset('assets/lottiefiles/bomb.json',
|
||||
renderCache: cache, height: 40, alignment: align);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _Row extends StatelessWidget {
|
||||
final Widget Function(RenderCache? cache) builder;
|
||||
|
||||
const _Row({required this.builder});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
decoration: BoxDecoration(border: Border.all(color: Colors.green)),
|
||||
child: Row(
|
||||
children: [
|
||||
for (var cache in [
|
||||
null,
|
||||
RenderCache.raster,
|
||||
RenderCache.drawingCommands
|
||||
])
|
||||
Expanded(child: builder(cache))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RenderCacheDebugPanel extends StatefulWidget {
|
||||
const RenderCacheDebugPanel({super.key});
|
||||
|
||||
@ -180,40 +122,34 @@ class RenderCacheDebugPanel extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _RenderCacheDebugPanelState extends State<RenderCacheDebugPanel> {
|
||||
late Timer _refreshTimer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_refreshTimer = Timer.periodic(const Duration(milliseconds: 500), (timer) {
|
||||
setState(() {
|
||||
// refresh
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StreamBuilder<void>(
|
||||
stream: globalRenderCache.onUpdate,
|
||||
builder: (context, snapshot) {
|
||||
return ListView(
|
||||
children: [
|
||||
Text('Images: ${globalRenderCache.imageCount}'),
|
||||
Text(
|
||||
'Memory: ${(globalRenderCache.totalMemory / 1000000).toStringAsFixed(1)}MB'),
|
||||
const Divider(),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
globalRenderCache.clear();
|
||||
},
|
||||
child: const Text('Clear'),
|
||||
),
|
||||
const Divider(),
|
||||
SwitchListTile(
|
||||
title: const Text('Enable debug background'),
|
||||
value: globalRenderCache.enableDebugBackground,
|
||||
onChanged: (v) {
|
||||
setState(() {
|
||||
globalRenderCache.enableDebugBackground = v;
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
});
|
||||
return ListView(
|
||||
children: [
|
||||
Text('Images: ${RenderCache.raster.store.imageCount}'),
|
||||
Text(
|
||||
'Memory: ${(RenderCache.raster.store.totalMemory / 1000000).toStringAsFixed(1)}MB'),
|
||||
const Divider(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_refreshTimer.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,8 @@ class App extends StatelessWidget {
|
||||
child: Lottie.asset(
|
||||
assetName,
|
||||
fit: BoxFit.contain,
|
||||
enableRenderCache: true,
|
||||
renderCache: RenderCache.drawingCommands,
|
||||
backgroundLoading: false,
|
||||
onWarning: (w) => _logger.info('$assetName - $w'),
|
||||
frameBuilder: (context, child, composition) {
|
||||
return AnimatedOpacity(
|
||||
@ -77,7 +78,7 @@ class _Item extends StatelessWidget {
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
color: Colors.black.withValues(alpha: 0.1),
|
||||
offset: const Offset(2, 2),
|
||||
blurRadius: 5)
|
||||
]),
|
||||
|
@ -18,6 +18,7 @@ class App extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
showPerformanceOverlay: true,
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(''),
|
||||
@ -136,6 +137,7 @@ class __LottieState extends State<_Lottie> with TickerProviderStateMixin {
|
||||
decoration: BoxDecoration(border: Border.all(color: Colors.red)),
|
||||
child: Lottie(
|
||||
composition: widget.composition,
|
||||
renderCache: RenderCache.raster,
|
||||
controller: _controller,
|
||||
width: widget.width,
|
||||
height: widget.height,
|
||||
|
@ -16,8 +16,8 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
||||
|
||||
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
|
||||
|
||||
COCOAPODS: 1.14.2
|
||||
COCOAPODS: 1.15.2
|
||||
|
@ -203,7 +203,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 1430;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "The Flutter Authors";
|
||||
TargetAttributes = {
|
||||
33CC10EC2044A3C60003C045 = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
LastUpgradeVersion = "1510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -2,19 +2,7 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.assets.pictures.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -1,18 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.assets.pictures.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<dict/>
|
||||
</plist>
|
||||
|
@ -5,10 +5,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b"
|
||||
sha256: "6199c74e3db4fbfbd04f66d739e72fe11c8a8957d5f219f1f4482dbde6420b5a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.9"
|
||||
version: "4.0.2"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -45,26 +45,26 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: collection
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
version: "1.19.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
version: "3.1.2"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
version: "3.0.6"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -77,10 +77,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
||||
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.3"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -90,134 +90,150 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_colorpicker
|
||||
sha256: "458a6ed8ea480eb16ff892aedb4b7092b2804affd7e046591fb03127e8d8ef8b"
|
||||
sha256: "969de5f6f9e2a570ac660fb7b501551451ea2a1ab9e2097e89475f60e07816ea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
version: "1.1.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
|
||||
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
version: "5.0.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
golden_toolkit:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: golden_toolkit
|
||||
sha256: "8f74adab33154fe7b731395782797021f97d2edc52f7bfb85ff4f1b5c4a215f0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.15.0"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
|
||||
sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.2.2"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
js:
|
||||
version: "4.1.2"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
name: leak_tracker
|
||||
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
version: "10.0.7"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.8"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
|
||||
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
version: "5.1.1"
|
||||
logging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: logging
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.0"
|
||||
lottie:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "3.0.0-alpha.3"
|
||||
version: "3.3.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16"
|
||||
version: "0.12.16+1"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.0"
|
||||
version: "0.11.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
version: "1.15.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.3"
|
||||
version: "1.9.0"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
|
||||
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.5"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
|
||||
sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
version: "2.2.15"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
|
||||
sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
version: "2.4.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -230,47 +246,63 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
|
||||
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
|
||||
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
version: "2.3.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
|
||||
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
version: "3.1.6"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.7"
|
||||
pointycastle:
|
||||
version: "2.1.8"
|
||||
posix:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
|
||||
name: posix
|
||||
sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.7.3"
|
||||
version: "6.0.1"
|
||||
shelf:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: shelf
|
||||
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.2"
|
||||
shelf_static:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: shelf_static
|
||||
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
version: "0.0.0"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -283,10 +315,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
version: "1.12.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -299,10 +331,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -315,18 +347,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
version: "0.7.3"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
version: "1.4.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -335,30 +367,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "7c99c0e1e2fa190b48d25c81ca5e42036d5cac81430ef249027d97b0935c553f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.0"
|
||||
version: "1.1.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
|
||||
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
version: "1.1.0"
|
||||
sdks:
|
||||
dart: ">=3.2.0 <4.0.0"
|
||||
flutter: ">=3.16.0"
|
||||
dart: ">=3.6.0 <4.0.0"
|
||||
flutter: ">=3.27.0"
|
||||
|
@ -5,7 +5,7 @@ publish_to: none
|
||||
version: 2.7.0+1
|
||||
|
||||
environment:
|
||||
sdk: "^3.2.0"
|
||||
sdk: "^3.6.0"
|
||||
|
||||
dependencies:
|
||||
collection:
|
||||
@ -23,7 +23,8 @@ dev_dependencies:
|
||||
flutter_lints:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
golden_toolkit:
|
||||
shelf:
|
||||
shelf_static:
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
9
example/tool/web_server.dart
Normal file
9
example/tool/web_server.dart
Normal file
@ -0,0 +1,9 @@
|
||||
import 'dart:io';
|
||||
import 'package:shelf/shelf_io.dart';
|
||||
import 'package:shelf_static/shelf_static.dart';
|
||||
|
||||
void main() async {
|
||||
var server = await serve(
|
||||
createStaticHandler('build/web'), InternetAddress.loopbackIPv4, 0);
|
||||
print('Listen on http://${server.address.host}:${server.port}/index.html');
|
||||
}
|
@ -14,5 +14,6 @@ export 'src/providers/lottie_provider.dart' show LottieCache, LottieProvider;
|
||||
export 'src/providers/memory_provider.dart' show MemoryLottie;
|
||||
export 'src/providers/network_provider.dart' show NetworkLottie;
|
||||
export 'src/raw_lottie.dart' show RawLottie;
|
||||
export 'src/render_cache.dart' show RenderCache;
|
||||
export 'src/value/drop_shadow.dart' show DropShadow;
|
||||
export 'src/value_delegate.dart' show ValueDelegate;
|
||||
|
@ -14,7 +14,6 @@ import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/dash_path.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../utils/utils.dart';
|
||||
import '../../value/drop_shadow.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
@ -29,8 +28,8 @@ import 'trim_path_content.dart';
|
||||
|
||||
abstract class BaseStrokeContent
|
||||
implements KeyPathElementContent, DrawingContent {
|
||||
final Path _path = PathFactory.create();
|
||||
final Path _trimPathPath = PathFactory.create();
|
||||
final Path _path = Path();
|
||||
final Path _trimPathPath = Path();
|
||||
final LottieDrawable lottieDrawable;
|
||||
final BaseLayer layer;
|
||||
final List<_PathGroup> _pathGroups = <_PathGroup>[];
|
||||
@ -135,8 +134,7 @@ abstract class BaseStrokeContent
|
||||
}
|
||||
|
||||
@override
|
||||
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
void draw(Canvas canvas, Matrix4 parentMatrix, {required int parentAlpha}) {
|
||||
L.beginSection('StrokeContent#draw');
|
||||
if (parentMatrix.hasZeroScaleAxis) {
|
||||
L.endSection('StrokeContent#draw');
|
||||
|
@ -8,7 +8,6 @@ import '../../model/key_path.dart';
|
||||
import '../../model/key_path_element.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/transform_keyframe_animation.dart';
|
||||
import 'content.dart';
|
||||
@ -42,7 +41,7 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
|
||||
}
|
||||
|
||||
final Matrix4 _matrix = Matrix4.identity();
|
||||
final Path _path = PathFactory.create();
|
||||
final Path _path = Path();
|
||||
|
||||
@override
|
||||
final String? name;
|
||||
@ -144,8 +143,7 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
|
||||
}
|
||||
|
||||
@override
|
||||
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
void draw(Canvas canvas, Matrix4 parentMatrix, {required int parentAlpha}) {
|
||||
if (_hidden) {
|
||||
return;
|
||||
}
|
||||
@ -176,7 +174,7 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
|
||||
for (var i = _contents.length - 1; i >= 0; i--) {
|
||||
Object content = _contents[i];
|
||||
if (content is DrawingContent) {
|
||||
content.draw(canvas, size, _matrix, parentAlpha: childAlpha);
|
||||
content.draw(canvas, _matrix, parentAlpha: childAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ import 'package:vector_math/vector_math_64.dart';
|
||||
import 'content.dart';
|
||||
|
||||
abstract class DrawingContent extends Content {
|
||||
void draw(Canvas canvas, Size canvasSize, Matrix4 parentMatrix,
|
||||
{required int parentAlpha});
|
||||
void draw(Canvas canvas, Matrix4 parentMatrix, {required int parentAlpha});
|
||||
Rect getBounds(Matrix4 parentMatrix, {required bool applyParents});
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import '../../model/key_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import 'compound_trim_path_content.dart';
|
||||
@ -19,7 +18,7 @@ import 'trim_path_content.dart';
|
||||
class EllipseContent implements PathContent, KeyPathElementContent {
|
||||
static const _ellipseControlPointPercentage = 0.55228;
|
||||
|
||||
final Path _path = PathFactory.create();
|
||||
final Path _path = Path();
|
||||
|
||||
@override
|
||||
final String? name;
|
||||
|
@ -9,7 +9,6 @@ import '../../model/key_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/drop_shadow.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
@ -21,7 +20,7 @@ import 'key_path_element_content.dart';
|
||||
import 'path_content.dart';
|
||||
|
||||
class FillContent implements DrawingContent, KeyPathElementContent {
|
||||
final Path _path = PathFactory.create();
|
||||
final Path _path = Path();
|
||||
final BaseLayer layer;
|
||||
@override
|
||||
final String? name;
|
||||
@ -79,17 +78,13 @@ class FillContent implements DrawingContent, KeyPathElementContent {
|
||||
}
|
||||
|
||||
@override
|
||||
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
void draw(Canvas canvas, Matrix4 parentMatrix, {required int parentAlpha}) {
|
||||
if (_hidden) {
|
||||
return;
|
||||
}
|
||||
L.beginSection('FillContent#draw');
|
||||
|
||||
var paint = Paint()..color = _colorAnimation.value;
|
||||
if (layer.blendMode case var blendMode?) {
|
||||
paint.blendMode = blendMode;
|
||||
}
|
||||
var alpha =
|
||||
((parentAlpha / 255.0 * _opacityAnimation.value / 100.0) * 255).round();
|
||||
paint.setAlpha(alpha.clamp(0, 255));
|
||||
|
@ -11,7 +11,6 @@ import '../../model/key_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/drop_shadow.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
@ -29,7 +28,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
final GradientFill _fill;
|
||||
final _linearGradientCache = <int, Gradient>{};
|
||||
final _radialGradientCache = <int, Gradient>{};
|
||||
final _path = PathFactory.create();
|
||||
final _path = Path();
|
||||
final _paint = Paint();
|
||||
final _paths = <PathContent>[];
|
||||
final BaseKeyframeAnimation<GradientColor, GradientColor> _colorAnimation;
|
||||
@ -97,8 +96,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
}
|
||||
|
||||
@override
|
||||
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
void draw(Canvas canvas, Matrix4 parentMatrix, {required int parentAlpha}) {
|
||||
if (_fill.hidden) {
|
||||
return;
|
||||
}
|
||||
|
@ -61,8 +61,7 @@ class GradientStrokeContent extends BaseStrokeContent {
|
||||
}
|
||||
|
||||
@override
|
||||
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
void draw(Canvas canvas, Matrix4 parentMatrix, {required int parentAlpha}) {
|
||||
if (_hidden) {
|
||||
return;
|
||||
}
|
||||
@ -76,7 +75,7 @@ class GradientStrokeContent extends BaseStrokeContent {
|
||||
|
||||
paint.shader = gradient;
|
||||
|
||||
super.draw(canvas, size, parentMatrix, parentAlpha: parentAlpha);
|
||||
super.draw(canvas, parentMatrix, parentAlpha: parentAlpha);
|
||||
}
|
||||
|
||||
Gradient _getLinearGradient(Matrix4 parentMatrix) {
|
||||
|
@ -1,16 +1,15 @@
|
||||
import 'dart:ui';
|
||||
import '../../model/content/merge_paths.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import 'content.dart';
|
||||
import 'content_group.dart';
|
||||
import 'greedy_content.dart';
|
||||
import 'path_content.dart';
|
||||
|
||||
class MergePathsContent implements PathContent, GreedyContent {
|
||||
final Path _firstPath = PathFactory.create();
|
||||
final Path _remainderPath = PathFactory.create();
|
||||
final Path _path = PathFactory.create();
|
||||
final Path _firstPath = Path();
|
||||
final Path _remainderPath = Path();
|
||||
final Path _path = Path();
|
||||
|
||||
final List<PathContent> _pathContents = <PathContent>[];
|
||||
final MergePaths _mergePaths;
|
||||
|
@ -8,7 +8,6 @@ import '../../model/content/shape_trim_path.dart';
|
||||
import '../../model/key_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import 'compound_trim_path_content.dart';
|
||||
@ -24,7 +23,7 @@ class PolystarContent implements PathContent, KeyPathElementContent {
|
||||
/// work otherwise.
|
||||
static const _polystarMagicNumber = .47829;
|
||||
static const _polygonMagicNumber = .25;
|
||||
final _path = PathFactory.create();
|
||||
final _path = Path();
|
||||
|
||||
final LottieDrawable lottieDrawable;
|
||||
final PolystarShape _polystarShape;
|
||||
|
@ -8,7 +8,6 @@ import '../../model/content/shape_trim_path.dart';
|
||||
import '../../model/key_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import 'compound_trim_path_content.dart';
|
||||
@ -19,7 +18,7 @@ import 'rounded_corners_content.dart';
|
||||
import 'trim_path_content.dart';
|
||||
|
||||
class RectangleContent implements KeyPathElementContent, PathContent {
|
||||
final _path = PathFactory.create();
|
||||
final _path = Path();
|
||||
|
||||
@override
|
||||
final String? name;
|
||||
|
@ -7,7 +7,6 @@ import '../../model/key_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import '../keyframe/transform_keyframe_animation.dart';
|
||||
@ -25,7 +24,7 @@ class RepeaterContent
|
||||
GreedyContent,
|
||||
KeyPathElementContent {
|
||||
final Matrix4 _matrix = Matrix4.identity();
|
||||
final _path = PathFactory.create();
|
||||
final _path = Path();
|
||||
|
||||
final LottieDrawable lottieDrawable;
|
||||
final BaseLayer layer;
|
||||
@ -105,8 +104,7 @@ class RepeaterContent
|
||||
}
|
||||
|
||||
@override
|
||||
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
void draw(Canvas canvas, Matrix4 parentMatrix, {required int parentAlpha}) {
|
||||
var copies = _copies.value;
|
||||
var offset = _offset.value;
|
||||
var startOpacity = _transform.startOpacity!.value / 100.0;
|
||||
@ -116,7 +114,7 @@ class RepeaterContent
|
||||
_matrix.preConcat(_transform.getMatrixForRepeater(i + offset));
|
||||
var newAlpha =
|
||||
parentAlpha * lerpDouble(startOpacity, endOpacity, i / copies)!;
|
||||
_contentGroup!.draw(canvas, size, _matrix, parentAlpha: newAlpha.round());
|
||||
_contentGroup!.draw(canvas, _matrix, parentAlpha: newAlpha.round());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import '../../model/content/shape_path.dart';
|
||||
import '../../model/content/shape_trim_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../keyframe/shape_keyframe_animation.dart';
|
||||
import 'compound_trim_path_content.dart';
|
||||
import 'content.dart';
|
||||
@ -13,7 +12,7 @@ import 'shape_modifier_content.dart';
|
||||
import 'trim_path_content.dart';
|
||||
|
||||
class ShapeContent implements PathContent {
|
||||
final _path = PathFactory.create();
|
||||
final _path = Path();
|
||||
|
||||
final ShapePath _shape;
|
||||
|
||||
|
@ -34,16 +34,16 @@ class StrokeContent extends BaseStrokeContent {
|
||||
}
|
||||
|
||||
@override
|
||||
void draw(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
void draw(Canvas canvas, Matrix4 parentMatrix, {required int parentAlpha}) {
|
||||
if (_hidden) {
|
||||
return;
|
||||
}
|
||||
paint.color = _colorAnimation.value.withAlpha(paint.color.alpha);
|
||||
paint.color =
|
||||
_colorAnimation.value.withAlpha((paint.color.a * 255).toInt());
|
||||
if (_colorFilterAnimation != null) {
|
||||
paint.colorFilter = _colorFilterAnimation!.value;
|
||||
}
|
||||
super.draw(canvas, size, parentMatrix, parentAlpha: parentAlpha);
|
||||
super.draw(canvas, parentMatrix, parentAlpha: parentAlpha);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -3,8 +3,8 @@ import '../../l.dart';
|
||||
import '../../value/keyframe.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
|
||||
/// @param <K> Keyframe type
|
||||
/// @param <A> Animation type
|
||||
/// @param K Keyframe type
|
||||
/// @param A Animation type
|
||||
abstract class BaseKeyframeAnimation<K extends Object, A extends Object?> {
|
||||
// This is not a Set because we don't want to create an iterator object on every setProgress.
|
||||
final listeners = <void Function()>[];
|
||||
@ -82,7 +82,7 @@ abstract class BaseKeyframeAnimation<K extends Object, A extends Object?> {
|
||||
/// the current keyframe's interpolator.
|
||||
double getInterpolatedCurrentKeyframeProgress() {
|
||||
var keyframe = getCurrentKeyframe();
|
||||
if (keyframe.isStatic) {
|
||||
if (keyframe.isStatic || keyframe.interpolator == null) {
|
||||
return 0.0;
|
||||
}
|
||||
return keyframe.interpolator!.transform(getLinearCurrentKeyframeProgress());
|
||||
|
@ -69,8 +69,8 @@ class DropShadowKeyframeAnimation {
|
||||
if (callback != null) {
|
||||
_color.setValueCallback(_createCallback(
|
||||
callback, (c) => c?.color ?? const Color(0xff000000)));
|
||||
_opacity.setValueCallback(
|
||||
_createCallback(callback, (c) => c?.color.alpha.toDouble() ?? 255));
|
||||
_opacity
|
||||
.setValueCallback(_createCallback(callback, (c) => c?.color.a ?? 1));
|
||||
_direction.setValueCallback(
|
||||
_createCallback(callback, (c) => c?.direction ?? 0));
|
||||
_distance
|
||||
|
@ -7,16 +7,18 @@ class IntegerKeyframeAnimation extends KeyframeAnimation<int> {
|
||||
|
||||
@override
|
||||
int getValue(Keyframe<int> keyframe, double keyframeProgress) {
|
||||
if (keyframe.startValue == null || keyframe.endValue == null) {
|
||||
if (keyframe.startValue == null) {
|
||||
throw Exception('Missing values for keyframe.');
|
||||
}
|
||||
|
||||
var endValue = keyframe.endValue ?? keyframe.startValue;
|
||||
|
||||
if (valueCallback != null) {
|
||||
var value = valueCallback!.getValueInternal(
|
||||
keyframe.startFrame,
|
||||
keyframe.endFrame,
|
||||
keyframe.startValue,
|
||||
keyframe.endValue,
|
||||
endValue,
|
||||
keyframeProgress,
|
||||
getLinearCurrentKeyframeProgress(),
|
||||
progress);
|
||||
@ -25,7 +27,6 @@ class IntegerKeyframeAnimation extends KeyframeAnimation<int> {
|
||||
}
|
||||
}
|
||||
|
||||
return lerpDouble(keyframe.startValue, keyframe.endValue, keyframeProgress)!
|
||||
.round();
|
||||
return lerpDouble(keyframe.startValue, endValue, keyframeProgress)!.round();
|
||||
}
|
||||
}
|
||||
|
@ -16,21 +16,20 @@ class PathKeyframe extends Keyframe<Offset> {
|
||||
xInterpolator: keyframe.xInterpolator,
|
||||
yInterpolator: keyframe.yInterpolator,
|
||||
startFrame: keyframe.startFrame,
|
||||
endFrame: keyframe.endFrame) {
|
||||
createPath();
|
||||
}
|
||||
endFrame: keyframe.endFrame);
|
||||
|
||||
void createPath() {
|
||||
Path? _createPath() {
|
||||
var equals =
|
||||
endValue != null && startValue != null && startValue == endValue;
|
||||
if (startValue != null && endValue != null && !equals) {
|
||||
_path = Utils.createPath(startValue!, endValue!, _pointKeyFrame.pathCp1,
|
||||
return Utils.createPath(startValue!, endValue!, _pointKeyFrame.pathCp1,
|
||||
_pointKeyFrame.pathCp2);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// This will be null if the startValue and endValue are the same. */
|
||||
/// This will be null if the startValue and endValue are the same.
|
||||
Path? getPath() {
|
||||
return _path;
|
||||
return _path ??= _createPath();
|
||||
}
|
||||
}
|
||||
|
@ -36,8 +36,22 @@ class PathKeyframeAnimation extends KeyframeAnimation<Offset> {
|
||||
_pathMeasureKeyframe = pathKeyframe;
|
||||
}
|
||||
|
||||
return _pathMeasure
|
||||
.getTangentForOffset(keyframeProgress * _pathMeasure.length)!
|
||||
.position;
|
||||
var length = _pathMeasure.length;
|
||||
|
||||
// allow bounce easings to calculate positions outside the path
|
||||
// by using the tangent at the extremities
|
||||
|
||||
if (keyframeProgress < 0) {
|
||||
var tangent = _pathMeasure.getTangentForOffset(0)!;
|
||||
return tangent.position + tangent.vector * (keyframeProgress * length);
|
||||
} else if (keyframeProgress > 1) {
|
||||
var tangent = _pathMeasure.getTangentForOffset(length)!;
|
||||
return tangent.position +
|
||||
tangent.vector * ((keyframeProgress - 1) * length);
|
||||
} else {
|
||||
return _pathMeasure
|
||||
.getTangentForOffset(keyframeProgress * length)!
|
||||
.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
import 'dart:ui';
|
||||
import '../../model/content/shape_data.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/keyframe.dart';
|
||||
import '../content/shape_modifier_content.dart';
|
||||
import 'base_keyframe_animation.dart';
|
||||
|
||||
class ShapeKeyframeAnimation extends BaseKeyframeAnimation<ShapeData, Path> {
|
||||
final ShapeData _tempShapeData = ShapeData.empty();
|
||||
final Path _tempPath = PathFactory.create();
|
||||
final Path _tempPath = Path();
|
||||
List<ShapeModifierContent>? _shapeModifiers;
|
||||
|
||||
ShapeKeyframeAnimation(super.keyframes);
|
||||
@ -16,7 +15,7 @@ class ShapeKeyframeAnimation extends BaseKeyframeAnimation<ShapeData, Path> {
|
||||
@override
|
||||
Path getValue(Keyframe<ShapeData> keyframe, double keyframeProgress) {
|
||||
var startShapeData = keyframe.startValue!;
|
||||
var endShapeData = keyframe.endValue!;
|
||||
var endShapeData = keyframe.endValue ?? startShapeData;
|
||||
|
||||
_tempShapeData.interpolateBetween(
|
||||
startShapeData, endShapeData, keyframeProgress);
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui';
|
||||
import 'package:archive/archive.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
@ -46,7 +45,6 @@ class LottieComposition {
|
||||
|
||||
static Future<LottieComposition> fromByteData(
|
||||
ByteData data, {
|
||||
LottieImageProviderFactory? imageProviderFactory,
|
||||
LottieDecoder? decoder,
|
||||
}) {
|
||||
return fromBytes(data.buffer.asUint8List(), decoder: decoder);
|
||||
@ -79,7 +77,7 @@ class LottieComposition {
|
||||
}
|
||||
jsonFile ??= archive.files.firstWhere((e) => e.name.endsWith('.json'));
|
||||
|
||||
var composition = parseJsonBytes(jsonFile.content as Uint8List);
|
||||
var composition = parseJsonBytes(jsonFile.content);
|
||||
|
||||
for (var image in composition.images.values) {
|
||||
var imagePath = p.posix.join(image.dirName, image.fileName);
|
||||
@ -96,8 +94,8 @@ class LottieComposition {
|
||||
}
|
||||
|
||||
if (found != null) {
|
||||
image.loadedImage ??= await loadImage(
|
||||
composition, image, MemoryImage(found.content as Uint8List));
|
||||
image.loadedImage ??=
|
||||
await loadImage(composition, image, MemoryImage(found.content));
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,8 +103,8 @@ class LottieComposition {
|
||||
var fileName = p.basenameWithoutExtension(font.name).toLowerCase();
|
||||
var existingFont = composition.fonts.values
|
||||
.firstWhereOrNull((f) => f.family.toLowerCase() == fileName);
|
||||
await loadFontFromList(font.content as Uint8List,
|
||||
fontFamily: existingFont?.family);
|
||||
composition._fontsToLoad
|
||||
.add(FontToLoad(font.content, family: existingFont?.family));
|
||||
}
|
||||
return composition;
|
||||
}
|
||||
@ -138,6 +136,8 @@ class LottieComposition {
|
||||
/// was only faster until you had ~4 masks after which it would actually become slower.
|
||||
int _maskAndMatteCount = 0;
|
||||
|
||||
final _fontsToLoad = <FontToLoad>[];
|
||||
|
||||
WarningCallback? onWarning;
|
||||
|
||||
void addWarning(String warning) {
|
||||
@ -211,9 +211,8 @@ class LottieComposition {
|
||||
return _parameters.images;
|
||||
}
|
||||
|
||||
double get durationFrames {
|
||||
return endFrame - startFrame;
|
||||
}
|
||||
/// Number of frames in the animation
|
||||
double get durationFrames => endFrame - startFrame;
|
||||
|
||||
/// Returns a "rounded" progress value according to the frameRate
|
||||
double roundProgress(double progress, {required FrameRate frameRate}) {
|
||||
@ -224,8 +223,10 @@ class LottieComposition {
|
||||
fps = this.frameRate;
|
||||
}
|
||||
fps ??= frameRate.framesPerSecond;
|
||||
assert(!fps.isNaN && fps.isFinite && !fps.isNegative);
|
||||
|
||||
var totalFrameCount = seconds * fps;
|
||||
var noOffsetDurationFrames = durationFrames + 0.01;
|
||||
var totalFrameCount = (noOffsetDurationFrames / this.frameRate) * fps;
|
||||
var frameIndex = (totalFrameCount * progress).toInt();
|
||||
var roundedProgress = frameIndex / totalFrameCount;
|
||||
assert(roundedProgress >= 0 && roundedProgress <= 1,
|
||||
@ -242,3 +243,19 @@ class LottieComposition {
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class FontToLoad {
|
||||
final Uint8List bytes;
|
||||
final String? family;
|
||||
|
||||
FontToLoad(this.bytes, {this.family});
|
||||
|
||||
static List<FontToLoad>? getAndClear(LottieComposition composition) {
|
||||
if (composition._fontsToLoad.isNotEmpty) {
|
||||
var fonts = composition._fontsToLoad.toList();
|
||||
composition._fontsToLoad.clear();
|
||||
return fonts;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import '../lottie.dart';
|
||||
import 'composition.dart';
|
||||
import 'l.dart';
|
||||
import 'lottie_builder.dart';
|
||||
import 'providers/lottie_provider.dart';
|
||||
import 'render_cache.dart';
|
||||
|
||||
/// A widget to display a loaded [LottieComposition].
|
||||
/// The [controller] property allows to specify a custom AnimationController that
|
||||
@ -16,15 +16,6 @@ class Lottie extends StatefulWidget {
|
||||
/// The cache instance for recently loaded Lottie compositions.
|
||||
static LottieCache get cache => sharedLottieCache;
|
||||
|
||||
/// The maximum memory to use when using `enableRenderCache`.
|
||||
/// When the limit is reached, new frames are not put in the cache until some
|
||||
/// memory is released. When an animation disappear from the screen, its memory
|
||||
/// is released immediately.
|
||||
static int get renderCacheMaxMemory => globalRenderCache.maxMemory;
|
||||
static set renderCacheMaxMemory(int value) {
|
||||
globalRenderCache.maxMemory = value;
|
||||
}
|
||||
|
||||
const Lottie({
|
||||
super.key,
|
||||
required this.composition,
|
||||
@ -41,12 +32,11 @@ class Lottie extends StatefulWidget {
|
||||
this.options,
|
||||
bool? addRepaintBoundary,
|
||||
this.filterQuality,
|
||||
bool? enableRenderCache,
|
||||
this.renderCache,
|
||||
}) : animate = animate ?? true,
|
||||
reverse = reverse ?? false,
|
||||
repeat = repeat ?? true,
|
||||
addRepaintBoundary = addRepaintBoundary ?? true,
|
||||
enableRenderCache = enableRenderCache ?? false;
|
||||
addRepaintBoundary = addRepaintBoundary ?? true;
|
||||
|
||||
/// Creates a widget that displays an [LottieComposition] obtained from an [AssetBundle].
|
||||
static LottieBuilder asset(
|
||||
@ -73,7 +63,8 @@ class Lottie extends StatefulWidget {
|
||||
FilterQuality? filterQuality,
|
||||
WarningCallback? onWarning,
|
||||
LottieDecoder? decoder,
|
||||
bool? enableRenderCache,
|
||||
RenderCache? renderCache,
|
||||
bool? backgroundLoading,
|
||||
}) =>
|
||||
LottieBuilder.asset(
|
||||
name,
|
||||
@ -99,12 +90,13 @@ class Lottie extends StatefulWidget {
|
||||
filterQuality: filterQuality,
|
||||
onWarning: onWarning,
|
||||
decoder: decoder,
|
||||
enableRenderCache: enableRenderCache,
|
||||
renderCache: renderCache,
|
||||
backgroundLoading: backgroundLoading,
|
||||
);
|
||||
|
||||
/// Creates a widget that displays an [LottieComposition] obtained from a [File].
|
||||
static LottieBuilder file(
|
||||
Object /*io.File|html.File*/ file, {
|
||||
Object file, {
|
||||
Animation<double>? controller,
|
||||
FrameRate? frameRate,
|
||||
bool? animate,
|
||||
@ -125,7 +117,8 @@ class Lottie extends StatefulWidget {
|
||||
FilterQuality? filterQuality,
|
||||
WarningCallback? onWarning,
|
||||
LottieDecoder? decoder,
|
||||
bool? enableRenderCache,
|
||||
RenderCache? renderCache,
|
||||
bool? backgroundLoading,
|
||||
}) =>
|
||||
LottieBuilder.file(
|
||||
file,
|
||||
@ -149,7 +142,8 @@ class Lottie extends StatefulWidget {
|
||||
filterQuality: filterQuality,
|
||||
onWarning: onWarning,
|
||||
decoder: decoder,
|
||||
enableRenderCache: enableRenderCache,
|
||||
renderCache: renderCache,
|
||||
backgroundLoading: backgroundLoading,
|
||||
);
|
||||
|
||||
/// Creates a widget that displays an [LottieComposition] obtained from a [Uint8List].
|
||||
@ -175,7 +169,8 @@ class Lottie extends StatefulWidget {
|
||||
FilterQuality? filterQuality,
|
||||
WarningCallback? onWarning,
|
||||
LottieDecoder? decoder,
|
||||
bool? enableRenderCache,
|
||||
RenderCache? renderCache,
|
||||
bool? backgroundLoading,
|
||||
}) =>
|
||||
LottieBuilder.memory(
|
||||
bytes,
|
||||
@ -199,12 +194,15 @@ class Lottie extends StatefulWidget {
|
||||
filterQuality: filterQuality,
|
||||
onWarning: onWarning,
|
||||
decoder: decoder,
|
||||
enableRenderCache: enableRenderCache,
|
||||
renderCache: renderCache,
|
||||
backgroundLoading: backgroundLoading,
|
||||
);
|
||||
|
||||
/// Creates a widget that displays an [LottieComposition] obtained from the network.
|
||||
static LottieBuilder network(
|
||||
String url, {
|
||||
http.Client? client,
|
||||
Map<String, String>? headers,
|
||||
Animation<double>? controller,
|
||||
FrameRate? frameRate,
|
||||
bool? animate,
|
||||
@ -225,10 +223,13 @@ class Lottie extends StatefulWidget {
|
||||
FilterQuality? filterQuality,
|
||||
WarningCallback? onWarning,
|
||||
LottieDecoder? decoder,
|
||||
bool? enableRenderCache,
|
||||
RenderCache? renderCache,
|
||||
bool? backgroundLoading,
|
||||
}) =>
|
||||
LottieBuilder.network(
|
||||
url,
|
||||
client: client,
|
||||
headers: headers,
|
||||
controller: controller,
|
||||
frameRate: frameRate,
|
||||
animate: animate,
|
||||
@ -249,7 +250,8 @@ class Lottie extends StatefulWidget {
|
||||
filterQuality: filterQuality,
|
||||
onWarning: onWarning,
|
||||
decoder: decoder,
|
||||
enableRenderCache: enableRenderCache,
|
||||
renderCache: renderCache,
|
||||
backgroundLoading: backgroundLoading,
|
||||
);
|
||||
|
||||
/// The Lottie composition to animate.
|
||||
@ -346,26 +348,38 @@ class Lottie extends StatefulWidget {
|
||||
/// Defaults to [FilterQuality.low]
|
||||
final FilterQuality? filterQuality;
|
||||
|
||||
/// Opt-in a special render mode where the frames of the animation are
|
||||
/// lazily rendered in offscreen images.
|
||||
/// Subsequent runs of the animation will be very cheap to render.
|
||||
/// {@template lottie.renderCache}
|
||||
/// Opt-in to a special render mode where the frames of the animation are
|
||||
/// lazily rendered and kept in a cache.
|
||||
/// Subsequent runs of the animation will be cheaper to render.
|
||||
///
|
||||
/// This is useful is the animation is complex and can consume lot of energy
|
||||
/// from the battery.
|
||||
/// This is will trade an excessive CPU usage for an increase memory usage.
|
||||
/// This will trade an excessive CPU usage for an increase memory usage.
|
||||
/// The main use-case is a short and small (size on the screen) animation that is
|
||||
/// played repeatedly.
|
||||
///
|
||||
/// There are 2 kinds of caches:
|
||||
/// - [RenderCache.raster]: keep the frame rasterized in the cache (as [dart:ui.Image]).
|
||||
/// Subsequent runs of the animation are very cheap for both the CPU and GPU but it takes
|
||||
/// a lot of memory (rendered_width * rendered_height * frame_rate * duration_of_the_animation).
|
||||
/// This should only be used for very short and very small animations.
|
||||
/// - [RenderCache.drawingCommands]: keep the frame as a list of graphical operations ([dart:ui.Picture]).
|
||||
/// Subsequent runs of the animation are cheaper for the CPU but not for the GPU.
|
||||
/// Memory usage is a lot lower than RenderCache.raster.
|
||||
///
|
||||
/// The render cache is managed internally and will release the memory once the
|
||||
/// animation is disposed. The cache is shared between all animations. If 2 `Lottie`
|
||||
/// widget are rendered at the same size, they will render only once.
|
||||
///
|
||||
/// animation disappear. The cache is shared between all animations.
|
||||
|
||||
/// Any change in the configuration of the animation (delegates, frame rate etc...)
|
||||
/// will clear the cache.
|
||||
/// Any change in the size will invalidate the cache. The cache use the final size
|
||||
/// visible on the screen (with all transforms applied).
|
||||
/// will clear the cache entry.
|
||||
/// For RenderCache.raster, any change in the size will invalidate the cache entry. The cache
|
||||
/// use the final size visible on the screen (with all transforms applied).
|
||||
///
|
||||
/// In order to not exceed the memory limit of a device, the cache is constrained
|
||||
/// In order to not exceed the memory limit of a device, the raster cache is constrained
|
||||
/// to maximum 50MB. After that, animations are not cached anymore.
|
||||
final bool enableRenderCache;
|
||||
/// {@endtemplate}
|
||||
final RenderCache? renderCache;
|
||||
|
||||
static bool get traceEnabled => L.traceEnabled;
|
||||
static set traceEnabled(bool enabled) {
|
||||
@ -435,7 +449,7 @@ class _LottieState extends State<Lottie> with TickerProviderStateMixin {
|
||||
fit: widget.fit,
|
||||
alignment: widget.alignment,
|
||||
filterQuality: widget.filterQuality,
|
||||
enableRenderCache: widget.enableRenderCache,
|
||||
renderCache: widget.renderCache,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'composition.dart';
|
||||
import 'frame_rate.dart';
|
||||
import 'lottie.dart';
|
||||
@ -12,6 +13,7 @@ import 'providers/load_image.dart';
|
||||
import 'providers/lottie_provider.dart';
|
||||
import 'providers/memory_provider.dart';
|
||||
import 'providers/network_provider.dart';
|
||||
import 'render_cache.dart';
|
||||
|
||||
typedef LottieFrameBuilder = Widget Function(
|
||||
BuildContext context,
|
||||
@ -60,12 +62,13 @@ class LottieBuilder extends StatefulWidget {
|
||||
this.addRepaintBoundary,
|
||||
this.filterQuality,
|
||||
this.onWarning,
|
||||
this.enableRenderCache,
|
||||
this.renderCache,
|
||||
});
|
||||
|
||||
/// Creates a widget that displays an [LottieComposition] obtained from the network.
|
||||
LottieBuilder.network(
|
||||
String src, {
|
||||
http.Client? client,
|
||||
Map<String, String>? headers,
|
||||
this.controller,
|
||||
this.frameRate,
|
||||
@ -87,11 +90,14 @@ class LottieBuilder extends StatefulWidget {
|
||||
this.filterQuality,
|
||||
this.onWarning,
|
||||
LottieDecoder? decoder,
|
||||
this.enableRenderCache,
|
||||
this.renderCache,
|
||||
bool? backgroundLoading,
|
||||
}) : lottie = NetworkLottie(src,
|
||||
client: client,
|
||||
headers: headers,
|
||||
imageProviderFactory: imageProviderFactory,
|
||||
decoder: decoder);
|
||||
decoder: decoder,
|
||||
backgroundLoading: backgroundLoading);
|
||||
|
||||
/// Creates a widget that displays an [LottieComposition] obtained from a [File].
|
||||
///
|
||||
@ -104,7 +110,7 @@ class LottieBuilder extends StatefulWidget {
|
||||
/// `android.permission.READ_EXTERNAL_STORAGE` permission.
|
||||
///
|
||||
LottieBuilder.file(
|
||||
Object /*io.File|html.File*/ file, {
|
||||
Object file, {
|
||||
this.controller,
|
||||
this.frameRate,
|
||||
this.animate,
|
||||
@ -125,9 +131,14 @@ class LottieBuilder extends StatefulWidget {
|
||||
this.filterQuality,
|
||||
this.onWarning,
|
||||
LottieDecoder? decoder,
|
||||
this.enableRenderCache,
|
||||
}) : lottie = FileLottie(file,
|
||||
imageProviderFactory: imageProviderFactory, decoder: decoder);
|
||||
this.renderCache,
|
||||
bool? backgroundLoading,
|
||||
}) : lottie = FileLottie(
|
||||
file,
|
||||
imageProviderFactory: imageProviderFactory,
|
||||
decoder: decoder,
|
||||
backgroundLoading: backgroundLoading,
|
||||
);
|
||||
|
||||
/// Creates a widget that displays an [LottieComposition] obtained from an [AssetBundle].
|
||||
LottieBuilder.asset(
|
||||
@ -154,12 +165,14 @@ class LottieBuilder extends StatefulWidget {
|
||||
this.filterQuality,
|
||||
this.onWarning,
|
||||
LottieDecoder? decoder,
|
||||
this.enableRenderCache,
|
||||
this.renderCache,
|
||||
bool? backgroundLoading,
|
||||
}) : lottie = AssetLottie(name,
|
||||
bundle: bundle,
|
||||
package: package,
|
||||
imageProviderFactory: imageProviderFactory,
|
||||
decoder: decoder);
|
||||
decoder: decoder,
|
||||
backgroundLoading: backgroundLoading);
|
||||
|
||||
/// Creates a widget that displays an [LottieComposition] obtained from a [Uint8List].
|
||||
LottieBuilder.memory(
|
||||
@ -184,9 +197,14 @@ class LottieBuilder extends StatefulWidget {
|
||||
this.filterQuality,
|
||||
this.onWarning,
|
||||
LottieDecoder? decoder,
|
||||
this.enableRenderCache,
|
||||
}) : lottie = MemoryLottie(bytes,
|
||||
imageProviderFactory: imageProviderFactory, decoder: decoder);
|
||||
this.renderCache,
|
||||
bool? backgroundLoading,
|
||||
}) : lottie = MemoryLottie(
|
||||
bytes,
|
||||
imageProviderFactory: imageProviderFactory,
|
||||
decoder: decoder,
|
||||
backgroundLoading: backgroundLoading,
|
||||
);
|
||||
|
||||
/// The lottie animation to load.
|
||||
/// Example of providers: [AssetLottie], [NetworkLottie], [FileLottie], [MemoryLottie]
|
||||
@ -417,26 +435,36 @@ class LottieBuilder extends StatefulWidget {
|
||||
/// ```
|
||||
final ImageErrorWidgetBuilder? errorBuilder;
|
||||
|
||||
/// Opt-in a special render mode where the frames of the animation are
|
||||
/// lazily rendered in offscreen images.
|
||||
/// Subsequent runs of the animation will be very cheap to render.
|
||||
/// Opt-in to a special render mode where the frames of the animation are
|
||||
/// lazily rendered and kept in a cache.
|
||||
/// Subsequent runs of the animation will be cheaper to render.
|
||||
///
|
||||
/// This is useful is the animation is complex and can consume lot of energy
|
||||
/// from the battery.
|
||||
/// This is will trade an excessive CPU usage for an increase memory usage.
|
||||
/// This will trade an excessive CPU usage for an increase memory usage.
|
||||
/// The main use-case is a short and small (size on the screen) animation that is
|
||||
/// played repeatedly.
|
||||
///
|
||||
/// There are 2 kinds of caches:
|
||||
/// - [RenderCache.raster]: keep the frame rasterized in the cache (as [dart:ui.Image]).
|
||||
/// Subsequent runs of the animation are very cheap for both the CPU and GPU but it takes
|
||||
/// a lot of memory (rendered_width * rendered_height * frame_rate * duration_of_the_animation).
|
||||
/// This should only be used for very short and very small animations.
|
||||
/// - [RenderCache.drawingCommands]: keep the frame as a list of graphical operations ([dart:ui.Picture]).
|
||||
/// Subsequent runs of the animation are cheaper for the CPU but not for the GPU.
|
||||
/// Memory usage is a lot lower than RenderCache.raster.
|
||||
///
|
||||
/// The render cache is managed internally and will release the memory once the
|
||||
/// animation is disposed. The cache is shared between all animations. If 2 `Lottie`
|
||||
/// widget are rendered at the same size, they will render only once.
|
||||
///
|
||||
/// animation disappear. The cache is shared between all animations.
|
||||
|
||||
/// Any change in the configuration of the animation (delegates, frame rate etc...)
|
||||
/// will clear the cache.
|
||||
/// Any change in the size will invalidate the cache. The cache use the final size
|
||||
/// visible on the screen (with all transforms applied).
|
||||
/// will clear the cache entry.
|
||||
/// For RenderCache.raster, any change in the size will invalidate the cache entry. The cache
|
||||
/// use the final size visible on the screen (with all transforms applied).
|
||||
///
|
||||
/// In order to not exceed the memory limit of a device, the cache is constrained
|
||||
/// In order to not exceed the memory limit of a device, the raster cache is constrained
|
||||
/// to maximum 50MB. After that, animations are not cached anymore.
|
||||
final bool? enableRenderCache;
|
||||
final RenderCache? renderCache;
|
||||
|
||||
@override
|
||||
State<LottieBuilder> createState() => _LottieBuilderState();
|
||||
@ -533,7 +561,7 @@ class _LottieBuilderState extends State<LottieBuilder> {
|
||||
alignment: widget.alignment,
|
||||
addRepaintBoundary: widget.addRepaintBoundary,
|
||||
filterQuality: widget.filterQuality,
|
||||
enableRenderCache: widget.enableRenderCache,
|
||||
renderCache: widget.renderCache,
|
||||
);
|
||||
|
||||
if (widget.frameBuilder != null) {
|
||||
|
@ -50,6 +50,8 @@ class LottieDrawable {
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
final _progressAliases = <double, double>{};
|
||||
|
||||
double get progress => _progress ?? 0.0;
|
||||
double? _progress;
|
||||
bool setProgress(double value) {
|
||||
@ -58,8 +60,13 @@ class LottieDrawable {
|
||||
composition.roundProgress(value, frameRate: frameRate);
|
||||
if (roundedProgress != _progress) {
|
||||
_isDirty = false;
|
||||
var previousProgress = _progress;
|
||||
_progress = roundedProgress;
|
||||
_compositionLayer.setProgress(roundedProgress);
|
||||
if (!_isDirty && frameRate != FrameRate.max && previousProgress != null) {
|
||||
var alias = _progressAliases[previousProgress] ?? previousProgress;
|
||||
_progressAliases[roundedProgress] = alias;
|
||||
}
|
||||
return _isDirty;
|
||||
} else {
|
||||
return false;
|
||||
@ -76,7 +83,7 @@ class LottieDrawable {
|
||||
}
|
||||
}
|
||||
|
||||
List<Object?> _configHash() {
|
||||
List<Object?> configHash() {
|
||||
return [
|
||||
enableMergePaths,
|
||||
filterQuality,
|
||||
@ -85,6 +92,8 @@ class LottieDrawable {
|
||||
];
|
||||
}
|
||||
|
||||
int delegatesHash() => _delegatesHash;
|
||||
|
||||
int _computeValueDelegateHash(LottieDelegates? delegates) {
|
||||
if (delegates == null) return 0;
|
||||
|
||||
@ -175,7 +184,6 @@ class LottieDrawable {
|
||||
return keyPaths;
|
||||
}
|
||||
|
||||
static final _normalPaint = Paint();
|
||||
void draw(
|
||||
ui.Canvas canvas,
|
||||
ui.Rect rect, {
|
||||
@ -206,35 +214,26 @@ class LottieDrawable {
|
||||
|
||||
var cacheUsed = false;
|
||||
if (renderCache != null) {
|
||||
var rect = Rect.fromPoints(renderCache.localToGlobal(destinationPosition),
|
||||
renderCache.localToGlobal(destinationRect.bottomRight));
|
||||
var cacheImageSize = Size(
|
||||
(rect.size.width * renderCache.devicePixelRatio).roundToDouble(),
|
||||
(rect.size.height * renderCache.devicePixelRatio).roundToDouble());
|
||||
var cacheKey = CacheKey(
|
||||
composition: composition,
|
||||
size: cacheImageSize,
|
||||
config: _configHash(),
|
||||
delegates: _delegatesHash);
|
||||
var cache = renderCache.handle.withKey(cacheKey);
|
||||
var cachedImage = cache.imageForProgress(progress, (cacheCanvas) {
|
||||
_matrix.scale(cacheImageSize.width / sourceSize.width,
|
||||
cacheImageSize.height / sourceSize.height);
|
||||
_compositionLayer.draw(cacheCanvas, cacheImageSize, _matrix,
|
||||
parentAlpha: 255);
|
||||
});
|
||||
if (cachedImage != null) {
|
||||
cacheUsed = true;
|
||||
canvas.drawImageRect(cachedImage, Offset.zero & cacheImageSize,
|
||||
destinationRect, _normalPaint);
|
||||
}
|
||||
var progressForCache = _progressAliases[progress] ?? progress;
|
||||
|
||||
cacheUsed = renderCache.cache.draw(
|
||||
this,
|
||||
progressForCache,
|
||||
canvas,
|
||||
destinationPosition: destinationPosition,
|
||||
destinationRect: destinationRect,
|
||||
sourceSize: sourceSize,
|
||||
sourceRect: sourceRect,
|
||||
renderBox: renderCache.renderBox,
|
||||
devicePixelRatio: renderCache.devicePixelRatio,
|
||||
);
|
||||
}
|
||||
if (!cacheUsed) {
|
||||
canvas.save();
|
||||
canvas.translate(destinationRect.left, destinationRect.top);
|
||||
_matrix.scale(destinationSize.width / sourceRect.width,
|
||||
destinationSize.height / sourceRect.height);
|
||||
_compositionLayer.draw(canvas, rect.size, _matrix, parentAlpha: 255);
|
||||
_compositionLayer.draw(canvas, _matrix, parentAlpha: 255);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
@ -247,12 +246,13 @@ class LottieFontStyle {
|
||||
}
|
||||
|
||||
class RenderCacheContext {
|
||||
final RenderCacheHandle handle;
|
||||
final Offset Function(Offset) localToGlobal;
|
||||
final AnimationCache cache;
|
||||
final RenderBox renderBox;
|
||||
final double devicePixelRatio;
|
||||
|
||||
RenderCacheContext(
|
||||
{required this.handle,
|
||||
required this.localToGlobal,
|
||||
required this.devicePixelRatio});
|
||||
RenderCacheContext({
|
||||
required this.cache,
|
||||
required this.renderBox,
|
||||
required this.devicePixelRatio,
|
||||
});
|
||||
}
|
||||
|
@ -2,54 +2,54 @@ import 'dart:ui';
|
||||
import 'value/drop_shadow.dart';
|
||||
|
||||
/// Property values are the same type as the generic type of their corresponding
|
||||
/// {@link LottieValueCallback}. With this, we can use generics to maintain type safety
|
||||
/// [LottieValueCallback]. With this, we can use generics to maintain type safety
|
||||
/// of the callbacks.
|
||||
///
|
||||
/// Supported properties:
|
||||
/// Transform:
|
||||
/// {@link #TRANSFORM_ANCHOR_POINT}
|
||||
/// {@link #TRANSFORM_POSITION}
|
||||
/// {@link #TRANSFORM_OPACITY}
|
||||
/// {@link #TRANSFORM_SCALE}
|
||||
/// {@link #TRANSFORM_ROTATION}
|
||||
/// {@link #TRANSFORM_SKEW}
|
||||
/// {@link #TRANSFORM_SKEW_ANGLE}
|
||||
/// {TRANSFORM_ANCHOR_POINT}
|
||||
/// {TRANSFORM_POSITION}
|
||||
/// {TRANSFORM_OPACITY}
|
||||
/// {TRANSFORM_SCALE}
|
||||
/// {TRANSFORM_ROTATION}
|
||||
/// {TRANSFORM_SKEW}
|
||||
/// {TRANSFORM_SKEW_ANGLE}
|
||||
///
|
||||
/// Fill:
|
||||
/// {@link #COLOR} (non-gradient)
|
||||
/// {@link #OPACITY}
|
||||
/// {@link #COLOR_FILTER}
|
||||
/// {#COLOR} (non-gradient)
|
||||
/// {#OPACITY}
|
||||
/// {#COLOR_FILTER}
|
||||
///
|
||||
/// Stroke:
|
||||
/// {@link #COLOR} (non-gradient)
|
||||
/// {@link #STROKE_WIDTH}
|
||||
/// {@link #OPACITY}
|
||||
/// {@link #COLOR_FILTER}
|
||||
/// {#COLOR} (non-gradient)
|
||||
/// {#STROKE_WIDTH}
|
||||
/// {#OPACITY}
|
||||
/// {#COLOR_FILTER}
|
||||
///
|
||||
/// Ellipse:
|
||||
/// {@link #POSITION}
|
||||
/// {@link #ELLIPSE_SIZE}
|
||||
/// {#POSITION}
|
||||
/// {#ELLIPSE_SIZE}
|
||||
///
|
||||
/// Polystar:
|
||||
/// {@link #POLYSTAR_POINTS}
|
||||
/// {@link #POLYSTAR_ROTATION}
|
||||
/// {@link #POSITION}
|
||||
/// {@link #POLYSTAR_INNER_RADIUS} (star)
|
||||
/// {@link #POLYSTAR_OUTER_RADIUS}
|
||||
/// {@link #POLYSTAR_INNER_ROUNDEDNESS} (star)
|
||||
/// {@link #POLYSTAR_OUTER_ROUNDEDNESS}
|
||||
/// {#POLYSTAR_POINTS}
|
||||
/// {#POLYSTAR_ROTATION}
|
||||
/// {#POSITION}
|
||||
/// {#POLYSTAR_INNER_RADIUS} (star)
|
||||
/// {#POLYSTAR_OUTER_RADIUS}
|
||||
/// {#POLYSTAR_INNER_ROUNDEDNESS} (star)
|
||||
/// {#POLYSTAR_OUTER_ROUNDEDNESS}
|
||||
///
|
||||
/// Repeater:
|
||||
/// All transform properties
|
||||
/// {@link #REPEATER_COPIES}
|
||||
/// {@link #REPEATER_OFFSET}
|
||||
/// {@link #TRANSFORM_ROTATION}
|
||||
/// {@link #TRANSFORM_START_OPACITY}
|
||||
/// {@link #TRANSFORM_END_OPACITY}
|
||||
/// {#REPEATER_COPIES}
|
||||
/// {#REPEATER_OFFSET}
|
||||
/// {#TRANSFORM_ROTATION}
|
||||
/// {#TRANSFORM_START_OPACITY}
|
||||
/// {#TRANSFORM_END_OPACITY}
|
||||
///
|
||||
/// Layers:
|
||||
/// All transform properties
|
||||
/// {@link #TIME_REMAP} (composition layers only)
|
||||
/// {#TIME_REMAP} (composition layers only)
|
||||
abstract class LottieProperty {
|
||||
/// ColorInt **/
|
||||
static const Color color = Color(0x00000001);
|
||||
|
@ -1,16 +1,32 @@
|
||||
import 'dart:ui';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/collection.dart';
|
||||
import '../../utils/gamma_evaluator.dart';
|
||||
|
||||
// ignore_for_file: avoid_equals_and_hash_code_on_mutable_classes
|
||||
|
||||
class GradientColor {
|
||||
final List<double> positions;
|
||||
final List<Color> colors;
|
||||
|
||||
GradientColor(this.positions, this.colors);
|
||||
const GradientColor(this.positions, this.colors);
|
||||
|
||||
int get size => colors.length;
|
||||
|
||||
void lerp(GradientColor gc1, GradientColor gc2, double progress) {
|
||||
// Fast return in case start and end is the same
|
||||
// or if progress is at start/end or out of [0,1] bounds
|
||||
if (gc1 == gc2) {
|
||||
_copyFrom(gc1);
|
||||
return;
|
||||
} else if (progress <= 0) {
|
||||
_copyFrom(gc1);
|
||||
return;
|
||||
} else if (progress >= 1) {
|
||||
_copyFrom(gc2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gc1.colors.length != gc2.colors.length) {
|
||||
throw Exception('Cannot interpolate between gradients. '
|
||||
'Lengths vary (${gc1.colors.length} vs ${gc2.colors.length})');
|
||||
@ -59,4 +75,30 @@ class GradientColor {
|
||||
var fraction = (position - startPosition) / (endPosition - startPosition);
|
||||
return GammaEvaluator.evaluate(fraction, startColor, endColor);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
}
|
||||
if (other is! GradientColor) {
|
||||
return false;
|
||||
}
|
||||
return const ListEquality<double>().equals(positions, other.positions) &&
|
||||
const ListEquality<Color>().equals(colors, other.colors);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var result = Object.hashAll(positions);
|
||||
result = 31 * result + Object.hashAll(colors);
|
||||
return result;
|
||||
}
|
||||
|
||||
void _copyFrom(GradientColor other) {
|
||||
for (var i = 0; i < other.colors.length; i++) {
|
||||
positions[i] = other.positions[i];
|
||||
colors[i] = other.colors[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,10 @@ class Font {
|
||||
final String style;
|
||||
final double ascent;
|
||||
|
||||
Font(
|
||||
{required this.family,
|
||||
required this.name,
|
||||
required this.style,
|
||||
required this.ascent});
|
||||
Font({
|
||||
required this.family,
|
||||
required this.name,
|
||||
required this.style,
|
||||
required this.ascent,
|
||||
});
|
||||
}
|
||||
|
@ -173,8 +173,7 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
}
|
||||
|
||||
@override
|
||||
void draw(Canvas canvas, Size canvasSize, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
void draw(Canvas canvas, Matrix4 parentMatrix, {required int parentAlpha}) {
|
||||
L.beginSection(_drawTraceName);
|
||||
if (!_visible || layerModel.isHidden) {
|
||||
L.endSection(_drawTraceName);
|
||||
@ -190,10 +189,11 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
L.endSection('Layer#parentMatrix');
|
||||
var opacity = transform.opacity?.value ?? 100;
|
||||
var alpha = ((parentAlpha / 255.0 * opacity / 100.0) * 255).toInt();
|
||||
if (!hasMatteOnThisLayer() && !hasMasksOnThisLayer()) {
|
||||
var blendMode = this.blendMode;
|
||||
if (!hasMatteOnThisLayer() && !hasMasksOnThisLayer() && blendMode == null) {
|
||||
_matrix.preConcat(transform.getMatrix());
|
||||
L.beginSection('Layer#drawLayer');
|
||||
drawLayer(canvas, canvasSize, _matrix, parentAlpha: alpha);
|
||||
drawLayer(canvas, _matrix, parentAlpha: alpha);
|
||||
L.endSection('Layer#drawLayer');
|
||||
_recordRenderTime(L.endSection(_drawTraceName));
|
||||
return;
|
||||
@ -214,24 +214,19 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
_matrix.preConcat(transform.getMatrix());
|
||||
bounds = _intersectBoundsWithMask(bounds, _matrix);
|
||||
|
||||
if (bounds
|
||||
.intersect(Rect.fromLTWH(0, 0, canvasSize.width, canvasSize.height))
|
||||
.isEmpty) {
|
||||
bounds = Rect.zero;
|
||||
}
|
||||
|
||||
L.endSection('Layer#computeBounds');
|
||||
|
||||
if (!bounds.isEmpty) {
|
||||
L.beginSection('Layer#saveLayer');
|
||||
_contentPaint.setAlpha(255);
|
||||
_contentPaint.blendMode = blendMode ?? ui.BlendMode.srcOver;
|
||||
canvas.saveLayer(bounds, _contentPaint);
|
||||
L.endSection('Layer#saveLayer');
|
||||
|
||||
// Clear the off screen buffer. This is necessary for some phones.
|
||||
_clearCanvas(canvas, bounds);
|
||||
L.beginSection('Layer#drawLayer');
|
||||
drawLayer(canvas, canvasSize, _matrix, parentAlpha: alpha);
|
||||
drawLayer(canvas, _matrix, parentAlpha: alpha);
|
||||
L.endSection('Layer#drawLayer');
|
||||
|
||||
if (hasMasksOnThisLayer()) {
|
||||
@ -244,7 +239,7 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
canvas.saveLayer(bounds, _mattePaint);
|
||||
L.endSection('Layer#saveLayer');
|
||||
_clearCanvas(canvas, bounds);
|
||||
_matteLayer!.draw(canvas, canvasSize, parentMatrix, parentAlpha: alpha);
|
||||
_matteLayer!.draw(canvas, parentMatrix, parentAlpha: alpha);
|
||||
L.beginSection('Layer#restoreLayer');
|
||||
canvas.restore();
|
||||
L.endSection('Layer#restoreLayer');
|
||||
@ -339,7 +334,7 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
void drawLayer(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
void drawLayer(Canvas canvas, Matrix4 parentMatrix,
|
||||
{required int parentAlpha});
|
||||
|
||||
void _applyMasks(Canvas canvas, Rect bounds, Matrix4 matrix) {
|
||||
|
@ -75,7 +75,7 @@ class CompositionLayer extends BaseLayer {
|
||||
}
|
||||
|
||||
@override
|
||||
void drawLayer(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
void drawLayer(Canvas canvas, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
L.beginSection('CompositionLayer#draw');
|
||||
var newClipRect = Rect.fromLTWH(0, 0, layerModel.preCompWidth.toDouble(),
|
||||
@ -101,7 +101,7 @@ class CompositionLayer extends BaseLayer {
|
||||
}
|
||||
|
||||
var layer = _layers[i];
|
||||
layer.draw(canvas, size, parentMatrix, parentAlpha: childAlpha);
|
||||
layer.draw(canvas, parentMatrix, parentAlpha: childAlpha);
|
||||
}
|
||||
canvas.restore();
|
||||
L.endSection('CompositionLayer#draw');
|
||||
|
@ -14,7 +14,7 @@ class ImageLayer extends BaseLayer {
|
||||
ImageLayer(super.lottieDrawable, super.layerModel);
|
||||
|
||||
@override
|
||||
void drawLayer(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
void drawLayer(Canvas canvas, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
var bitmap = getBitmap();
|
||||
if (bitmap == null) {
|
||||
|
@ -6,7 +6,7 @@ class NullLayer extends BaseLayer {
|
||||
NullLayer(super.lottieDrawable, super.layerModel);
|
||||
|
||||
@override
|
||||
void drawLayer(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
void drawLayer(Canvas canvas, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
@ -26,9 +26,9 @@ class ShapeLayer extends BaseLayer {
|
||||
}
|
||||
|
||||
@override
|
||||
void drawLayer(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
void drawLayer(Canvas canvas, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
_contentGroup.draw(canvas, size, parentMatrix, parentAlpha: parentAlpha);
|
||||
_contentGroup.draw(canvas, parentMatrix, parentAlpha: parentAlpha);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -5,14 +5,13 @@ import '../../animation/keyframe/value_callback_keyframe_animation.dart';
|
||||
import '../../lottie_drawable.dart';
|
||||
import '../../lottie_property.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import 'base_layer.dart';
|
||||
import 'layer.dart';
|
||||
|
||||
class SolidLayer extends BaseLayer {
|
||||
final Paint paint = Paint()..style = PaintingStyle.fill;
|
||||
final Path path = PathFactory.create();
|
||||
final Path path = Path();
|
||||
BaseKeyframeAnimation<ColorFilter, ColorFilter?>? _colorFilterAnimation;
|
||||
BaseKeyframeAnimation<Color, Color?>? _colorAnimation;
|
||||
|
||||
@ -22,23 +21,21 @@ class SolidLayer extends BaseLayer {
|
||||
}
|
||||
|
||||
@override
|
||||
void drawLayer(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
void drawLayer(Canvas canvas, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
var backgroundAlpha = layerModel.solidColor.alpha;
|
||||
var backgroundAlpha = layerModel.solidColor.a;
|
||||
if (backgroundAlpha == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
paint.color = _colorAnimation?.value ?? layerModel.solidColor;
|
||||
|
||||
var opacity = transform.opacity?.value ?? 100;
|
||||
var alpha = (parentAlpha /
|
||||
255.0 *
|
||||
(backgroundAlpha / 255.0 * opacity / 100.0) *
|
||||
255.0)
|
||||
.round();
|
||||
var alpha =
|
||||
(parentAlpha / 255.0 * (backgroundAlpha * opacity / 100.0) * 255.0)
|
||||
.round();
|
||||
paint.setAlpha(alpha);
|
||||
if (_colorAnimation?.value case var color?) {
|
||||
paint.color = color;
|
||||
}
|
||||
|
||||
if (_colorFilterAnimation != null) {
|
||||
paint.colorFilter = _colorFilterAnimation!.value;
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ class TextLayer extends BaseLayer {
|
||||
}
|
||||
|
||||
@override
|
||||
void drawLayer(Canvas canvas, Size size, Matrix4 parentMatrix,
|
||||
void drawLayer(Canvas canvas, Matrix4 parentMatrix,
|
||||
{required int parentAlpha}) {
|
||||
var documentData = _textAnimation.value;
|
||||
var font = _composition.fonts[documentData.fontName];
|
||||
@ -120,7 +120,7 @@ class TextLayer extends BaseLayer {
|
||||
} else {
|
||||
fillPaintColor = documentData.color;
|
||||
}
|
||||
_fillPaint.color = fillPaintColor.withAlpha(_fillPaint.color.alpha);
|
||||
_fillPaint.color = fillPaintColor.withValues(alpha: _fillPaint.color.a);
|
||||
|
||||
Color strokePaintColor;
|
||||
if (_strokeColorCallbackAnimation != null) {
|
||||
@ -130,7 +130,8 @@ class TextLayer extends BaseLayer {
|
||||
} else {
|
||||
strokePaintColor = documentData.strokeColor;
|
||||
}
|
||||
_strokePaint.color = strokePaintColor.withAlpha(_strokePaint.color.alpha);
|
||||
_strokePaint.color =
|
||||
strokePaintColor.withValues(alpha: _strokePaint.color.a);
|
||||
|
||||
var opacity = transform.opacity?.value ?? 100;
|
||||
var alpha = opacity * 255 / 100 * parentAlpha ~/ 255;
|
||||
@ -418,7 +419,7 @@ class TextLayer extends BaseLayer {
|
||||
}
|
||||
|
||||
void _drawGlyph(Path path, Paint paint, Canvas canvas) {
|
||||
if (paint.color.alpha == 0) {
|
||||
if (paint.color.a == 0) {
|
||||
return;
|
||||
}
|
||||
if (paint.style == PaintingStyle.stroke && paint.strokeWidth == 0) {
|
||||
@ -440,7 +441,7 @@ class TextLayer extends BaseLayer {
|
||||
|
||||
void _drawCharacter(
|
||||
String character, TextStyle textStyle, Paint paint, Canvas canvas) {
|
||||
if (paint.color.alpha == 0) {
|
||||
if (paint.color.a == 0) {
|
||||
return;
|
||||
}
|
||||
if (paint.style == PaintingStyle.stroke && paint.strokeWidth == 0) {
|
||||
|
@ -76,7 +76,6 @@ class DropShadowEffectParser {
|
||||
_radius = AnimatableValueParser.parseFloat(reader, composition);
|
||||
default:
|
||||
reader.skipValue();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
reader.skipName();
|
||||
|
@ -162,7 +162,7 @@ class GradientColorParser {
|
||||
continue;
|
||||
}
|
||||
if (i == colorStopPositions.length - 1 && position >= colorStopPosition) {
|
||||
return colorStopColors[i].withOpacity(opacity);
|
||||
return colorStopColors[i].withValues(alpha: opacity);
|
||||
}
|
||||
// We found the position in which position is between i - 1 and i.
|
||||
var distanceBetweenColors =
|
||||
@ -171,9 +171,9 @@ class GradientColorParser {
|
||||
var percentage = distanceToLowerColor / distanceBetweenColors;
|
||||
var upperColor = colorStopColors[i];
|
||||
var lowerColor = colorStopColors[i - 1];
|
||||
return GammaEvaluator.evaluate(
|
||||
percentage, upperColor.withOpacity(1), lowerColor.withOpacity(1))
|
||||
.withOpacity(opacity);
|
||||
return GammaEvaluator.evaluate(percentage,
|
||||
lowerColor.withValues(alpha: 1), upperColor.withValues(alpha: 1))
|
||||
.withValues(alpha: opacity);
|
||||
}
|
||||
throw Exception('Unreachable code.');
|
||||
}
|
||||
@ -182,7 +182,7 @@ class GradientColorParser {
|
||||
List<double> opacityStopPositions, List<double> opacityStopOpacities) {
|
||||
if (opacityStopOpacities.length < 2 ||
|
||||
position <= opacityStopPositions[0]) {
|
||||
return color.withOpacity(opacityStopOpacities[0]);
|
||||
return color.withValues(alpha: opacityStopOpacities[0]);
|
||||
}
|
||||
for (var i = 1; i < opacityStopPositions.length; i++) {
|
||||
var opacityStopPosition = opacityStopPositions[i];
|
||||
@ -202,7 +202,7 @@ class GradientColorParser {
|
||||
opacity = lerpDouble(
|
||||
opacityStopOpacities[i - 1], opacityStopOpacities[i], percentage)!;
|
||||
}
|
||||
return color.withOpacity(opacity);
|
||||
return color.withValues(alpha: opacity);
|
||||
}
|
||||
throw Exception('Unreachable code.');
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import '../animation/keyframe/path_keyframe.dart';
|
||||
import '../composition.dart';
|
||||
import '../value/keyframe.dart';
|
||||
import 'keyframe_parser.dart';
|
||||
@ -65,9 +64,6 @@ class KeyframesParser {
|
||||
keyframe.endFrame = nextKeyframe.startFrame;
|
||||
if (keyframe.endValue == null && nextKeyframe.startValue != null) {
|
||||
keyframe.endValue = nextKeyframe.startValue;
|
||||
if (keyframe is PathKeyframe) {
|
||||
(keyframe as PathKeyframe).createPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
var lastKeyframe = keyframes[size - 1];
|
||||
|
@ -228,9 +228,9 @@ class LayerParser {
|
||||
case 15:
|
||||
startFrame = reader.nextDouble();
|
||||
case 16:
|
||||
preCompWidth = reader.nextInt();
|
||||
preCompWidth = reader.nextDouble().toInt();
|
||||
case 17:
|
||||
preCompHeight = reader.nextInt();
|
||||
preCompHeight = reader.nextDouble().toInt();
|
||||
case 18:
|
||||
inFrame = reader.nextDouble();
|
||||
case 19:
|
||||
|
@ -33,9 +33,9 @@ class LottieCompositionParser {
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
parameters.bounds.width = reader.nextInt();
|
||||
parameters.bounds.width = reader.nextDouble().toInt();
|
||||
case 1:
|
||||
parameters.bounds.height = reader.nextInt();
|
||||
parameters.bounds.height = reader.nextDouble().toInt();
|
||||
case 2:
|
||||
parameters.startFrame = reader.nextDouble();
|
||||
case 3:
|
||||
@ -70,7 +70,7 @@ class LottieCompositionParser {
|
||||
}
|
||||
}
|
||||
assert(parameters.startFrame != parameters.endFrame,
|
||||
'startFrame == endFrame ($parameters.startFrame)');
|
||||
'startFrame == endFrame (${parameters.startFrame})');
|
||||
assert(
|
||||
parameters.frameRate > 0, 'invalid framerate: ${parameters.frameRate}');
|
||||
|
||||
|
@ -66,7 +66,7 @@ class Buffer {
|
||||
}
|
||||
|
||||
/// Reads and discards {@code byteCount} bytes from this source. Throws an
|
||||
/// {@link java.io.EOFException} if the source is exhausted before the
|
||||
/// [Exception] if the source is exhausted before the
|
||||
/// requested bytes can be skipped.
|
||||
void skip(int byteCount) {
|
||||
_start += byteCount;
|
||||
|
@ -3,6 +3,8 @@ import 'buffer.dart';
|
||||
import 'json_scope.dart';
|
||||
import 'json_utf8_reader.dart';
|
||||
|
||||
// ignore_for_file: unintended_html_in_doc_comment
|
||||
|
||||
/// Reads a JSON (<a href="http://www.ietf.org/rfc/rfc7159.txt">RFC 7159</a>)
|
||||
/// encoded value as a stream of tokens. This stream includes both literal
|
||||
/// values (strings, numbers, booleans, and nulls) as well as the begin and
|
||||
|
@ -857,7 +857,7 @@ class JsonUtf8Reader extends JsonReader {
|
||||
|
||||
/// Returns the next character in the stream that is neither whitespace nor a
|
||||
/// part of a comment. When this returns, the returned character is always at
|
||||
/// {@code buffer.getByte(0)}.
|
||||
/// {buffer.getByte(0)}.
|
||||
int _nextNonWhitespace(bool throwOnEof) {
|
||||
// This code uses ugly local variables 'p' and 'l' representing the 'pos'
|
||||
// and 'limit' fields respectively. Using locals rather than fields saves
|
||||
|
@ -1,10 +1,12 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import '../composition.dart';
|
||||
import '../lottie_image_asset.dart';
|
||||
import 'load_fonts.dart';
|
||||
import 'load_image.dart';
|
||||
import 'lottie_provider.dart';
|
||||
|
||||
@ -16,6 +18,7 @@ class AssetLottie extends LottieProvider {
|
||||
this.package,
|
||||
super.imageProviderFactory,
|
||||
super.decoder,
|
||||
super.backgroundLoading,
|
||||
});
|
||||
|
||||
final String assetName;
|
||||
@ -37,13 +40,21 @@ class AssetLottie extends LottieProvider {
|
||||
|
||||
var data = await chosenBundle.load(keyName);
|
||||
|
||||
var composition = await LottieComposition.fromByteData(data,
|
||||
imageProviderFactory: imageProviderFactory, decoder: decoder);
|
||||
LottieComposition composition;
|
||||
if (backgroundLoading) {
|
||||
composition =
|
||||
await compute(parseJsonBytes, (data.buffer.asUint8List(), decoder));
|
||||
} else {
|
||||
composition =
|
||||
await LottieComposition.fromByteData(data, decoder: decoder);
|
||||
}
|
||||
|
||||
for (var image in composition.images.values) {
|
||||
image.loadedImage ??= await _loadImage(composition, image);
|
||||
}
|
||||
|
||||
await ensureLoadedFonts(composition);
|
||||
|
||||
return composition;
|
||||
});
|
||||
}
|
||||
@ -63,7 +74,7 @@ class AssetLottie extends LottieProvider {
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is AssetLottie &&
|
||||
other.keyName == keyName &&
|
||||
|
@ -1,54 +1 @@
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/widgets.dart';
|
||||
import '../composition.dart';
|
||||
import '../lottie_image_asset.dart';
|
||||
import 'load_image.dart';
|
||||
import 'lottie_provider.dart';
|
||||
import 'provider_io.dart' if (dart.library.html) 'provider_web.dart' as io;
|
||||
|
||||
@immutable
|
||||
class FileLottie extends LottieProvider {
|
||||
FileLottie(
|
||||
this.file, {
|
||||
super.imageProviderFactory,
|
||||
super.decoder,
|
||||
});
|
||||
|
||||
final Object /*io.File|html.File*/ file;
|
||||
|
||||
@override
|
||||
Future<LottieComposition> load({BuildContext? context}) {
|
||||
return sharedLottieCache.putIfAbsent(this, () async {
|
||||
var bytes = await io.loadFile(file);
|
||||
var composition =
|
||||
await LottieComposition.fromBytes(bytes, decoder: decoder);
|
||||
|
||||
for (var image in composition.images.values) {
|
||||
image.loadedImage ??= await _loadImage(composition, image);
|
||||
}
|
||||
|
||||
return composition;
|
||||
});
|
||||
}
|
||||
|
||||
Future<ui.Image?> _loadImage(
|
||||
LottieComposition composition, LottieImageAsset lottieImage) {
|
||||
var imageProvider = getImageProvider(lottieImage);
|
||||
|
||||
imageProvider ??= io.loadImageForFile(file, lottieImage);
|
||||
|
||||
return loadImage(composition, lottieImage, imageProvider);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is FileLottie && other.file == file;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => file.hashCode;
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType(file: ${io.filePath(file)})';
|
||||
}
|
||||
export 'file_provider_no_io.dart' if (dart.library.io) 'file_provider_io.dart';
|
||||
|
77
lib/src/providers/file_provider_io.dart
Normal file
77
lib/src/providers/file_provider_io.dart
Normal file
@ -0,0 +1,77 @@
|
||||
import 'dart:io' as io;
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import '../composition.dart';
|
||||
import '../lottie_image_asset.dart';
|
||||
import 'load_fonts.dart';
|
||||
import 'load_image.dart';
|
||||
import 'lottie_provider.dart';
|
||||
|
||||
@immutable
|
||||
class FileLottie extends LottieProvider {
|
||||
FileLottie(
|
||||
Object file, {
|
||||
super.imageProviderFactory,
|
||||
super.decoder,
|
||||
super.backgroundLoading,
|
||||
}) : file = file as io.File,
|
||||
assert(
|
||||
!kIsWeb,
|
||||
'Lottie.file is not supported on Flutter Web. '
|
||||
'Consider using either Lottie.asset or Lottie.network instead.',
|
||||
);
|
||||
|
||||
final io.File file;
|
||||
|
||||
@override
|
||||
Future<LottieComposition> load({BuildContext? context}) {
|
||||
return sharedLottieCache.putIfAbsent(this, () async {
|
||||
LottieComposition composition;
|
||||
var args = (file, decoder);
|
||||
if (backgroundLoading) {
|
||||
composition = await compute(_loadFileAndParse, args);
|
||||
} else {
|
||||
composition = await _loadFileAndParse(args);
|
||||
}
|
||||
|
||||
for (var image in composition.images.values) {
|
||||
image.loadedImage ??= await _loadImage(composition, image);
|
||||
}
|
||||
|
||||
await ensureLoadedFonts(composition);
|
||||
|
||||
return composition;
|
||||
});
|
||||
}
|
||||
|
||||
Future<ui.Image?> _loadImage(
|
||||
LottieComposition composition, LottieImageAsset lottieImage) {
|
||||
var imageProvider = getImageProvider(lottieImage);
|
||||
|
||||
var imagePath = p.url
|
||||
.join(p.dirname(file.path), lottieImage.dirName, lottieImage.fileName);
|
||||
imageProvider ??= FileImage(io.File(imagePath));
|
||||
|
||||
return loadImage(composition, lottieImage, imageProvider);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is FileLottie && file.path == other.file.path;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => file.hashCode;
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType(file: ${file.path})';
|
||||
}
|
||||
|
||||
Future<LottieComposition> _loadFileAndParse(
|
||||
(io.File, LottieDecoder?) args) async {
|
||||
var bytes = await args.$1.readAsBytes();
|
||||
return await LottieComposition.fromBytes(bytes, decoder: args.$2);
|
||||
}
|
26
lib/src/providers/file_provider_no_io.dart
Normal file
26
lib/src/providers/file_provider_no_io.dart
Normal file
@ -0,0 +1,26 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import '../composition.dart';
|
||||
import 'lottie_provider.dart';
|
||||
|
||||
@immutable
|
||||
class FileLottie extends LottieProvider {
|
||||
FileLottie(
|
||||
this.file, {
|
||||
super.imageProviderFactory,
|
||||
super.decoder,
|
||||
super.backgroundLoading,
|
||||
}) : assert(
|
||||
!kIsWeb,
|
||||
'Lottie.file is not supported on Flutter Web. '
|
||||
'Consider using either Lottie.asset or Lottie.network instead.',
|
||||
);
|
||||
|
||||
final Object file;
|
||||
|
||||
@override
|
||||
Future<LottieComposition> load({BuildContext? context}) {
|
||||
throw UnimplementedError(
|
||||
'FileLottie provider is not supported on Web platform');
|
||||
}
|
||||
}
|
11
lib/src/providers/load_fonts.dart
Normal file
11
lib/src/providers/load_fonts.dart
Normal file
@ -0,0 +1,11 @@
|
||||
import 'dart:ui';
|
||||
import '../composition.dart';
|
||||
|
||||
Future<void> ensureLoadedFonts(LottieComposition composition) async {
|
||||
var fonts = FontToLoad.getAndClear(composition);
|
||||
if (fonts != null) {
|
||||
for (var font in fonts) {
|
||||
await loadFontFromList(font.bytes, fontFamily: font.family);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,12 +4,18 @@ import '../../lottie.dart';
|
||||
import 'load_image.dart';
|
||||
|
||||
abstract class LottieProvider {
|
||||
LottieProvider({this.imageProviderFactory, this.decoder});
|
||||
LottieProvider({
|
||||
this.imageProviderFactory,
|
||||
this.decoder,
|
||||
bool? backgroundLoading,
|
||||
}) : backgroundLoading = backgroundLoading ?? false;
|
||||
|
||||
final LottieImageProviderFactory? imageProviderFactory;
|
||||
|
||||
final LottieDecoder? decoder;
|
||||
|
||||
final bool backgroundLoading;
|
||||
|
||||
ImageProvider? getImageProvider(LottieImageAsset lottieImage) {
|
||||
var imageProvider = fromDataUri(lottieImage.fileName);
|
||||
if (imageProvider == null && imageProviderFactory != null) {
|
||||
@ -21,6 +27,11 @@ abstract class LottieProvider {
|
||||
Future<LottieComposition> load({BuildContext? context});
|
||||
}
|
||||
|
||||
Future<LottieComposition> parseJsonBytes(
|
||||
(Uint8List, LottieDecoder?) args) async {
|
||||
return LottieComposition.fromBytes(args.$1, decoder: args.$2);
|
||||
}
|
||||
|
||||
class LottieCache {
|
||||
final Map<Object, Future<LottieComposition>> _pending =
|
||||
<Object, Future<LottieComposition>>{};
|
||||
|
@ -4,24 +4,37 @@ import 'package:flutter/widgets.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import '../composition.dart';
|
||||
import '../lottie_image_asset.dart';
|
||||
import 'load_fonts.dart';
|
||||
import 'load_image.dart';
|
||||
import 'lottie_provider.dart';
|
||||
|
||||
@immutable
|
||||
class MemoryLottie extends LottieProvider {
|
||||
MemoryLottie(this.bytes, {super.imageProviderFactory, super.decoder});
|
||||
MemoryLottie(
|
||||
this.bytes, {
|
||||
super.imageProviderFactory,
|
||||
super.decoder,
|
||||
super.backgroundLoading,
|
||||
});
|
||||
|
||||
final Uint8List bytes;
|
||||
|
||||
@override
|
||||
Future<LottieComposition> load({BuildContext? context}) {
|
||||
return sharedLottieCache.putIfAbsent(this, () async {
|
||||
var composition =
|
||||
await LottieComposition.fromBytes(bytes, decoder: decoder);
|
||||
LottieComposition composition;
|
||||
if (backgroundLoading) {
|
||||
composition = await compute(parseJsonBytes, (bytes, decoder));
|
||||
} else {
|
||||
composition =
|
||||
await LottieComposition.fromBytes(bytes, decoder: decoder);
|
||||
}
|
||||
for (var image in composition.images.values) {
|
||||
image.loadedImage ??= await _loadImage(composition, image);
|
||||
}
|
||||
|
||||
await ensureLoadedFonts(composition);
|
||||
|
||||
return composition;
|
||||
});
|
||||
}
|
||||
@ -37,7 +50,7 @@ class MemoryLottie extends LottieProvider {
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
|
||||
//TODO(xha): compare bytes content
|
||||
|
@ -1,18 +1,27 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:path/path.dart' as p;
|
||||
import '../composition.dart';
|
||||
import '../lottie_image_asset.dart';
|
||||
import 'load_fonts.dart';
|
||||
import 'load_image.dart';
|
||||
import 'lottie_provider.dart';
|
||||
import 'provider_io.dart' if (dart.library.html) 'provider_web.dart' as network;
|
||||
|
||||
@immutable
|
||||
class NetworkLottie extends LottieProvider {
|
||||
NetworkLottie(this.url,
|
||||
{this.headers, super.imageProviderFactory, super.decoder});
|
||||
NetworkLottie(
|
||||
this.url, {
|
||||
this.client,
|
||||
this.headers,
|
||||
super.imageProviderFactory,
|
||||
super.decoder,
|
||||
super.backgroundLoading,
|
||||
});
|
||||
|
||||
final http.Client? client;
|
||||
final String url;
|
||||
final Map<String, String>? headers;
|
||||
|
||||
@ -20,16 +29,31 @@ class NetworkLottie extends LottieProvider {
|
||||
Future<LottieComposition> load({BuildContext? context}) {
|
||||
return sharedLottieCache.putIfAbsent(this, () async {
|
||||
var resolved = Uri.base.resolve(url);
|
||||
var bytes = await network.loadHttp(resolved, headers: headers);
|
||||
|
||||
var composition =
|
||||
await LottieComposition.fromBytes(bytes, decoder: decoder);
|
||||
var client = this.client ?? http.Client();
|
||||
try {
|
||||
var bytes = await client.readBytes(resolved, headers: headers);
|
||||
|
||||
for (var image in composition.images.values) {
|
||||
image.loadedImage ??= await _loadImage(resolved, composition, image);
|
||||
LottieComposition composition;
|
||||
if (backgroundLoading) {
|
||||
composition = await compute(parseJsonBytes, (bytes, decoder));
|
||||
} else {
|
||||
composition =
|
||||
await LottieComposition.fromBytes(bytes, decoder: decoder);
|
||||
}
|
||||
|
||||
for (var image in composition.images.values) {
|
||||
image.loadedImage ??= await _loadImage(resolved, composition, image);
|
||||
}
|
||||
|
||||
await ensureLoadedFonts(composition);
|
||||
|
||||
return composition;
|
||||
} finally {
|
||||
if (this.client == null) {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
return composition;
|
||||
});
|
||||
}
|
||||
|
||||
@ -47,7 +71,7 @@ class NetworkLottie extends LottieProvider {
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is NetworkLottie &&
|
||||
other.url == url &&
|
||||
|
@ -1,41 +0,0 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import '../lottie_image_asset.dart';
|
||||
|
||||
final HttpClient _sharedHttpClient = HttpClient()..autoUncompress = false;
|
||||
|
||||
Future<Uint8List> loadHttp(Uri uri, {Map<String, String>? headers}) async {
|
||||
var request = await _sharedHttpClient.getUrl(uri);
|
||||
headers?.forEach((String name, String value) {
|
||||
request.headers.add(name, value);
|
||||
});
|
||||
final response = await request.close();
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
throw Exception('Http error. Status code: ${response.statusCode} for $uri');
|
||||
}
|
||||
|
||||
final bytes = await consolidateHttpClientResponseBytes(response);
|
||||
if (bytes.lengthInBytes == 0) {
|
||||
throw Exception('NetworkImage is an empty file: $uri');
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
Future<Uint8List> loadFile(Object file) {
|
||||
return (file as File).readAsBytes();
|
||||
}
|
||||
|
||||
String filePath(Object file) {
|
||||
return (file as File).path;
|
||||
}
|
||||
|
||||
ImageProvider loadImageForFile(Object file, LottieImageAsset lottieImage) {
|
||||
var fileIo = file as File;
|
||||
|
||||
var imagePath = p.url
|
||||
.join(p.dirname(fileIo.path), lottieImage.dirName, lottieImage.fileName);
|
||||
return FileImage(File(imagePath));
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
import 'dart:html';
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import '../lottie_image_asset.dart';
|
||||
|
||||
// ignore_for_file: avoid_web_libraries_in_flutter
|
||||
|
||||
Future<Uint8List> loadHttp(Uri uri, {Map<String, String>? headers}) async {
|
||||
var request = await HttpRequest.request(uri.toString(),
|
||||
requestHeaders: headers, responseType: 'blob');
|
||||
|
||||
return _loadBlob(request.response as Blob);
|
||||
}
|
||||
|
||||
Future<Uint8List> loadFile(Object file) {
|
||||
return _loadBlob(file as File);
|
||||
}
|
||||
|
||||
Future<Uint8List> _loadBlob(Blob file) async {
|
||||
var reader = FileReader();
|
||||
reader.readAsArrayBuffer(file);
|
||||
|
||||
await reader.onLoadEnd.first;
|
||||
if (reader.readyState != FileReader.DONE) {
|
||||
throw Exception('Error while reading blob');
|
||||
}
|
||||
|
||||
return reader.result! as Uint8List;
|
||||
}
|
||||
|
||||
String filePath(Object file) {
|
||||
return (file as File).relativePath ?? '';
|
||||
}
|
||||
|
||||
ImageProvider loadImageForFile(Object file, LottieImageAsset lottieImage) {
|
||||
throw UnimplementedError();
|
||||
}
|
@ -5,6 +5,7 @@ import 'frame_rate.dart';
|
||||
import 'lottie_delegates.dart';
|
||||
import 'lottie_drawable.dart';
|
||||
import 'options.dart';
|
||||
import 'render_cache.dart';
|
||||
import 'render_lottie.dart';
|
||||
|
||||
/// A widget that displays a [LottieDrawable] directly.
|
||||
@ -24,10 +25,9 @@ class RawLottie extends LeafRenderObjectWidget {
|
||||
this.fit,
|
||||
AlignmentGeometry? alignment,
|
||||
this.filterQuality,
|
||||
bool? enableRenderCache,
|
||||
this.renderCache,
|
||||
}) : progress = progress ?? 0.0,
|
||||
alignment = alignment ?? Alignment.center,
|
||||
enableRenderCache = enableRenderCache ?? false;
|
||||
alignment = alignment ?? Alignment.center;
|
||||
|
||||
/// The Lottie composition to display.
|
||||
final LottieComposition? composition;
|
||||
@ -80,26 +80,8 @@ class RawLottie extends LeafRenderObjectWidget {
|
||||
/// relative to text direction.
|
||||
final AlignmentGeometry alignment;
|
||||
|
||||
/// Opt-in a special render mode where the frames of the animation are
|
||||
/// lazily rendered in offscreen images.
|
||||
/// Subsequent runs of the animation will be very cheap to render.
|
||||
///
|
||||
/// This is useful is the animation is complex and can consume lot of energy
|
||||
/// from the battery.
|
||||
/// This is will trade an excessive CPU usage for an increase memory usage.
|
||||
///
|
||||
/// The render cache is managed internally and will release the memory once the
|
||||
/// animation is disposed. The cache is shared between all animations. If 2 `Lottie`
|
||||
/// widget are rendered at the same size, they will render only once.
|
||||
///
|
||||
/// Any change in the configuration of the animation (delegates, frame rate etc...)
|
||||
/// will clear the cache.
|
||||
/// Any change in the size will invalidate the cache. The cache use the final size
|
||||
/// visible on the screen (with all transforms applied).
|
||||
///
|
||||
/// In order to not exceed the memory limit of a device, the cache is constrained
|
||||
/// to maximum 50MB. After that, animations are not cached anymore.
|
||||
final bool enableRenderCache;
|
||||
/// {@macro lottie.renderCache}
|
||||
final RenderCache? renderCache;
|
||||
|
||||
final FilterQuality? filterQuality;
|
||||
|
||||
@ -117,7 +99,7 @@ class RawLottie extends LeafRenderObjectWidget {
|
||||
fit: fit,
|
||||
alignment: alignment,
|
||||
filterQuality: filterQuality,
|
||||
enableRenderCache: enableRenderCache,
|
||||
renderCache: renderCache,
|
||||
devicePixelRatio: MediaQuery.devicePixelRatioOf(context),
|
||||
);
|
||||
}
|
||||
@ -138,7 +120,7 @@ class RawLottie extends LeafRenderObjectWidget {
|
||||
..height = height
|
||||
..alignment = alignment
|
||||
..fit = fit
|
||||
..enableRenderCache = enableRenderCache
|
||||
..renderCache = renderCache
|
||||
..devicePixelRatio = MediaQuery.devicePixelRatioOf(context);
|
||||
}
|
||||
|
||||
|
@ -1,200 +1,34 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ui';
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart' show Colors;
|
||||
import 'package:flutter/material.dart' show RenderBox;
|
||||
import '../lottie.dart';
|
||||
import 'utils.dart';
|
||||
import 'render_cache/store_drawing.dart';
|
||||
import 'render_cache/store_raster.dart';
|
||||
|
||||
final globalRenderCache = RenderCache();
|
||||
abstract class RenderCache {
|
||||
/// The frames stored in the cache are fully rasterized. This is the most efficient
|
||||
/// to render but will use the most memory.
|
||||
/// This should only be used for very short and very small animations (final size on the screen).
|
||||
static const raster = RenderCacheRaster(maxMemory: 50000000);
|
||||
|
||||
class RenderCache {
|
||||
final _onUpdateController = StreamController<void>.broadcast();
|
||||
final entries = <CacheKey, RenderCacheEntry>{};
|
||||
final handles = <Object, RenderCacheHandle>{};
|
||||
/// The frames are stored as [dart:ui.Picture] in the cache.
|
||||
/// It will will spare the CPU work for each frame. The GPU work will be the same as without cache.
|
||||
static const drawingCommands = RenderCacheDrawing();
|
||||
|
||||
/// The maximum memory this cache will use (default 50MB)
|
||||
/// It should refuse to create new images if the size is exceeded.
|
||||
static const int defaultMaxMemory = 50000000;
|
||||
AnimationCache acquire(Object user);
|
||||
|
||||
int maxMemory = defaultMaxMemory;
|
||||
|
||||
bool enableDebugBackground = false;
|
||||
|
||||
Stream<void> get onUpdate => _onUpdateController.stream;
|
||||
|
||||
int get handleCount => handles.length;
|
||||
|
||||
int get entryCount => entries.length;
|
||||
|
||||
int get imageCount =>
|
||||
entries.values.map((e) => e.images.length).fold<int>(0, (a, b) => a + b);
|
||||
|
||||
int get totalMemory => entries.values
|
||||
.expand((e) => e.images.values)
|
||||
.fold(0, (a, b) => a + b.width * b.height);
|
||||
|
||||
bool canUseMemory(int newMemory) {
|
||||
return totalMemory + newMemory <= maxMemory;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
for (var entry in entries.values) {
|
||||
entry._clear();
|
||||
}
|
||||
_notifyUpdate();
|
||||
}
|
||||
|
||||
void _clearUnused() {
|
||||
for (var entry in entries.entries.toList()) {
|
||||
var key = entry.key;
|
||||
var cache = entry.value;
|
||||
|
||||
if (cache.handles.isEmpty) {
|
||||
cache.dispose();
|
||||
var found = entries.remove(key);
|
||||
assert(found == cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _notifyUpdate() {
|
||||
_onUpdateController.add(null);
|
||||
}
|
||||
|
||||
RenderCacheHandle acquire(Object user) {
|
||||
return handles[user] ??= RenderCacheHandle(this);
|
||||
}
|
||||
|
||||
void release(Object user) {
|
||||
var handle = handles.remove(user);
|
||||
if (handle?._currentEntry case var currentEntry?) {
|
||||
currentEntry.handles.remove(handle);
|
||||
_clearUnused();
|
||||
_notifyUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_onUpdateController.close();
|
||||
}
|
||||
void release(Object user);
|
||||
}
|
||||
|
||||
class RenderCacheHandle {
|
||||
final RenderCache _cache;
|
||||
RenderCacheEntry? _currentEntry;
|
||||
|
||||
RenderCacheHandle(this._cache);
|
||||
|
||||
RenderCacheEntry withKey(CacheKey key) {
|
||||
if (_currentEntry case var currentEntry? when currentEntry.key != key) {
|
||||
_currentEntry = null;
|
||||
currentEntry.handles.remove(this);
|
||||
_cache._clearUnused();
|
||||
}
|
||||
var entry = _cache.entries[key] ??= RenderCacheEntry(_cache, key);
|
||||
entry.handles.add(this);
|
||||
_currentEntry = entry;
|
||||
_cache._notifyUpdate();
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
var _debugId = 0;
|
||||
|
||||
class RenderCacheEntry {
|
||||
final RenderCache _cache;
|
||||
final CacheKey key;
|
||||
final handles = <RenderCacheHandle>{};
|
||||
final images = <double, Image>{};
|
||||
bool _isDisposed = false;
|
||||
final _id = _debugId++;
|
||||
|
||||
RenderCacheEntry(this._cache, this.key);
|
||||
|
||||
ui.Image? imageForProgress(double progress, void Function(Canvas) draw) {
|
||||
assert(!_isDisposed);
|
||||
|
||||
var existing = images[progress];
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
var size = key.size;
|
||||
var newImageSize = size.width.round() * size.height.round();
|
||||
if (!_cache.canUseMemory(newImageSize)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var recorder = PictureRecorder();
|
||||
var canvas = Canvas(recorder);
|
||||
if (_cache.enableDebugBackground) {
|
||||
_drawDebugBackground(canvas, size);
|
||||
}
|
||||
draw(canvas);
|
||||
var picture = recorder.endRecording();
|
||||
var image = picture.toImageSync(size.width.round(), size.height.round());
|
||||
images[progress] = image;
|
||||
picture.dispose();
|
||||
_cache._notifyUpdate();
|
||||
return image;
|
||||
}
|
||||
|
||||
void _drawDebugBackground(Canvas canvas, Size size) {
|
||||
var debugColors = [
|
||||
Colors.yellow,
|
||||
Colors.orange,
|
||||
Colors.red,
|
||||
Colors.blue,
|
||||
Colors.green,
|
||||
Colors.amber
|
||||
];
|
||||
var color = debugColors[_id % debugColors.length];
|
||||
canvas.drawRect(
|
||||
Offset.zero & size, Paint()..color = color.withOpacity(0.2));
|
||||
}
|
||||
|
||||
void _clear() {
|
||||
for (var image in images.values) {
|
||||
image.dispose();
|
||||
}
|
||||
images.clear();
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_isDisposed = true;
|
||||
_clear();
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
class CacheKey {
|
||||
final LottieComposition composition;
|
||||
final Size size;
|
||||
final List<Object?> config;
|
||||
final int delegates;
|
||||
|
||||
CacheKey({
|
||||
required this.composition,
|
||||
required this.size,
|
||||
required this.config,
|
||||
required this.delegates,
|
||||
}) : assert(size.width == size.width.toInt() &&
|
||||
size.height == size.height.toInt());
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(composition, size, Object.hashAll(config), delegates);
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
other is CacheKey &&
|
||||
other.composition == composition &&
|
||||
other.size == size &&
|
||||
const ListEquality<Object?>().equals(other.config, config) &&
|
||||
other.delegates == delegates;
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'CacheKey(${composition.hashCode}, $size, $config, $delegates)';
|
||||
abstract class AnimationCache {
|
||||
bool draw(
|
||||
LottieDrawable drawable,
|
||||
double progress,
|
||||
Canvas canvas, {
|
||||
required Offset destinationPosition,
|
||||
required Rect destinationRect,
|
||||
required Rect sourceRect,
|
||||
required Size sourceSize,
|
||||
required RenderBox renderBox,
|
||||
required double devicePixelRatio,
|
||||
});
|
||||
}
|
||||
|
36
lib/src/render_cache/key.dart
Normal file
36
lib/src/render_cache/key.dart
Normal file
@ -0,0 +1,36 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import '../composition.dart';
|
||||
import '../utils.dart';
|
||||
|
||||
@immutable
|
||||
class CacheKey {
|
||||
final LottieComposition composition;
|
||||
final Size size;
|
||||
final List<Object?> config;
|
||||
final int delegates;
|
||||
|
||||
CacheKey({
|
||||
required this.composition,
|
||||
required this.size,
|
||||
required this.config,
|
||||
required this.delegates,
|
||||
}) : assert(size.width == size.width.toInt() &&
|
||||
size.height == size.height.toInt());
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(composition, size, Object.hashAll(config), delegates);
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
other is CacheKey &&
|
||||
other.composition == composition &&
|
||||
other.size == size &&
|
||||
const ListEquality<Object?>().equals(other.config, config) &&
|
||||
other.delegates == delegates;
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'CacheKey(${composition.hashCode}, $size, $config, $delegates)';
|
||||
}
|
63
lib/src/render_cache/store.dart
Normal file
63
lib/src/render_cache/store.dart
Normal file
@ -0,0 +1,63 @@
|
||||
abstract class Store<TEntry extends CacheEntry<TCacheKey>, TCacheKey> {
|
||||
final entries = <TCacheKey, TEntry>{};
|
||||
final handles = <Object, Handle<TEntry, TCacheKey>>{};
|
||||
|
||||
bool shouldRemove(TEntry entry) => entry.handles.isEmpty;
|
||||
|
||||
TEntry createEntry(TCacheKey key);
|
||||
|
||||
void _clearUnused() {
|
||||
for (var entry in entries.entries.toList()) {
|
||||
var key = entry.key;
|
||||
var cache = entry.value;
|
||||
|
||||
if (shouldRemove(cache)) {
|
||||
cache.dispose();
|
||||
var found = entries.remove(key);
|
||||
assert(found == cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Handle<TEntry, TCacheKey> acquire(Object user) {
|
||||
var handle = handles[user] ??= Handle<TEntry, TCacheKey>(this);
|
||||
return handle;
|
||||
}
|
||||
|
||||
void release(Object user) {
|
||||
var handle = handles.remove(user);
|
||||
if (handle?._currentEntry case var currentEntry?) {
|
||||
var removed = currentEntry.handles.remove(handle);
|
||||
assert(removed);
|
||||
_clearUnused();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Handle<TEntry extends CacheEntry<TCacheKey>, TCacheKey> {
|
||||
final Store<TEntry, TCacheKey> _cache;
|
||||
TEntry? _currentEntry;
|
||||
|
||||
Handle(this._cache);
|
||||
|
||||
TEntry withKey(TCacheKey key) {
|
||||
if (_currentEntry case var currentEntry? when currentEntry.key != key) {
|
||||
_currentEntry = null;
|
||||
currentEntry.handles.remove(this);
|
||||
_cache._clearUnused();
|
||||
}
|
||||
var entry = _cache.entries[key] ??= _cache.createEntry(key);
|
||||
entry.handles.add(this);
|
||||
_currentEntry = entry;
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
abstract base class CacheEntry<TCacheKey> {
|
||||
final TCacheKey key;
|
||||
final handles = <Handle>{};
|
||||
|
||||
CacheEntry(this.key);
|
||||
|
||||
void dispose();
|
||||
}
|
131
lib/src/render_cache/store_drawing.dart
Normal file
131
lib/src/render_cache/store_drawing.dart
Normal file
@ -0,0 +1,131 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import '../lottie_drawable.dart';
|
||||
import '../render_cache.dart';
|
||||
import 'key.dart';
|
||||
import 'store.dart';
|
||||
|
||||
final _stores = Expando<DrawingStore>();
|
||||
|
||||
class RenderCacheDrawing implements RenderCache {
|
||||
const RenderCacheDrawing();
|
||||
|
||||
@override
|
||||
AnimationCache acquire(Object user) {
|
||||
var handle = store.acquire(user);
|
||||
return DrawingAnimationCache(handle);
|
||||
}
|
||||
|
||||
@override
|
||||
void release(Object user) {
|
||||
store.release(user);
|
||||
}
|
||||
|
||||
DrawingStore get store => _stores[this] ??= DrawingStore();
|
||||
}
|
||||
|
||||
class DrawingAnimationCache extends AnimationCache {
|
||||
final Handle<DrawingEntry, CacheKey> handle;
|
||||
|
||||
DrawingAnimationCache(this.handle);
|
||||
|
||||
@override
|
||||
bool draw(
|
||||
LottieDrawable drawable,
|
||||
double progress,
|
||||
Canvas canvas, {
|
||||
required Offset destinationPosition,
|
||||
required Rect destinationRect,
|
||||
required Rect sourceRect,
|
||||
required Size sourceSize,
|
||||
required RenderBox renderBox,
|
||||
required double devicePixelRatio,
|
||||
}) {
|
||||
var key = CacheKey(
|
||||
composition: drawable.composition,
|
||||
size: Size.zero,
|
||||
config: drawable.configHash(),
|
||||
delegates: drawable.delegatesHash());
|
||||
var entry = handle.withKey(key);
|
||||
|
||||
return entry.draw(
|
||||
drawable,
|
||||
progress,
|
||||
canvas,
|
||||
destinationPosition: destinationPosition,
|
||||
destinationRect: destinationRect,
|
||||
sourceRect: sourceRect,
|
||||
sourceSize: sourceSize,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DrawingStore extends Store<DrawingEntry, CacheKey> {
|
||||
@override
|
||||
DrawingEntry createEntry(CacheKey key) {
|
||||
return DrawingEntry(this, key);
|
||||
}
|
||||
}
|
||||
|
||||
base class DrawingEntry extends CacheEntry<CacheKey> {
|
||||
final DrawingStore store;
|
||||
final pictures = <double, Picture>{};
|
||||
|
||||
DrawingEntry(this.store, super.key);
|
||||
|
||||
Picture _record(void Function(Canvas) draw) {
|
||||
var recorder = PictureRecorder();
|
||||
var canvas = Canvas(recorder);
|
||||
draw(canvas);
|
||||
return recorder.endRecording();
|
||||
}
|
||||
|
||||
Picture? _pictureForProgress(double progress, void Function(Canvas) draw) {
|
||||
var existing = pictures[progress];
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
var picture = _record(draw);
|
||||
pictures[progress] = picture;
|
||||
return picture;
|
||||
}
|
||||
|
||||
final _matrix = Matrix4.identity();
|
||||
|
||||
bool draw(
|
||||
LottieDrawable drawable,
|
||||
double progress,
|
||||
Canvas canvas, {
|
||||
required Offset destinationPosition,
|
||||
required Rect destinationRect,
|
||||
required Rect sourceRect,
|
||||
required Size sourceSize,
|
||||
}) {
|
||||
var cachedImage = _pictureForProgress(progress, (cacheCanvas) {
|
||||
drawable.compositionLayer.draw(cacheCanvas, _matrix, parentAlpha: 255);
|
||||
});
|
||||
if (cachedImage != null) {
|
||||
var destinationSize = destinationRect.size;
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(destinationRect.left, destinationRect.top);
|
||||
canvas.scale(destinationSize.width / sourceRect.width,
|
||||
destinationSize.height / sourceRect.height);
|
||||
canvas.drawPicture(cachedImage);
|
||||
canvas.restore();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
for (var picture in pictures.values) {
|
||||
picture.dispose();
|
||||
}
|
||||
pictures.clear();
|
||||
}
|
||||
}
|
171
lib/src/render_cache/store_raster.dart
Normal file
171
lib/src/render_cache/store_raster.dart
Normal file
@ -0,0 +1,171 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import '../lottie_drawable.dart';
|
||||
import '../render_cache.dart';
|
||||
import 'key.dart';
|
||||
import 'store.dart';
|
||||
|
||||
final _stores = Expando<RasterStore>();
|
||||
|
||||
class RenderCacheRaster implements RenderCache {
|
||||
final int maxMemory;
|
||||
|
||||
const RenderCacheRaster({required this.maxMemory});
|
||||
|
||||
@override
|
||||
AnimationCache acquire(Object user) {
|
||||
var handle = store.acquire(user);
|
||||
return RasterAnimationCache(handle);
|
||||
}
|
||||
|
||||
@override
|
||||
void release(Object user) {
|
||||
store.release(user);
|
||||
}
|
||||
|
||||
RasterStore get store => _stores[this] ??= RasterStore(maxMemory);
|
||||
}
|
||||
|
||||
class RasterAnimationCache extends AnimationCache {
|
||||
final Handle<RasterEntry, CacheKey> handle;
|
||||
|
||||
RasterAnimationCache(this.handle);
|
||||
|
||||
@override
|
||||
bool draw(
|
||||
LottieDrawable drawable,
|
||||
double progress,
|
||||
Canvas canvas, {
|
||||
required Offset destinationPosition,
|
||||
required Rect destinationRect,
|
||||
required Rect sourceRect,
|
||||
required Size sourceSize,
|
||||
required RenderBox renderBox,
|
||||
required double devicePixelRatio,
|
||||
}) {
|
||||
var rect = Rect.fromPoints(renderBox.localToGlobal(destinationPosition),
|
||||
renderBox.localToGlobal(destinationRect.bottomRight));
|
||||
var cacheImageSize = Size(
|
||||
(rect.size.width * devicePixelRatio).roundToDouble(),
|
||||
(rect.size.height * devicePixelRatio).roundToDouble());
|
||||
|
||||
var key = CacheKey(
|
||||
composition: drawable.composition,
|
||||
size: cacheImageSize,
|
||||
config: drawable.configHash(),
|
||||
delegates: drawable.delegatesHash());
|
||||
var entry = handle.withKey(key);
|
||||
|
||||
return entry.draw(
|
||||
drawable,
|
||||
progress,
|
||||
canvas,
|
||||
destinationPosition: destinationPosition,
|
||||
destinationRect: destinationRect,
|
||||
sourceSize: sourceSize,
|
||||
sourceRect: sourceRect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RasterStore extends Store<RasterEntry, CacheKey> {
|
||||
final int maxMemory;
|
||||
|
||||
RasterStore(this.maxMemory);
|
||||
|
||||
int get totalMemory => entries.values.fold(0, (a, b) => a + b.currentMemory);
|
||||
|
||||
int get imageCount => entries.values.expand((e) => e.images.values).length;
|
||||
|
||||
void clear() {
|
||||
for (var entry in entries.values) {
|
||||
entry.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
RasterEntry createEntry(CacheKey key) {
|
||||
return RasterEntry(this, key);
|
||||
}
|
||||
|
||||
bool canUseMemory(int newMemory) {
|
||||
return totalMemory + newMemory <= maxMemory;
|
||||
}
|
||||
}
|
||||
|
||||
base class RasterEntry extends CacheEntry<CacheKey> {
|
||||
final RasterStore store;
|
||||
final images = <double, Image>{};
|
||||
int currentMemory = 0;
|
||||
|
||||
RasterEntry(this.store, super.key);
|
||||
|
||||
Picture _record(void Function(Canvas) draw) {
|
||||
var recorder = PictureRecorder();
|
||||
var canvas = Canvas(recorder);
|
||||
draw(canvas);
|
||||
return recorder.endRecording();
|
||||
}
|
||||
|
||||
Image? imageForProgress(double progress, void Function(Canvas) draw) {
|
||||
var existing = images[progress];
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
var size = key.size;
|
||||
var newImageSize = size.width.round() * size.height.round();
|
||||
if (!store.canUseMemory(newImageSize)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var picture = _record(draw);
|
||||
var image = picture.toImageSync(size.width.round(), size.height.round());
|
||||
picture.dispose();
|
||||
images[progress] = image;
|
||||
currentMemory += size.width.round() * size.height.round();
|
||||
return image;
|
||||
}
|
||||
|
||||
final _normalPaint = Paint();
|
||||
final _matrix = Matrix4.identity();
|
||||
|
||||
bool draw(
|
||||
LottieDrawable drawable,
|
||||
double progress,
|
||||
Canvas canvas, {
|
||||
required Offset destinationPosition,
|
||||
required Rect destinationRect,
|
||||
required Size sourceSize,
|
||||
required Rect sourceRect,
|
||||
}) {
|
||||
var cacheImageSize = key.size;
|
||||
|
||||
var cachedImage = imageForProgress(progress, (cacheCanvas) {
|
||||
_matrix.setIdentity();
|
||||
_matrix.scale(cacheImageSize.width / sourceSize.width,
|
||||
cacheImageSize.height / sourceSize.height);
|
||||
drawable.compositionLayer.draw(cacheCanvas, _matrix, parentAlpha: 255);
|
||||
});
|
||||
if (cachedImage != null) {
|
||||
canvas.drawImageRect(cachedImage, Offset.zero & cacheImageSize,
|
||||
destinationRect, _normalPaint);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
for (var image in images.values) {
|
||||
image.dispose();
|
||||
}
|
||||
images.clear();
|
||||
currentMemory = 0;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
clear();
|
||||
}
|
||||
}
|
@ -22,13 +22,13 @@ class RenderLottie extends RenderBox {
|
||||
BoxFit? fit,
|
||||
AlignmentGeometry alignment = Alignment.center,
|
||||
FilterQuality? filterQuality,
|
||||
bool enableRenderCache = false,
|
||||
RenderCache? renderCache,
|
||||
required double devicePixelRatio,
|
||||
}) : assert(progress >= 0.0 && progress <= 1.0),
|
||||
assert(
|
||||
!enableRenderCache || frameRate != FrameRate.max,
|
||||
'FrameRate.max cannot be used with enableRenderCache. '
|
||||
'You should use a specific frame rate. e.g. FrameRate(60)'),
|
||||
renderCache == null || frameRate != FrameRate.max,
|
||||
'FrameRate.max cannot be used with a RenderCache '
|
||||
'Use a specific frame rate. e.g. FrameRate(60)'),
|
||||
_drawable = composition != null
|
||||
? (LottieDrawable(composition, frameRate: frameRate)
|
||||
..setProgress(progress)
|
||||
@ -42,7 +42,7 @@ class RenderLottie extends RenderBox {
|
||||
_height = height,
|
||||
_fit = fit,
|
||||
_alignment = alignment,
|
||||
_enableRenderCache = enableRenderCache,
|
||||
_renderCache = renderCache,
|
||||
_devicePixelRatio = devicePixelRatio;
|
||||
|
||||
/// The lottie composition to display.
|
||||
@ -161,13 +161,14 @@ class RenderLottie extends RenderBox {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
bool get enableRenderCache => _enableRenderCache;
|
||||
bool _enableRenderCache;
|
||||
set enableRenderCache(bool value) {
|
||||
if (value == _enableRenderCache) {
|
||||
RenderCache? get renderCache => _renderCache;
|
||||
RenderCache? _renderCache;
|
||||
set renderCache(RenderCache? value) {
|
||||
if (value == _renderCache) {
|
||||
return;
|
||||
}
|
||||
_enableRenderCache = value;
|
||||
_renderCache?.release(this);
|
||||
_renderCache = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
@ -256,14 +257,12 @@ class RenderLottie extends RenderBox {
|
||||
if (_drawable == null) return;
|
||||
|
||||
RenderCacheContext? cacheContext;
|
||||
if (enableRenderCache) {
|
||||
if (_renderCache case var renderCache?) {
|
||||
cacheContext = RenderCacheContext(
|
||||
handle: globalRenderCache.acquire(this),
|
||||
cache: renderCache.acquire(this),
|
||||
devicePixelRatio: _devicePixelRatio,
|
||||
localToGlobal: localToGlobal,
|
||||
renderBox: this,
|
||||
);
|
||||
} else {
|
||||
globalRenderCache.release(this);
|
||||
}
|
||||
|
||||
_drawable!.draw(
|
||||
@ -290,7 +289,7 @@ class RenderLottie extends RenderBox {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
globalRenderCache.release(this);
|
||||
_renderCache?.release(this);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'dart:math';
|
||||
import 'dart:ui';
|
||||
import 'path_factory.dart';
|
||||
|
||||
Path dashPath(
|
||||
Path source, {
|
||||
@ -10,7 +9,7 @@ Path dashPath(
|
||||
assert(intervals.length >= 2);
|
||||
phase ??= 0;
|
||||
|
||||
var dest = PathFactory.create();
|
||||
var dest = Path();
|
||||
for (final metric in source.computeMetrics()) {
|
||||
for (var dash in _dashes(metric.length, intervals, phase)) {
|
||||
dest.addPath(metric.extractPath(dash.left, dash.right), Offset.zero);
|
||||
|
@ -26,18 +26,25 @@ class GammaEvaluator {
|
||||
}
|
||||
|
||||
static Color evaluate(double fraction, Color startColor, Color endColor) {
|
||||
// Fast return in case start and end is the same
|
||||
// or if fraction is at start/end or out of [0,1] bounds
|
||||
if (startColor == endColor) {
|
||||
return startColor;
|
||||
} else if (fraction <= 0) {
|
||||
return startColor;
|
||||
} else if (fraction >= 1) {
|
||||
return endColor;
|
||||
}
|
||||
var startA = startColor.alpha / 255.0;
|
||||
var startR = startColor.red / 255.0;
|
||||
var startG = startColor.green / 255.0;
|
||||
var startB = startColor.blue / 255.0;
|
||||
|
||||
var endA = endColor.alpha / 255.0;
|
||||
var endR = endColor.red / 255.0;
|
||||
var endG = endColor.green / 255.0;
|
||||
var endB = endColor.blue / 255.0;
|
||||
var startA = startColor.a;
|
||||
var startR = startColor.r;
|
||||
var startG = startColor.g;
|
||||
var startB = startColor.b;
|
||||
|
||||
var endA = endColor.a;
|
||||
var endR = endColor.r;
|
||||
var endG = endColor.g;
|
||||
var endB = endColor.b;
|
||||
|
||||
// convert from sRGB to linear
|
||||
startR = _eocfSRgb(startR);
|
||||
|
@ -96,7 +96,7 @@ class MiscUtils {
|
||||
/// it to the accumulator list.
|
||||
///
|
||||
/// Any {@link KeyPathElementContent} should call through to this as its implementation of
|
||||
/// {@link KeyPathElementContent#resolveKeyPath(KeyPath, int, List, KeyPath)}.
|
||||
/// {KeyPathElementContent#resolveKeyPath(KeyPath, int, List, KeyPath)}.
|
||||
static void resolveKeyPath(
|
||||
KeyPath keyPath,
|
||||
int depth,
|
||||
|
@ -1,7 +0,0 @@
|
||||
import 'dart:ui';
|
||||
|
||||
class PathFactory {
|
||||
static Path create() {
|
||||
return Path();
|
||||
}
|
||||
}
|
@ -1,17 +1,33 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'path_factory.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class PathInterpolator extends Curve {
|
||||
/// Governs the accuracy of the approximation of the {@link Path}.
|
||||
static const double _precision = 0.002;
|
||||
|
||||
final List<double> _mX;
|
||||
final List<double> _mY;
|
||||
late final List<double> _mX;
|
||||
late final List<double> _mY;
|
||||
bool _isInitialized = false;
|
||||
|
||||
const PathInterpolator._(this._mX, this._mY);
|
||||
final double controlX1, controlY1, controlX2, controlY2;
|
||||
|
||||
PathInterpolator.cubic(
|
||||
this.controlX1, this.controlY1, this.controlX2, this.controlY2);
|
||||
|
||||
void _ensureInitialized() {
|
||||
if (_isInitialized) {
|
||||
return;
|
||||
}
|
||||
_initialize();
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
void _initialize() {
|
||||
final path = Path();
|
||||
path.moveTo(0.0, 0.0);
|
||||
path.cubicTo(controlX1, controlY1, controlX2, controlY2, 1.0, 1.0);
|
||||
|
||||
factory PathInterpolator(Path path) {
|
||||
final pathMeasure = path.computeMetrics().toList().first;
|
||||
|
||||
final pathLength = pathMeasure.length;
|
||||
@ -27,18 +43,13 @@ class PathInterpolator extends Curve {
|
||||
mX[i] = tangent.position.dx;
|
||||
mY[i] = tangent.position.dy;
|
||||
}
|
||||
|
||||
return PathInterpolator._(mX, mY);
|
||||
}
|
||||
|
||||
factory PathInterpolator.cubic(
|
||||
double controlX1, double controlY1, double controlX2, double controlY2) {
|
||||
return PathInterpolator(
|
||||
_createCubic(controlX1, controlY1, controlX2, controlY2));
|
||||
_mX = mX;
|
||||
_mY = mY;
|
||||
}
|
||||
|
||||
@override
|
||||
double transform(double t) {
|
||||
_ensureInitialized();
|
||||
if (t <= 0.0) {
|
||||
return 0.0;
|
||||
} else if (t >= 1.0) {
|
||||
@ -70,12 +81,4 @@ class PathInterpolator extends Curve {
|
||||
|
||||
return startY + (fraction * (endY - startY));
|
||||
}
|
||||
|
||||
static Path _createCubic(
|
||||
double controlX1, double controlY1, double controlX2, double controlY2) {
|
||||
final path = PathFactory.create();
|
||||
path.moveTo(0.0, 0.0);
|
||||
path.cubicTo(controlX1, controlY1, controlX2, controlY2, 1.0, 1.0);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,11 @@ import '../animation/content/trim_path_content.dart';
|
||||
import '../l.dart';
|
||||
import '../utils.dart';
|
||||
import 'misc.dart';
|
||||
import 'path_factory.dart';
|
||||
|
||||
class Utils {
|
||||
static Path createPath(
|
||||
Offset startPoint, Offset endPoint, Offset? cp1, Offset? cp2) {
|
||||
var path = PathFactory.create();
|
||||
var path = Path();
|
||||
path.moveTo(startPoint.dx, startPoint.dy);
|
||||
|
||||
if (cp1 != null &&
|
||||
|
@ -331,7 +331,7 @@ class ResolvedValueDelegate<T> {
|
||||
/// to multiple contents. In that case, the callbacks's value will apply to all of them.
|
||||
/// <p>
|
||||
/// Internally, this will check if the {@link KeyPath} has already been resolved with
|
||||
/// {@link #resolveKeyPath(KeyPath)} and will resolve it if it hasn't.
|
||||
/// {#resolveKeyPath(KeyPath)} and will resolve it if it hasn't.
|
||||
void addValueCallback(LottieDrawable drawable) {
|
||||
var invalidate = false;
|
||||
if (valueDelegate.keyPath.isEmpty) {
|
||||
|
183
pubspec.lock
183
pubspec.lock
@ -5,34 +5,39 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051
|
||||
sha256: "88399e291da5f7e889359681a8f64b18c5123e03576b01f32a6a276611e511c3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "64.0.0"
|
||||
version: "78.0.0"
|
||||
_macros:
|
||||
dependency: transitive
|
||||
description: dart
|
||||
source: sdk
|
||||
version: "0.3.3"
|
||||
analyzer:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893"
|
||||
sha256: "62899ef43d0b962b056ed2ebac6b47ec76ffd003d5f7c4e4dc870afe63188e33"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
version: "7.1.0"
|
||||
archive:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: archive
|
||||
sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b"
|
||||
sha256: "6199c74e3db4fbfbd04f66d739e72fe11c8a8957d5f219f1f4482dbde6420b5a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.9"
|
||||
version: "4.0.2"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
version: "2.6.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -69,34 +74,34 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
version: "1.19.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
version: "3.1.2"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
version: "3.0.6"
|
||||
dart_style:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: dart_style
|
||||
sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368"
|
||||
sha256: "27eb0ae77836989a3bc541ce55595e8ceee0992807f14511552a898ddd0d88ac"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.4"
|
||||
version: "3.0.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -105,14 +110,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
version: "7.0.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -122,10 +135,10 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
|
||||
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
version: "5.0.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@ -139,83 +152,123 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
js:
|
||||
dependency: transitive
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
name: http
|
||||
sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
version: "1.2.2"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.2"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.7"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.8"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
|
||||
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
version: "5.1.1"
|
||||
macros:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: macros
|
||||
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.3-main.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16"
|
||||
version: "0.12.16+1"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.0"
|
||||
version: "0.11.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
version: "1.15.0"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
||||
sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.1"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.3"
|
||||
pointycastle:
|
||||
version: "1.9.0"
|
||||
posix:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
|
||||
name: posix
|
||||
sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.7.3"
|
||||
version: "6.0.1"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
||||
sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
version: "2.1.5"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
version: "0.0.0"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -228,10 +281,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
version: "1.12.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -244,10 +297,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -260,18 +313,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
version: "0.7.3"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
version: "1.4.0"
|
||||
vector_math:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -280,30 +333,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||
sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.1"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "1.1.0"
|
||||
yaml:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.2.0 <4.0.0"
|
||||
flutter: ">=3.16.0"
|
||||
dart: ">=3.6.0 <4.0.0"
|
||||
flutter: ">=3.27.0"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user