mirror of
https://github.com/xvrh/lottie-flutter.git
synced 2025-08-06 16:39:36 +08:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
d8f5b872ef | |||
bc3eb4621b | |||
08d7da747a | |||
b2ebd2058d | |||
2979b62dc0 | |||
340f0d2f27 | |||
34fef26eb2 | |||
89c62122bf |
13
.github/workflows/analyze-and-test.yaml
vendored
13
.github/workflows/analyze-and-test.yaml
vendored
@ -10,11 +10,11 @@ jobs:
|
||||
name: Flutter analyze
|
||||
strategy:
|
||||
matrix:
|
||||
flutter: ['beta']
|
||||
flutter: ['stable']
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: subosito/flutter-action@v1
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: ${{ matrix.flutter }}
|
||||
- run: flutter doctor
|
||||
@ -22,8 +22,8 @@ jobs:
|
||||
- run: flutter pub get
|
||||
working-directory: example
|
||||
- run: flutter analyze
|
||||
- run: flutter test test # https://github.com/flutter/flutter/issues/20907
|
||||
- run: flutter test test
|
||||
- run: flutter test
|
||||
- run: flutter test
|
||||
working-directory: example
|
||||
- run: flutter pub run tool/prepare_submit.dart
|
||||
- name: "check for uncommitted changes"
|
||||
@ -38,10 +38,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: subosito/flutter-action@v1
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: 'beta'
|
||||
- run: flutter config --enable-web
|
||||
channel: 'stable'
|
||||
- run: flutter precache web
|
||||
- run: flutter pub get
|
||||
working-directory: example
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,6 +3,7 @@ _*
|
||||
|
||||
!.gitignore
|
||||
!.github
|
||||
!.pubignore
|
||||
|
||||
**/failures/*.png
|
||||
|
||||
|
15
.pubignore
Normal file
15
.pubignore
Normal file
@ -0,0 +1,15 @@
|
||||
.dart_tool/
|
||||
.packages
|
||||
build/
|
||||
doc/api/
|
||||
*.iml
|
||||
_*
|
||||
.*
|
||||
**/failures/*.png
|
||||
test/golden/
|
||||
test/goldens/
|
||||
example/assets/
|
||||
example/android/
|
||||
example/ios/
|
||||
example/macos/
|
||||
example/web/
|
68
CHANGELOG.md
68
CHANGELOG.md
@ -1,3 +1,71 @@
|
||||
## [1.4.0]
|
||||
- Added `filterQuality` property to control the performance vs quality trade-off to use when drawing images
|
||||
|
||||
## [1.3.0]
|
||||
- Added support for rounded corners on shapes and rects
|
||||
- Add support for text in dynamic properties (`ValueDelegate`)
|
||||
|
||||
Example:
|
||||
|
||||
```dart
|
||||
Lottie.asset(
|
||||
'assets/DynamicText.json',
|
||||
delegates: LottieDelegates(values: [
|
||||
ValueDelegate.text(
|
||||
['Text layer'], // The path to the text element to change
|
||||
value: 'The new text',
|
||||
),
|
||||
]),
|
||||
)
|
||||
```
|
||||
|
||||
- Improve stroke with offset
|
||||
- Add support for reversed polystar paths
|
||||
- Enforce order of operations to avoid rounding errors
|
||||
|
||||
## [1.2.2]
|
||||
- Internal maintenance: fix lints for Flutter 2.10
|
||||
|
||||
## [1.2.1]
|
||||
- Fix: Revert Cubic to `PathInterpolator.cubic`
|
||||
|
||||
## [1.2.0]
|
||||
- Add support for gaussian blurs.
|
||||
|
||||
Example to blur some elements dynamically:
|
||||
|
||||
```dart
|
||||
Lottie.asset(
|
||||
'assets/AndroidWave.json',
|
||||
delegates: LottieDelegates(values: [
|
||||
ValueDelegate.blurRadius(
|
||||
['**'], // The path to the element to blur
|
||||
value: 20,
|
||||
),
|
||||
]),
|
||||
)
|
||||
```
|
||||
|
||||
- Add support for drop shadows.
|
||||
|
||||
Example to add a shadow dynamically:
|
||||
```dart
|
||||
Lottie.asset(
|
||||
'assets/animation.json',
|
||||
delegates: LottieDelegates(values: [
|
||||
ValueDelegate.dropShadow(
|
||||
['**'], // The path to the elements with shadow
|
||||
value: const DropShadow(
|
||||
color: Colors.blue,
|
||||
direction: 140,
|
||||
distance: 60,
|
||||
radius: 10,
|
||||
),
|
||||
),
|
||||
]),
|
||||
)
|
||||
```
|
||||
|
||||
## [1.1.0]
|
||||
- Add `errorBuilder` callback to provide an alternative widget in case an error occurs during loading.
|
||||
```dart
|
||||
|
@ -64,7 +64,7 @@ class MyApp extends StatefulWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MyAppState createState() => _MyAppState();
|
||||
State<MyApp> createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||
@ -139,7 +139,7 @@ class MyWidget extends StatefulWidget {
|
||||
const MyWidget({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MyWidgetState createState() => _MyWidgetState();
|
||||
State<MyWidget> createState() => _MyWidgetState();
|
||||
}
|
||||
|
||||
class _MyWidgetState extends State<MyWidget> {
|
||||
|
@ -6,7 +6,6 @@ analyzer:
|
||||
linter:
|
||||
rules:
|
||||
avoid_print: false
|
||||
unnecessary_overrides: false # remove when mockito is fixed
|
||||
|
||||
always_declare_return_types: true
|
||||
avoid_dynamic_calls: true
|
||||
|
6
example/android/.gitignore
vendored
6
example/android/.gitignore
vendored
@ -5,3 +5,9 @@ gradle-wrapper.jar
|
||||
/gradlew.bat
|
||||
/local.properties
|
||||
GeneratedPluginRegistrant.java
|
||||
|
||||
# Remember to never publicly share your keystore.
|
||||
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
|
||||
key.properties
|
||||
**/*.keystore
|
||||
**/*.jks
|
||||
|
@ -8,7 +8,7 @@ if (localPropertiesFile.exists()) {
|
||||
|
||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||
if (flutterRoot == null) {
|
||||
throw new Exception("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
}
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||
@ -26,23 +26,28 @@ apply plugin: 'kotlin-android'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
compileSdkVersion flutter.compileSdkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.github.xvrh.lottie.sample"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "com.github.xvrh.lottie.example"
|
||||
minSdkVersion flutter.minSdkVersion
|
||||
targetSdkVersion flutter.targetSdkVersion
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@ -60,7 +65,4 @@ flutter {
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.github.xvrh.lottie.sample">
|
||||
package="com.github.xvrh.lottie.example">
|
||||
<!-- Flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
|
@ -1,21 +1,25 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.github.xvrh.lottie.sample">
|
||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||
In most cases you can leave this as-is, but you if you want to provide
|
||||
additional functionality it is fine to subclass or reimplement
|
||||
FlutterApplication and put your custom class here. -->
|
||||
<application
|
||||
android:name="io.flutter.app.FlutterApplication"
|
||||
package="com.github.xvrh.lottie.example">
|
||||
<application
|
||||
android:label="example"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
@ -0,0 +1,6 @@
|
||||
package com.github.xvrh.lottie.example
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.github.xvrh.lottie.sample
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
|
||||
GeneratedPluginRegistrant.registerWith(flutterEngine);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="?android:colorBackground" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
18
example/android/app/src/main/res/values-night/styles.xml
Normal file
18
example/android/app/src/main/res/values-night/styles.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
Flutter draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
@ -1,8 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
Flutter draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.github.xvrh.lottie.sample">
|
||||
package="com.github.xvrh.lottie.example">
|
||||
<!-- Flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
|
@ -1,12 +1,12 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.50'
|
||||
ext.kotlin_version = '1.6.10'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.0'
|
||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
@ -14,7 +14,7 @@ buildscript {
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
||||
|
@ -1,15 +1,11 @@
|
||||
include ':app'
|
||||
|
||||
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
|
||||
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
|
||||
def properties = new Properties()
|
||||
|
||||
def plugins = new Properties()
|
||||
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
|
||||
if (pluginsFile.exists()) {
|
||||
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
|
||||
}
|
||||
assert localPropertiesFile.exists()
|
||||
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
|
||||
|
||||
plugins.each { name, path ->
|
||||
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
|
||||
include ":$name"
|
||||
project(":$name").projectDir = pluginDirectory
|
||||
}
|
||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
|
||||
|
1
example/assets/Tests/AnimatedShadow.json
Normal file
1
example/assets/Tests/AnimatedShadow.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":181.000007372281,"w":375,"h":375,"nm":"Square","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,187.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow2","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0,0,0,1]},{"t":151.000006150356,"s":[0,0.371857702732,1,1]}],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[127.5]},{"t":151.000006150356,"s":[127.5]}],"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":151.000006150356,"s":[360]}],"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[10]},{"t":151.000006150356,"s":[15]}],"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[20]},{"t":151.000006150356,"s":[50]}],"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[217.641,217.641],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.68,-1.68],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":184.000007494474,"st":0,"bm":0}],"markers":[]}
|
1
example/assets/Tests/FillBlur.json
Normal file
1
example/assets/Tests/FillBlur.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":121.000004928431,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":29,"nm":"Gaussian Blur2","np":5,"mn":"ADBE Gaussian Blur 2","ix":1,"en":1,"ef":[{"ty":0,"nm":"Blurriness","mn":"ADBE Gaussian Blur 2-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24.00000097754,"s":[120.7]}],"ix":1}},{"ty":7,"nm":"Blur Dimensions","mn":"ADBE Gaussian Blur 2-0002","ix":2,"v":{"a":0,"k":1,"ix":2}},{"ty":7,"nm":"Repeat Edge Pixels","mn":"ADBE Gaussian Blur 2-0003","ix":3,"v":{"a":0,"k":0,"ix":3}}]},{"ty":5,"nm":"Bulge","np":9,"mn":"ADBE Bulge","ix":2,"en":1,"ef":[{"ty":0,"nm":"Horizontal Radius","mn":"ADBE Bulge-0001","ix":1,"v":{"a":0,"k":50,"ix":1}},{"ty":0,"nm":"Vertical Radius","mn":"ADBE Bulge-0002","ix":2,"v":{"a":0,"k":50,"ix":2}},{"ty":3,"nm":"Bulge Center","mn":"ADBE Bulge-0003","ix":3,"v":{"a":0,"k":[200,200],"ix":3}},{"ty":0,"nm":"Bulge Height","mn":"ADBE Bulge-0004","ix":4,"v":{"a":0,"k":1,"ix":4}},{"ty":0,"nm":"Taper Radius","mn":"ADBE Bulge-0005","ix":5,"v":{"a":0,"k":0,"ix":5}},{"ty":7,"nm":"Antialiasing (Best Qual Only)","mn":"ADBE Bulge-0006","ix":6,"v":{"a":0,"k":1,"ix":6}},{"ty":7,"nm":"Pinning","mn":"ADBE Bulge-0007","ix":7,"v":{"a":0,"k":0,"ix":7}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[274.975,274.975],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.513,7.487],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":121.000004928431,"st":0,"bm":0}],"markers":[]}
|
1
example/assets/Tests/GradientFillBlur.json
Normal file
1
example/assets/Tests/GradientFillBlur.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":121.000004928431,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":29,"nm":"Gaussian Blur2","np":5,"mn":"ADBE Gaussian Blur 2","ix":1,"en":1,"ef":[{"ty":0,"nm":"Blurriness","mn":"ADBE Gaussian Blur 2-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24.00000097754,"s":[120.7]}],"ix":1}},{"ty":7,"nm":"Blur Dimensions","mn":"ADBE Gaussian Blur 2-0002","ix":2,"v":{"a":0,"k":1,"ix":2}},{"ty":7,"nm":"Repeat Edge Pixels","mn":"ADBE Gaussian Blur 2-0003","ix":3,"v":{"a":0,"k":0,"ix":3}}]},{"ty":5,"nm":"Bulge","np":9,"mn":"ADBE Bulge","ix":2,"en":1,"ef":[{"ty":0,"nm":"Horizontal Radius","mn":"ADBE Bulge-0001","ix":1,"v":{"a":0,"k":50,"ix":1}},{"ty":0,"nm":"Vertical Radius","mn":"ADBE Bulge-0002","ix":2,"v":{"a":0,"k":50,"ix":2}},{"ty":3,"nm":"Bulge Center","mn":"ADBE Bulge-0003","ix":3,"v":{"a":0,"k":[200,200],"ix":3}},{"ty":0,"nm":"Bulge Height","mn":"ADBE Bulge-0004","ix":4,"v":{"a":0,"k":1,"ix":4}},{"ty":0,"nm":"Taper Radius","mn":"ADBE Bulge-0005","ix":5,"v":{"a":0,"k":0,"ix":5}},{"ty":7,"nm":"Antialiasing (Best Qual Only)","mn":"ADBE Bulge-0006","ix":6,"v":{"a":0,"k":1,"ix":6}},{"ty":7,"nm":"Pinning","mn":"ADBE Bulge-0007","ix":7,"v":{"a":0,"k":0,"ix":7}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[274.975,274.975],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.513,7.487],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,0,0,0.5,0.505,0,0.5,1,0.009,0,1],"ix":9}},"s":{"a":0,"k":[-125,0],"ix":5},"e":{"a":0,"k":[100,0],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false}],"ip":0,"op":121.000004928431,"st":0,"bm":0}],"markers":[]}
|
3512
example/assets/Tests/GradientOneColor.json
Normal file
3512
example/assets/Tests/GradientOneColor.json
Normal file
File diff suppressed because it is too large
Load Diff
1
example/assets/Tests/GradientStrokeBlur.json
Normal file
1
example/assets/Tests/GradientStrokeBlur.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":121.000004928431,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":29,"nm":"Gaussian Blur2","np":5,"mn":"ADBE Gaussian Blur 2","ix":1,"en":1,"ef":[{"ty":0,"nm":"Blurriness","mn":"ADBE Gaussian Blur 2-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24.00000097754,"s":[120.7]}],"ix":1}},{"ty":7,"nm":"Blur Dimensions","mn":"ADBE Gaussian Blur 2-0002","ix":2,"v":{"a":0,"k":1,"ix":2}},{"ty":7,"nm":"Repeat Edge Pixels","mn":"ADBE Gaussian Blur 2-0003","ix":3,"v":{"a":0,"k":0,"ix":3}}]},{"ty":5,"nm":"Bulge","np":9,"mn":"ADBE Bulge","ix":2,"en":1,"ef":[{"ty":0,"nm":"Horizontal Radius","mn":"ADBE Bulge-0001","ix":1,"v":{"a":0,"k":50,"ix":1}},{"ty":0,"nm":"Vertical Radius","mn":"ADBE Bulge-0002","ix":2,"v":{"a":0,"k":50,"ix":2}},{"ty":3,"nm":"Bulge Center","mn":"ADBE Bulge-0003","ix":3,"v":{"a":0,"k":[200,200],"ix":3}},{"ty":0,"nm":"Bulge Height","mn":"ADBE Bulge-0004","ix":4,"v":{"a":0,"k":1,"ix":4}},{"ty":0,"nm":"Taper Radius","mn":"ADBE Bulge-0005","ix":5,"v":{"a":0,"k":0,"ix":5}},{"ty":7,"nm":"Antialiasing (Best Qual Only)","mn":"ADBE Bulge-0006","ix":6,"v":{"a":0,"k":1,"ix":6}},{"ty":7,"nm":"Pinning","mn":"ADBE Bulge-0007","ix":7,"v":{"a":0,"k":0,"ix":7}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[274.975,274.975],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.513,7.487],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":41,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.01,0,1,0.5,0.496,0,0.5,1,0.982,0,0],"ix":8}},"s":{"a":0,"k":[-45,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":1,"lj":1,"ml":4,"ml2":{"a":0,"k":4,"ix":13},"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false}],"ip":0,"op":121.000004928431,"st":0,"bm":0}],"markers":[]}
|
1
example/assets/Tests/PrecompBlur.json
Normal file
1
example/assets/Tests/PrecompBlur.json
Normal file
File diff suppressed because one or more lines are too long
288
example/assets/Tests/ReversedStar.json
Normal file
288
example/assets/Tests/ReversedStar.json
Normal file
@ -0,0 +1,288 @@
|
||||
{
|
||||
"v": "5.8.2",
|
||||
"fr": 24,
|
||||
"ip": 0,
|
||||
"op": 94,
|
||||
"w": 150,
|
||||
"h": 150,
|
||||
"nm": "Anim_load",
|
||||
"ddd": 0,
|
||||
"assets": [],
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 1,
|
||||
"ty": 4,
|
||||
"nm": "LF03",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": -19,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
75,
|
||||
76.005,
|
||||
0
|
||||
],
|
||||
"ix": 2,
|
||||
"l": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1,
|
||||
"l": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
19.986,
|
||||
19.986,
|
||||
100
|
||||
],
|
||||
"ix": 6,
|
||||
"l": 2
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"ty": "sr",
|
||||
"sy": 1,
|
||||
"d": 3,
|
||||
"pt": {
|
||||
"a": 0,
|
||||
"k": 14,
|
||||
"ix": 3
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 4
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"ir": {
|
||||
"a": 0,
|
||||
"k": 91.612,
|
||||
"ix": 6
|
||||
},
|
||||
"is": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 8
|
||||
},
|
||||
"or": {
|
||||
"a": 0,
|
||||
"k": 113.225,
|
||||
"ix": 7
|
||||
},
|
||||
"os": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 9
|
||||
},
|
||||
"ix": 1,
|
||||
"nm": "Polystar Path 1",
|
||||
"mn": "ADBE Vector Shape - Star",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0.937254905701,
|
||||
0.89411765337,
|
||||
0.850980401039,
|
||||
1
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 4
|
||||
},
|
||||
"w": {
|
||||
"a": 0,
|
||||
"k": 30,
|
||||
"ix": 5
|
||||
},
|
||||
"lc": 1,
|
||||
"lj": 1,
|
||||
"ml": 4,
|
||||
"bm": 0,
|
||||
"nm": "Stroke 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
-1.979,
|
||||
-0.604
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "Transform"
|
||||
}
|
||||
],
|
||||
"nm": "Polystar 1",
|
||||
"np": 2,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.667
|
||||
],
|
||||
"y": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.333
|
||||
],
|
||||
"y": [
|
||||
0
|
||||
]
|
||||
},
|
||||
"t": -0.127,
|
||||
"s": [
|
||||
100
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 32,
|
||||
"s": [
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"e": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.333
|
||||
],
|
||||
"y": [
|
||||
0
|
||||
]
|
||||
},
|
||||
"t": 36,
|
||||
"s": [
|
||||
100
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 68,
|
||||
"s": [
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": -43,
|
||||
"ix": 3
|
||||
},
|
||||
"m": 1,
|
||||
"ix": 2,
|
||||
"nm": "Trim Paths 1",
|
||||
"mn": "ADBE Vector Filter - Trim",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 94,
|
||||
"st": 18,
|
||||
"bm": 0
|
||||
}
|
||||
],
|
||||
"markers": []
|
||||
}
|
390
example/assets/Tests/RoundedCorners.json
Normal file
390
example/assets/Tests/RoundedCorners.json
Normal file
@ -0,0 +1,390 @@
|
||||
{
|
||||
"v": "5.8.1",
|
||||
"fr": 29.9700012207031,
|
||||
"ip": 0,
|
||||
"op": 900.000036657751,
|
||||
"w": 1000,
|
||||
"h": 1000,
|
||||
"nm": "Rounded Corners",
|
||||
"ddd": 0,
|
||||
"assets": [],
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 1,
|
||||
"ty": 4,
|
||||
"nm": "Shape Layer 1",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
500,
|
||||
500,
|
||||
0
|
||||
],
|
||||
"ix": 2,
|
||||
"l": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1,
|
||||
"l": 2
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 6,
|
||||
"l": 2
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ind": 0,
|
||||
"ty": "sh",
|
||||
"ix": 1,
|
||||
"ks": {
|
||||
"a": 0,
|
||||
"k": {
|
||||
"i": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"o": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"v": [
|
||||
[
|
||||
-75,
|
||||
-475
|
||||
],
|
||||
[
|
||||
-75,
|
||||
-75
|
||||
],
|
||||
[
|
||||
-475,
|
||||
-75
|
||||
],
|
||||
[
|
||||
-475,
|
||||
-475
|
||||
]
|
||||
],
|
||||
"c": true
|
||||
},
|
||||
"ix": 2
|
||||
},
|
||||
"nm": "Path 1",
|
||||
"mn": "ADBE Vector Shape - Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "rc",
|
||||
"d": 1,
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
400,
|
||||
400
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
275,
|
||||
-275
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"nm": "Rectangle Path 1",
|
||||
"mn": "ADBE Vector Shape - Rect",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "sr",
|
||||
"sy": 1,
|
||||
"d": 1,
|
||||
"pt": {
|
||||
"a": 0,
|
||||
"k": 5,
|
||||
"ix": 3
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
275,
|
||||
275
|
||||
],
|
||||
"ix": 4
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"ir": {
|
||||
"a": 0,
|
||||
"k": 107,
|
||||
"ix": 6
|
||||
},
|
||||
"is": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 8
|
||||
},
|
||||
"or": {
|
||||
"a": 0,
|
||||
"k": 275,
|
||||
"ix": 7
|
||||
},
|
||||
"os": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 9
|
||||
},
|
||||
"ix": 3,
|
||||
"nm": "Polystar Path 1",
|
||||
"mn": "ADBE Vector Shape - Star",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ind": 3,
|
||||
"ty": "sh",
|
||||
"ix": 4,
|
||||
"ks": {
|
||||
"a": 0,
|
||||
"k": {
|
||||
"i": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"o": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"v": [
|
||||
[
|
||||
-275,
|
||||
0
|
||||
],
|
||||
[
|
||||
-212.107,
|
||||
188.435
|
||||
],
|
||||
[
|
||||
-13.459,
|
||||
190.02
|
||||
],
|
||||
[
|
||||
-173.237,
|
||||
308.065
|
||||
],
|
||||
[
|
||||
-113.359,
|
||||
497.48
|
||||
],
|
||||
[
|
||||
-275,
|
||||
382
|
||||
],
|
||||
[
|
||||
-436.641,
|
||||
497.48
|
||||
],
|
||||
[
|
||||
-376.763,
|
||||
308.065
|
||||
],
|
||||
[
|
||||
-536.541,
|
||||
190.02
|
||||
],
|
||||
[
|
||||
-337.893,
|
||||
188.435
|
||||
]
|
||||
],
|
||||
"c": true
|
||||
},
|
||||
"ix": 2
|
||||
},
|
||||
"nm": "Path 2",
|
||||
"mn": "ADBE Vector Shape - Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "rd",
|
||||
"nm": "Round Corners 1",
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 136,
|
||||
"ix": 1
|
||||
},
|
||||
"ix": 5,
|
||||
"mn": "ADBE Vector Filter - RC",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "fl",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"ix": 4
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 5
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"nm": "Fill 1",
|
||||
"mn": "ADBE Vector Graphic - Fill",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 900.000036657751,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
}
|
||||
],
|
||||
"markers": []
|
||||
}
|
1
example/assets/Tests/StaticShadow.json
Normal file
1
example/assets/Tests/StaticShadow.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":181.000007372281,"w":375,"h":375,"nm":"Square","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,187.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow2","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,1,0.609851837158,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":127.5,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":0,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":10,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":20,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[217.641,217.641],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.68,-1.68],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":184.000007494474,"st":0,"bm":0}],"markers":[]}
|
1
example/assets/Tests/StrokeBlur.json
Normal file
1
example/assets/Tests/StrokeBlur.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":121.000004928431,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":29,"nm":"Gaussian Blur2","np":5,"mn":"ADBE Gaussian Blur 2","ix":1,"en":1,"ef":[{"ty":0,"nm":"Blurriness","mn":"ADBE Gaussian Blur 2-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24.00000097754,"s":[120.7]}],"ix":1}},{"ty":7,"nm":"Blur Dimensions","mn":"ADBE Gaussian Blur 2-0002","ix":2,"v":{"a":0,"k":1,"ix":2}},{"ty":7,"nm":"Repeat Edge Pixels","mn":"ADBE Gaussian Blur 2-0003","ix":3,"v":{"a":0,"k":0,"ix":3}}]},{"ty":5,"nm":"Bulge","np":9,"mn":"ADBE Bulge","ix":2,"en":1,"ef":[{"ty":0,"nm":"Horizontal Radius","mn":"ADBE Bulge-0001","ix":1,"v":{"a":0,"k":50,"ix":1}},{"ty":0,"nm":"Vertical Radius","mn":"ADBE Bulge-0002","ix":2,"v":{"a":0,"k":50,"ix":2}},{"ty":3,"nm":"Bulge Center","mn":"ADBE Bulge-0003","ix":3,"v":{"a":0,"k":[200,200],"ix":3}},{"ty":0,"nm":"Bulge Height","mn":"ADBE Bulge-0004","ix":4,"v":{"a":0,"k":1,"ix":4}},{"ty":0,"nm":"Taper Radius","mn":"ADBE Bulge-0005","ix":5,"v":{"a":0,"k":0,"ix":5}},{"ty":7,"nm":"Antialiasing (Best Qual Only)","mn":"ADBE Bulge-0006","ix":6,"v":{"a":0,"k":1,"ix":6}},{"ty":7,"nm":"Pinning","mn":"ADBE Bulge-0007","ix":7,"v":{"a":0,"k":0,"ix":7}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[274.975,274.975],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.513,7.487],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":46,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":121.000004928431,"st":0,"bm":0}],"markers":[]}
|
4841
example/assets/Tests/TrimPathWrapAround.json
Normal file
4841
example/assets/Tests/TrimPathWrapAround.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@
|
||||
<?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>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,8 @@
|
||||
<?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>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,8 @@
|
||||
<?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>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
@ -25,7 +25,7 @@ class __PageState extends State<_Page> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
SchedulerBinding.instance!.addPostFrameCallback((_) => _showLoader());
|
||||
SchedulerBinding.instance.addPostFrameCallback((_) => _showLoader());
|
||||
}
|
||||
|
||||
void _showLoader() {
|
||||
|
@ -7,7 +7,7 @@ class MyApp extends StatefulWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MyAppState createState() => _MyAppState();
|
||||
State<MyApp> createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||
|
@ -15,7 +15,7 @@ class MyApp extends StatefulWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MyAppState createState() => _MyAppState();
|
||||
State<MyApp> createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||
|
30
example/lib/examples/blur.dart
Normal file
30
example/lib/examples/blur.dart
Normal file
@ -0,0 +1,30 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
void main() => runApp(const MyApp());
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: ListView(
|
||||
children: [
|
||||
Lottie.asset(
|
||||
'assets/AndroidWave.json',
|
||||
height: 300,
|
||||
delegates: LottieDelegates(values: [
|
||||
ValueDelegate.blurRadius(
|
||||
['**'],
|
||||
value: 20,
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
void main() => runApp(const MyApp());
|
||||
@ -22,7 +21,7 @@ class MyWidget extends StatefulWidget {
|
||||
const MyWidget({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MyWidgetState createState() => _MyWidgetState();
|
||||
State<MyWidget> createState() => _MyWidgetState();
|
||||
}
|
||||
|
||||
class _MyWidgetState extends State<MyWidget> {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
void main() => runApp(const MyApp());
|
||||
@ -23,7 +22,7 @@ class MyWidget extends StatefulWidget {
|
||||
const MyWidget({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MyWidgetState createState() => _MyWidgetState();
|
||||
State<MyWidget> createState() => _MyWidgetState();
|
||||
}
|
||||
|
||||
class _MyWidgetState extends State<MyWidget> {
|
||||
|
35
example/lib/examples/drop_shadow.dart
Normal file
35
example/lib/examples/drop_shadow.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
void main() => runApp(const MyApp());
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: ListView(
|
||||
children: [
|
||||
Lottie.asset(
|
||||
'assets/Tests/Fill.json',
|
||||
height: 300,
|
||||
delegates: LottieDelegates(values: [
|
||||
ValueDelegate.dropShadow(
|
||||
['**'],
|
||||
value: const DropShadow(
|
||||
color: Colors.blue,
|
||||
direction: 140,
|
||||
distance: 60,
|
||||
radius: 10,
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
@ -11,7 +10,7 @@ class App extends StatefulWidget {
|
||||
const App({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AppState createState() => _AppState();
|
||||
State<App> createState() => _AppState();
|
||||
}
|
||||
|
||||
class _AppState extends State<App> with TickerProviderStateMixin {
|
||||
@ -72,7 +71,7 @@ class _AppState extends State<App> with TickerProviderStateMixin {
|
||||
_color = newColor;
|
||||
});
|
||||
},
|
||||
showLabel: false,
|
||||
labelTypes: const [],
|
||||
enableAlpha: false,
|
||||
pickerAreaHeightPercent: 0.8,
|
||||
),
|
||||
|
@ -10,7 +10,7 @@ class App extends StatefulWidget {
|
||||
const App({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AppState createState() => _AppState();
|
||||
State<App> createState() => _AppState();
|
||||
}
|
||||
|
||||
class _AppState extends State<App> with TickerProviderStateMixin {
|
||||
|
@ -9,7 +9,7 @@ class App extends StatefulWidget {
|
||||
const App({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AppState createState() => _AppState();
|
||||
State<App> createState() => _AppState();
|
||||
}
|
||||
|
||||
class _AppState extends State<App> with TickerProviderStateMixin {
|
||||
|
@ -12,7 +12,7 @@ class App extends StatefulWidget {
|
||||
const App({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AppState createState() => _AppState();
|
||||
State<App> createState() => _AppState();
|
||||
}
|
||||
|
||||
class _AppState extends State<App> with TickerProviderStateMixin {
|
||||
|
@ -7,7 +7,7 @@ class MyApp extends StatefulWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MyAppState createState() => _MyAppState();
|
||||
State<MyApp> createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||
|
@ -15,7 +15,7 @@ class App extends StatefulWidget {
|
||||
const App({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AppState createState() => _AppState();
|
||||
State<App> createState() => _AppState();
|
||||
}
|
||||
|
||||
class _AppState extends State<App> with TickerProviderStateMixin {
|
||||
|
@ -13,7 +13,7 @@ class MyApp extends StatefulWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MyAppState createState() => _MyAppState();
|
||||
State<MyApp> createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
@ -93,7 +92,7 @@ class Detail extends StatefulWidget {
|
||||
const Detail(this.assetName, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DetailState createState() => _DetailState();
|
||||
State<Detail> createState() => _DetailState();
|
||||
}
|
||||
|
||||
class _DetailState extends State<Detail> with TickerProviderStateMixin {
|
||||
|
@ -15,8 +15,8 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
|
||||
path_provider_macos: a0a3fd666cb7cd0448e936fb4abad4052961002b
|
||||
path_provider_macos: 160cab0d5461f0c0e02995469a98f24bdb9a3f1f
|
||||
|
||||
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||
|
||||
COCOAPODS: 1.10.1
|
||||
COCOAPODS: 1.11.3
|
||||
|
@ -7,14 +7,14 @@ packages:
|
||||
name: archive
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
version: "3.3.1"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.5.0"
|
||||
version: "2.8.2"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -28,14 +28,14 @@ packages:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.2.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -49,28 +49,28 @@ packages:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
version: "1.16.0"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
version: "3.0.2"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
version: "2.0.1"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -89,14 +89,14 @@ packages:
|
||||
name: flutter_colorpicker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.5.0"
|
||||
version: "1.0.3"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
version: "2.0.1"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@ -108,126 +108,140 @@ packages:
|
||||
name: golden_toolkit
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.0"
|
||||
version: "0.13.0"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.13.3"
|
||||
version: "0.13.4"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
version: "4.0.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
version: "2.0.0"
|
||||
logging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: logging
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
version: "1.0.2"
|
||||
lottie:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.1.0"
|
||||
version: "1.4.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.10"
|
||||
version: "0.12.11"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.4"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.7.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
version: "1.8.1"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
version: "2.0.11"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.16"
|
||||
path_provider_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_ios
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.10"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.1.7"
|
||||
path_provider_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.0.6"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "2.0.4"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
version: "2.1.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
version: "3.1.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.1.2"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.2.1"
|
||||
version: "4.2.4"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -239,7 +253,7 @@ packages:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
version: "1.8.2"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -274,35 +288,35 @@ packages:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "0.4.9"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.3.1"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.2"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.5"
|
||||
version: "2.7.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
version: "0.2.0+1"
|
||||
sdks:
|
||||
dart: ">=2.13.0 <3.0.0"
|
||||
flutter: ">=1.20.0"
|
||||
dart: ">=2.17.0 <3.0.0"
|
||||
flutter: ">=3.0.0"
|
||||
|
@ -13,6 +13,7 @@ dependencies:
|
||||
logging:
|
||||
lottie:
|
||||
path: ../
|
||||
path:
|
||||
path_provider:
|
||||
|
||||
dev_dependencies:
|
||||
|
BIN
example/web/favicon.png
Normal file
BIN
example/web/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 917 B |
BIN
example/web/icons/Icon-192.png
Normal file
BIN
example/web/icons/Icon-192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
BIN
example/web/icons/Icon-512.png
Normal file
BIN
example/web/icons/Icon-512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
BIN
example/web/icons/Icon-maskable-192.png
Normal file
BIN
example/web/icons/Icon-maskable-192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
BIN
example/web/icons/Icon-maskable-512.png
Normal file
BIN
example/web/icons/Icon-maskable-512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
35
example/web/manifest.json
Normal file
35
example/web/manifest.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "example",
|
||||
"short_name": "example",
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"background_color": "#0175C2",
|
||||
"theme_color": "#0175C2",
|
||||
"description": "A new Flutter project.",
|
||||
"orientation": "portrait-primary",
|
||||
"prefer_related_applications": false,
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/Icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
@ -14,4 +14,5 @@ export 'src/providers/lottie_provider.dart' show LottieProvider;
|
||||
export 'src/providers/memory_provider.dart' show MemoryLottie;
|
||||
export 'src/providers/network_provider.dart' show NetworkLottie;
|
||||
export 'src/raw_lottie.dart' show RawLottie;
|
||||
export 'src/value/drop_shadow.dart' show DropShadow;
|
||||
export 'src/value_delegate.dart' show ValueDelegate;
|
||||
|
@ -7,6 +7,7 @@ import '../../lottie_drawable.dart';
|
||||
import '../../lottie_property.dart';
|
||||
import '../../model/animatable/animatable_double_value.dart';
|
||||
import '../../model/animatable/animatable_integer_value.dart';
|
||||
import '../../model/content/drop_shadow_effect.dart';
|
||||
import '../../model/content/shape_trim_path.dart';
|
||||
import '../../model/key_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
@ -15,8 +16,10 @@ import '../../utils/dash_path.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../utils/utils.dart';
|
||||
import '../../value/drop_shadow.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import '../keyframe/drop_shadow_keyframe_animation.dart';
|
||||
import '../keyframe/value_callback_keyframe_animation.dart';
|
||||
import 'content.dart';
|
||||
import 'drawing_content.dart';
|
||||
@ -39,6 +42,9 @@ abstract class BaseStrokeContent
|
||||
final List<BaseKeyframeAnimation<Object, double>> _dashPatternAnimations;
|
||||
final BaseKeyframeAnimation<Object, double>? _dashPatternOffsetAnimation;
|
||||
BaseKeyframeAnimation<ColorFilter, ColorFilter?>? _colorFilterAnimation;
|
||||
BaseKeyframeAnimation<double, double>? _blurAnimation;
|
||||
double _blurMaskFilterRadius = 0;
|
||||
DropShadowKeyframeAnimation? dropShadowAnimation;
|
||||
|
||||
BaseStrokeContent(this.lottieDrawable, this.layer,
|
||||
{required StrokeCap cap,
|
||||
@ -77,6 +83,17 @@ abstract class BaseStrokeContent
|
||||
if (_dashPatternOffsetAnimation != null) {
|
||||
_dashPatternOffsetAnimation!.addUpdateListener(onUpdateListener);
|
||||
}
|
||||
var blurEffect = layer.blurEffect;
|
||||
if (blurEffect != null) {
|
||||
_blurAnimation = blurEffect.blurriness.createAnimation()
|
||||
..addUpdateListener(onUpdateListener);
|
||||
layer.addAnimation(_blurAnimation);
|
||||
}
|
||||
var dropShadowEffect = layer.dropShadowEffect;
|
||||
if (dropShadowEffect != null) {
|
||||
dropShadowAnimation = DropShadowKeyframeAnimation(
|
||||
onUpdateListener, layer, dropShadowEffect);
|
||||
}
|
||||
}
|
||||
|
||||
void onUpdateListener() {
|
||||
@ -139,6 +156,18 @@ abstract class BaseStrokeContent
|
||||
paint.colorFilter = _colorFilterAnimation!.value;
|
||||
}
|
||||
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
var blurRadius = blurAnimation.value;
|
||||
if (blurRadius == 0) {
|
||||
paint.maskFilter = null;
|
||||
} else if (blurRadius != _blurMaskFilterRadius) {
|
||||
var blur = layer.getBlurMaskFilter(blurRadius);
|
||||
paint.maskFilter = blur;
|
||||
}
|
||||
_blurMaskFilterRadius = blurRadius;
|
||||
}
|
||||
|
||||
for (var i = 0; i < _pathGroups.length; i++) {
|
||||
var pathGroup = _pathGroups[i];
|
||||
|
||||
@ -153,6 +182,10 @@ abstract class BaseStrokeContent
|
||||
}
|
||||
L.endSection('StrokeContent#buildPath');
|
||||
L.beginSection('StrokeContent#drawPath');
|
||||
var dropShadow = dropShadowAnimation;
|
||||
if (dropShadow != null) {
|
||||
dropShadow.draw(canvas, _path);
|
||||
}
|
||||
canvas.drawPath(_withDashPattern(_path, parentMatrix), paint);
|
||||
L.endSection('StrokeContent#drawPath');
|
||||
}
|
||||
@ -163,7 +196,8 @@ abstract class BaseStrokeContent
|
||||
void _applyTrimPath(
|
||||
Canvas canvas, _PathGroup pathGroup, Matrix4 parentMatrix) {
|
||||
L.beginSection('StrokeContent#applyTrimPath');
|
||||
if (pathGroup.trimPath == null) {
|
||||
var trimPath = pathGroup.trimPath;
|
||||
if (trimPath == null) {
|
||||
L.endSection('StrokeContent#applyTrimPath');
|
||||
return;
|
||||
}
|
||||
@ -172,13 +206,24 @@ abstract class BaseStrokeContent
|
||||
_path.addPath(pathGroup.paths[j].getPath(), Offset.zero,
|
||||
matrix4: parentMatrix.storage);
|
||||
}
|
||||
var animStartValue = trimPath.start.value / 100;
|
||||
var animEndValue = trimPath.end.value / 100;
|
||||
var animOffsetValue = trimPath.offset.value / 360;
|
||||
|
||||
// If the start-end is ~100, consider it to be the full path.
|
||||
if (animStartValue < 0.01 && animEndValue > 0.99) {
|
||||
canvas.drawPath(_path, paint);
|
||||
L.endSection('StrokeContent#applyTrimPath');
|
||||
return;
|
||||
}
|
||||
|
||||
var pathMetrics = _path.computeMetrics().toList();
|
||||
var totalLength = pathMetrics.fold<double>(0.0, (a, b) => a + b.length);
|
||||
|
||||
var trimPath = pathGroup.trimPath!;
|
||||
var offsetLength = totalLength * trimPath.offset.value / 360.0;
|
||||
var startLength = totalLength * trimPath.start.value / 100.0 + offsetLength;
|
||||
var endLength = totalLength * trimPath.end.value / 100.0 + offsetLength;
|
||||
var offsetLength = totalLength * animOffsetValue;
|
||||
var startLength = totalLength * animStartValue + offsetLength;
|
||||
var endLength = min(totalLength * animEndValue + offsetLength,
|
||||
startLength + totalLength - 1);
|
||||
|
||||
var currentLength = 0.0;
|
||||
for (var j = pathGroup.paths.length - 1; j >= 0; j--) {
|
||||
@ -308,10 +353,31 @@ abstract class BaseStrokeContent
|
||||
} else {
|
||||
_colorFilterAnimation =
|
||||
ValueCallbackKeyframeAnimation<ColorFilter, ColorFilter?>(
|
||||
callback as LottieValueCallback<ColorFilter>, null);
|
||||
_colorFilterAnimation!.addUpdateListener(onUpdateListener);
|
||||
callback as LottieValueCallback<ColorFilter>, null)
|
||||
..addUpdateListener(onUpdateListener);
|
||||
layer.addAnimation(_colorFilterAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.blurRadius) {
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
blurAnimation
|
||||
.setValueCallback(callback as LottieValueCallback<double>?);
|
||||
} else {
|
||||
_blurAnimation = blurAnimation = ValueCallbackKeyframeAnimation(
|
||||
callback as LottieValueCallback<double>?, 0)
|
||||
..addUpdateListener(onUpdateListener);
|
||||
layer.addAnimation(blurAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.dropShadow) {
|
||||
var dropShadowAnimation = this.dropShadowAnimation;
|
||||
if (dropShadowAnimation == null) {
|
||||
var effect = DropShadowEffect.createEmpty();
|
||||
this.dropShadowAnimation = dropShadowAnimation = dropShadowAnimation =
|
||||
DropShadowKeyframeAnimation(onUpdateListener, layer, effect);
|
||||
}
|
||||
|
||||
dropShadowAnimation
|
||||
.setCallback(callback as LottieValueCallback<DropShadow>?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,17 @@ import 'package:vector_math/vector_math_64.dart';
|
||||
import '../../l.dart';
|
||||
import '../../lottie_drawable.dart';
|
||||
import '../../lottie_property.dart';
|
||||
import '../../model/content/drop_shadow_effect.dart';
|
||||
import '../../model/content/shape_fill.dart';
|
||||
import '../../model/key_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/drop_shadow.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import '../keyframe/drop_shadow_keyframe_animation.dart';
|
||||
import '../keyframe/value_callback_keyframe_animation.dart';
|
||||
import 'content.dart';
|
||||
import 'drawing_content.dart';
|
||||
@ -29,10 +32,25 @@ class FillContent implements DrawingContent, KeyPathElementContent {
|
||||
late final BaseKeyframeAnimation<int, int> _opacityAnimation;
|
||||
BaseKeyframeAnimation<ColorFilter, ColorFilter?>? _colorFilterAnimation;
|
||||
final LottieDrawable lottieDrawable;
|
||||
BaseKeyframeAnimation<double, double>? _blurAnimation;
|
||||
double _blurMaskFilterRadius = 0;
|
||||
DropShadowKeyframeAnimation? dropShadowAnimation;
|
||||
|
||||
FillContent(this.lottieDrawable, this.layer, ShapeFill fill)
|
||||
: name = fill.name,
|
||||
_hidden = fill.hidden {
|
||||
var blurEffect = layer.blurEffect;
|
||||
if (blurEffect != null) {
|
||||
_blurAnimation = blurEffect.blurriness.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_blurAnimation);
|
||||
}
|
||||
var dropShadowEffect = layer.dropShadowEffect;
|
||||
if (dropShadowEffect != null) {
|
||||
dropShadowAnimation =
|
||||
DropShadowKeyframeAnimation(onValueChanged, layer, dropShadowEffect);
|
||||
}
|
||||
|
||||
if (fill.color == null || fill.opacity == null) {
|
||||
return;
|
||||
}
|
||||
@ -80,6 +98,18 @@ class FillContent implements DrawingContent, KeyPathElementContent {
|
||||
_paint.colorFilter = _colorFilterAnimation!.value;
|
||||
}
|
||||
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
var blurRadius = blurAnimation.value;
|
||||
if (blurRadius == 0) {
|
||||
_paint.maskFilter = null;
|
||||
} else if (blurRadius != _blurMaskFilterRadius) {
|
||||
var blur = layer.getBlurMaskFilter(blurRadius);
|
||||
_paint.maskFilter = blur;
|
||||
}
|
||||
_blurMaskFilterRadius = blurRadius;
|
||||
}
|
||||
|
||||
_path.reset();
|
||||
for (var i = 0; i < _paths.length; i++) {
|
||||
_path.addPath(_paths[i].getPath(), Offset.zero);
|
||||
@ -87,6 +117,10 @@ class FillContent implements DrawingContent, KeyPathElementContent {
|
||||
|
||||
canvas.save();
|
||||
canvas.transform(parentMatrix.storage);
|
||||
var dropShadow = dropShadowAnimation;
|
||||
if (dropShadow != null) {
|
||||
dropShadow.draw(canvas, _path);
|
||||
}
|
||||
canvas.drawPath(_path, _paint);
|
||||
canvas.restore();
|
||||
|
||||
@ -132,6 +166,28 @@ class FillContent implements DrawingContent, KeyPathElementContent {
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_colorFilterAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.blurRadius) {
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
blurAnimation
|
||||
.setValueCallback(callback as LottieValueCallback<double>?);
|
||||
} else {
|
||||
var callbackBlur = callback as LottieValueCallback<double>?;
|
||||
_blurAnimation = blurAnimation = ValueCallbackKeyframeAnimation(
|
||||
callbackBlur, callbackBlur?.value ?? 0)
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(blurAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.dropShadow) {
|
||||
var dropShadowAnimation = this.dropShadowAnimation;
|
||||
if (dropShadowAnimation == null) {
|
||||
var effect = DropShadowEffect.createEmpty();
|
||||
this.dropShadowAnimation = dropShadowAnimation = dropShadowAnimation =
|
||||
DropShadowKeyframeAnimation(onValueChanged, layer, effect);
|
||||
}
|
||||
|
||||
dropShadowAnimation
|
||||
.setCallback(callback as LottieValueCallback<DropShadow>?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import 'package:vector_math/vector_math_64.dart';
|
||||
import '../../l.dart';
|
||||
import '../../lottie_drawable.dart';
|
||||
import '../../lottie_property.dart';
|
||||
import '../../model/content/drop_shadow_effect.dart';
|
||||
import '../../model/content/gradient_color.dart';
|
||||
import '../../model/content/gradient_fill.dart';
|
||||
import '../../model/content/gradient_type.dart';
|
||||
@ -11,8 +12,10 @@ import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/misc.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../../value/drop_shadow.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import '../keyframe/drop_shadow_keyframe_animation.dart';
|
||||
import '../keyframe/value_callback_keyframe_animation.dart';
|
||||
import 'content.dart';
|
||||
import 'drawing_content.dart';
|
||||
@ -38,6 +41,9 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
_colorCallbackAnimation;
|
||||
final LottieDrawable lottieDrawable;
|
||||
final int _cacheSteps;
|
||||
BaseKeyframeAnimation<double, double>? _blurAnimation;
|
||||
double _blurMaskFilterRadius = 0;
|
||||
DropShadowKeyframeAnimation? dropShadowAnimation;
|
||||
|
||||
GradientFillContent(this.lottieDrawable, this.layer, this._fill)
|
||||
: _cacheSteps =
|
||||
@ -59,6 +65,18 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
|
||||
_endPointAnimation.addUpdateListener(invalidate);
|
||||
layer.addAnimation(_endPointAnimation);
|
||||
|
||||
var blurEffect = layer.blurEffect;
|
||||
if (blurEffect != null) {
|
||||
_blurAnimation = blurEffect.blurriness.createAnimation()
|
||||
..addUpdateListener(invalidate);
|
||||
layer.addAnimation(_blurAnimation);
|
||||
}
|
||||
var dropShadowEffect = layer.dropShadowEffect;
|
||||
if (dropShadowEffect != null) {
|
||||
dropShadowAnimation =
|
||||
DropShadowKeyframeAnimation(invalidate, layer, dropShadowEffect);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -103,6 +121,18 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
_paint.colorFilter = _colorFilterAnimation!.value;
|
||||
}
|
||||
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
var blurRadius = blurAnimation.value;
|
||||
if (blurRadius == 0) {
|
||||
_paint.maskFilter = null;
|
||||
} else if (blurRadius != _blurMaskFilterRadius) {
|
||||
var blur = layer.getBlurMaskFilter(blurRadius);
|
||||
_paint.maskFilter = blur;
|
||||
}
|
||||
_blurMaskFilterRadius = blurRadius;
|
||||
}
|
||||
|
||||
var alpha =
|
||||
((parentAlpha / 255.0 * _opacityAnimation.value / 100.0) * 255).round();
|
||||
_paint.setAlpha(alpha.clamp(0, 255).toInt());
|
||||
@ -112,6 +142,10 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
|
||||
canvas.save();
|
||||
canvas.transform(parentMatrix.storage);
|
||||
var dropShadow = dropShadowAnimation;
|
||||
if (dropShadow != null) {
|
||||
dropShadow.draw(canvas, _path);
|
||||
}
|
||||
canvas.drawPath(_path, _paint);
|
||||
canvas.restore();
|
||||
L.endSection('GradientFillContent#draw');
|
||||
@ -246,6 +280,27 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
..addUpdateListener(invalidate);
|
||||
layer.addAnimation(_colorCallbackAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.blurRadius) {
|
||||
var blurAnimation = _blurAnimation;
|
||||
if (blurAnimation != null) {
|
||||
blurAnimation
|
||||
.setValueCallback(callback as LottieValueCallback<double>?);
|
||||
} else {
|
||||
_blurAnimation = blurAnimation = ValueCallbackKeyframeAnimation(
|
||||
callback as LottieValueCallback<double>?, 0)
|
||||
..addUpdateListener(invalidate);
|
||||
layer.addAnimation(blurAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.dropShadow) {
|
||||
var dropShadowAnimation = this.dropShadowAnimation;
|
||||
if (dropShadowAnimation == null) {
|
||||
var effect = DropShadowEffect.createEmpty();
|
||||
this.dropShadowAnimation = dropShadowAnimation = dropShadowAnimation =
|
||||
DropShadowKeyframeAnimation(invalidate, layer, effect);
|
||||
}
|
||||
|
||||
dropShadowAnimation
|
||||
.setCallback(callback as LottieValueCallback<DropShadow>?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,9 @@ class PolystarContent implements PathContent, KeyPathElementContent {
|
||||
currentAngle = radians(currentAngle);
|
||||
// adjust current angle for partial points
|
||||
var anglePerPoint = 2 * pi / points;
|
||||
if (_polystarShape.isReversed) {
|
||||
anglePerPoint *= -1;
|
||||
}
|
||||
var halfAnglePerPoint = anglePerPoint / 2.0;
|
||||
var partialPointAmount = points - points.toInt();
|
||||
if (partialPointAmount != 0) {
|
||||
|
@ -15,6 +15,7 @@ import 'compound_trim_path_content.dart';
|
||||
import 'content.dart';
|
||||
import 'key_path_element_content.dart';
|
||||
import 'path_content.dart';
|
||||
import 'rounded_corners_content.dart';
|
||||
import 'trim_path_content.dart';
|
||||
|
||||
class RectangleContent implements KeyPathElementContent, PathContent {
|
||||
@ -29,6 +30,9 @@ class RectangleContent implements KeyPathElementContent, PathContent {
|
||||
final BaseKeyframeAnimation<Object, double> _cornerRadiusAnimation;
|
||||
|
||||
final CompoundTrimPathContent _trimPaths = CompoundTrimPathContent();
|
||||
|
||||
/// This corner radius is from a layer item. The first one is from the roundedness on this specific rect.
|
||||
BaseKeyframeAnimation<double, double>? _roundedCornersAnimation;
|
||||
bool _isPathValid = false;
|
||||
|
||||
RectangleContent(
|
||||
@ -61,6 +65,8 @@ class RectangleContent implements KeyPathElementContent, PathContent {
|
||||
var trimPath = content;
|
||||
_trimPaths.addTrimPath(trimPath);
|
||||
trimPath.addListener(invalidate);
|
||||
} else if (content is RoundedCornersContent) {
|
||||
_roundedCornersAnimation = content.roundedCorners;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -82,6 +88,10 @@ class RectangleContent implements KeyPathElementContent, PathContent {
|
||||
var halfWidth = size.dx / 2.0;
|
||||
var halfHeight = size.dy / 2.0;
|
||||
var radius = _cornerRadiusAnimation.value;
|
||||
var roundedCornersAnimation = _roundedCornersAnimation;
|
||||
if (radius == 0 && roundedCornersAnimation != null) {
|
||||
radius = min(roundedCornersAnimation.value, min(halfWidth, halfHeight));
|
||||
}
|
||||
var maxRadius = min(halfWidth, halfHeight);
|
||||
if (radius > maxRadius) {
|
||||
radius = maxRadius;
|
||||
|
236
lib/src/animation/content/rounded_corners_content.dart
Normal file
236
lib/src/animation/content/rounded_corners_content.dart
Normal file
@ -0,0 +1,236 @@
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui';
|
||||
import '../../lottie_drawable.dart';
|
||||
import '../../model/content/rounded_corners.dart';
|
||||
import '../../model/content/shape_data.dart';
|
||||
import '../../model/cubic_curve_data.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import 'content.dart';
|
||||
import 'shape_modifier_content.dart';
|
||||
|
||||
class RoundedCornersContent implements ShapeModifierContent {
|
||||
/// Copied from:
|
||||
/// https://github.com/airbnb/lottie-web/blob/bb71072a26e03f1ca993da60915860f39aae890b/player/js/utils/common.js#L47
|
||||
static const _roundedCornerMagicNumber = 0.5519;
|
||||
|
||||
final LottieDrawable lottieDrawable;
|
||||
|
||||
@override
|
||||
final String name;
|
||||
final BaseKeyframeAnimation<double, double> roundedCorners;
|
||||
ShapeData? shapeData;
|
||||
|
||||
RoundedCornersContent(
|
||||
this.lottieDrawable, BaseLayer layer, RoundedCorners roundedCorners)
|
||||
: name = roundedCorners.name,
|
||||
roundedCorners = roundedCorners.cornerRadius.createAnimation() {
|
||||
layer.addAnimation(this.roundedCorners);
|
||||
this.roundedCorners.addUpdateListener(_onValueChanged);
|
||||
}
|
||||
|
||||
void _onValueChanged() {
|
||||
lottieDrawable.invalidateSelf();
|
||||
}
|
||||
|
||||
@override
|
||||
void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/// Rounded corner algorithm:
|
||||
/// Iterate through each vertex.
|
||||
/// If a vertex is a sharp corner, it rounds it.
|
||||
/// If a vertex has control points, it is already rounded, so it does nothing.
|
||||
/// <p>
|
||||
/// To round a vertex:
|
||||
/// Split the vertex into two.
|
||||
/// Move vertex 1 directly towards the previous vertex.
|
||||
/// Set vertex 1's in control point to itself so it is not rounded on that side.
|
||||
/// Extend vertex 1's out control point towards the original vertex.
|
||||
/// <p>
|
||||
/// Repeat for vertex 2:
|
||||
/// Move vertex 2 directly towards the next vertex.
|
||||
/// Set vertex 2's out point to itself so it is not rounded on that side.
|
||||
/// Extend vertex 2's in control point towards the original vertex.
|
||||
/// <p>
|
||||
/// The distance that the vertices and control points are moved are relative to the
|
||||
/// shape's vertex distances and the roundedness set in the animation.
|
||||
@override
|
||||
ShapeData modifyShape(ShapeData startingShapeData) {
|
||||
var startingCurves = startingShapeData.curves;
|
||||
if (startingCurves.length <= 2) {
|
||||
return startingShapeData;
|
||||
}
|
||||
var roundedness = roundedCorners.value;
|
||||
if (roundedness == 0) {
|
||||
return startingShapeData;
|
||||
}
|
||||
|
||||
var modifiedShapeData = _getShapeData(startingShapeData);
|
||||
modifiedShapeData.setInitialPoint(
|
||||
startingShapeData.initialPoint.dx, startingShapeData.initialPoint.dy);
|
||||
var modifiedCurves = modifiedShapeData.curves;
|
||||
var modifiedCurvesIndex = 0;
|
||||
var isClosed = startingShapeData.isClosed;
|
||||
|
||||
// i represents which vertex we are currently on. Refer to the docs of CubicCurveData prior to working with
|
||||
// this code.
|
||||
// When i == 0
|
||||
// vertex=ShapeData.initialPoint
|
||||
// inCp=if closed vertex else curves[size - 1].cp2
|
||||
// outCp=curves[0].cp1
|
||||
// When i == 1
|
||||
// vertex=curves[0].vertex
|
||||
// inCp=curves[0].cp2
|
||||
// outCp=curves[1].cp1.
|
||||
// When i == size - 1
|
||||
// vertex=curves[size - 1].vertex
|
||||
// inCp=curves[size - 1].cp2
|
||||
// outCp=if closed vertex else curves[0].cp1
|
||||
for (var i = 0; i < startingCurves.length; i++) {
|
||||
var startingCurve = startingCurves[i];
|
||||
var previousCurve =
|
||||
startingCurves[floorMod(i - 1, startingCurves.length)];
|
||||
var previousPreviousCurve =
|
||||
startingCurves[floorMod(i - 2, startingCurves.length)];
|
||||
var vertex = (i == 0 && !isClosed)
|
||||
? startingShapeData.initialPoint
|
||||
: previousCurve.vertex;
|
||||
var inPoint =
|
||||
(i == 0 && !isClosed) ? vertex : previousCurve.controlPoint2;
|
||||
var outPoint = startingCurve.controlPoint1;
|
||||
var previousVertex = previousPreviousCurve.vertex;
|
||||
var nextVertex = startingCurve.vertex;
|
||||
|
||||
// We can't round the corner of the end of a non-closed curve.
|
||||
var isEndOfCurve = !startingShapeData.isClosed &&
|
||||
(i == 0 && i == startingCurves.length - 1);
|
||||
if (inPoint == vertex && outPoint == vertex && !isEndOfCurve) {
|
||||
// This vertex is a point. Round its corners
|
||||
var dxToPreviousVertex = vertex.dx - previousVertex.dx;
|
||||
var dyToPreviousVertex = vertex.dy - previousVertex.dy;
|
||||
var dxToNextVertex = nextVertex.dx - vertex.dx;
|
||||
var dyToNextVertex = nextVertex.dy - vertex.dy;
|
||||
|
||||
var dToPreviousVertex = hypot(dxToPreviousVertex, dyToPreviousVertex);
|
||||
var dToNextVertex = hypot(dxToNextVertex, dyToNextVertex);
|
||||
|
||||
double previousVertexPercent =
|
||||
math.min(roundedness / dToPreviousVertex, 0.5);
|
||||
double nextVertexPercent = math.min(roundedness / dToNextVertex, 0.5);
|
||||
|
||||
// Split the vertex into two and move each vertex towards the previous/next vertex.
|
||||
var newVertex1X =
|
||||
vertex.dx + (previousVertex.dx - vertex.dx) * previousVertexPercent;
|
||||
var newVertex1Y =
|
||||
vertex.dy + (previousVertex.dy - vertex.dy) * previousVertexPercent;
|
||||
var newVertex2X =
|
||||
vertex.dx + (nextVertex.dx - vertex.dx) * nextVertexPercent;
|
||||
var newVertex2Y =
|
||||
vertex.dy + (nextVertex.dy - vertex.dy) * nextVertexPercent;
|
||||
|
||||
// Extend the new vertex control point towards the original vertex.
|
||||
var newVertex1OutPointX =
|
||||
newVertex1X - (newVertex1X - vertex.dx) * _roundedCornerMagicNumber;
|
||||
var newVertex1OutPointY =
|
||||
newVertex1Y - (newVertex1Y - vertex.dy) * _roundedCornerMagicNumber;
|
||||
var newVertex2InPointX =
|
||||
newVertex2X - (newVertex2X - vertex.dx) * _roundedCornerMagicNumber;
|
||||
var newVertex2InPointY =
|
||||
newVertex2Y - (newVertex2Y - vertex.dy) * _roundedCornerMagicNumber;
|
||||
|
||||
// Remap vertex/in/out point to CubicCurveData.
|
||||
// Refer to the docs for CubicCurveData for more info on the difference.
|
||||
var previousCurveData = modifiedCurves[
|
||||
floorMod(modifiedCurvesIndex - 1, modifiedCurves.length)];
|
||||
var currentCurveData = modifiedCurves[modifiedCurvesIndex];
|
||||
previousCurveData.controlPoint2 = Offset(newVertex1X, newVertex1Y);
|
||||
previousCurveData.vertex = Offset(newVertex1X, newVertex1Y);
|
||||
if (i == 0) {
|
||||
modifiedShapeData.setInitialPoint(newVertex1X, newVertex1Y);
|
||||
}
|
||||
currentCurveData.controlPoint1 =
|
||||
Offset(newVertex1OutPointX, newVertex1OutPointY);
|
||||
modifiedCurvesIndex++;
|
||||
|
||||
previousCurveData = currentCurveData;
|
||||
currentCurveData = modifiedCurves[modifiedCurvesIndex];
|
||||
previousCurveData.controlPoint2 =
|
||||
Offset(newVertex2InPointX, newVertex2InPointY);
|
||||
previousCurveData.vertex = Offset(newVertex2X, newVertex2Y);
|
||||
currentCurveData.controlPoint1 = Offset(newVertex2X, newVertex2Y);
|
||||
modifiedCurvesIndex++;
|
||||
} else {
|
||||
// This vertex is not a point. Don't modify it. Refer to the documentation above and for CubicCurveData for mapping a vertex
|
||||
// oriented point to CubicCurveData (path segments).
|
||||
var previousCurveData = modifiedCurves[
|
||||
floorMod(modifiedCurvesIndex - 1, modifiedCurves.length)];
|
||||
var currentCurveData = modifiedCurves[modifiedCurvesIndex];
|
||||
previousCurveData.controlPoint2 =
|
||||
Offset(previousCurve.vertex.dx, previousCurve.vertex.dy);
|
||||
previousCurveData.vertex =
|
||||
Offset(previousCurve.vertex.dx, previousCurve.vertex.dy);
|
||||
currentCurveData.controlPoint1 =
|
||||
Offset(startingCurve.vertex.dx, startingCurve.vertex.dy);
|
||||
modifiedCurvesIndex++;
|
||||
}
|
||||
}
|
||||
return modifiedShapeData;
|
||||
}
|
||||
|
||||
/// Returns a shape data with the correct number of vertices for the rounded corners shape.
|
||||
/// This just returns the object. It does not update any values within the shape.
|
||||
|
||||
ShapeData _getShapeData(ShapeData startingShapeData) {
|
||||
var startingCurves = startingShapeData.curves;
|
||||
var isClosed = startingShapeData.isClosed;
|
||||
var vertices = 0;
|
||||
for (var i = startingCurves.length - 1; i >= 0; i--) {
|
||||
var startingCurve = startingCurves[i];
|
||||
var previousCurve =
|
||||
startingCurves[floorMod(i - 1, startingCurves.length)];
|
||||
var vertex = (i == 0 && !isClosed)
|
||||
? startingShapeData.initialPoint
|
||||
: previousCurve.vertex;
|
||||
var inPoint =
|
||||
(i == 0 && !isClosed) ? vertex : previousCurve.controlPoint2;
|
||||
var outPoint = startingCurve.controlPoint1;
|
||||
|
||||
var isEndOfCurve = !startingShapeData.isClosed &&
|
||||
(i == 0 && i == startingCurves.length - 1);
|
||||
if (inPoint == vertex && outPoint == vertex && !isEndOfCurve) {
|
||||
vertices += 2;
|
||||
} else {
|
||||
vertices += 1;
|
||||
}
|
||||
}
|
||||
var shapeData = this.shapeData;
|
||||
if (shapeData == null || shapeData.curves.length != vertices) {
|
||||
var newCurves = <CubicCurveData>[];
|
||||
for (var i = 0; i < vertices; i++) {
|
||||
newCurves.add(CubicCurveData());
|
||||
}
|
||||
this.shapeData = shapeData =
|
||||
ShapeData(newCurves, initialPoint: Offset.zero, closed: false);
|
||||
}
|
||||
shapeData.setClosed(isClosed);
|
||||
return shapeData;
|
||||
}
|
||||
|
||||
/// Copied from the API 24+ AOSP source.
|
||||
static int floorMod(int x, int y) {
|
||||
return x - floorDiv(x, y) * y;
|
||||
}
|
||||
|
||||
/// Copied from the API 24+ AOSP source.
|
||||
static int floorDiv(int x, int y) {
|
||||
var r = x ~/ y;
|
||||
// if the signs are different and modulo not zero, round down
|
||||
if ((x ^ y) < 0 && (r * y != x)) {
|
||||
r--;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
@ -5,10 +5,11 @@ import '../../model/content/shape_trim_path.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../utils/path_factory.dart';
|
||||
import '../keyframe/base_keyframe_animation.dart';
|
||||
import '../keyframe/shape_keyframe_animation.dart';
|
||||
import 'compound_trim_path_content.dart';
|
||||
import 'content.dart';
|
||||
import 'path_content.dart';
|
||||
import 'shape_modifier_content.dart';
|
||||
import 'trim_path_content.dart';
|
||||
|
||||
class ShapeContent implements PathContent {
|
||||
@ -17,7 +18,7 @@ class ShapeContent implements PathContent {
|
||||
final ShapePath _shape;
|
||||
|
||||
final LottieDrawable lottieDrawable;
|
||||
final BaseKeyframeAnimation<Object, Path> _shapeAnimation;
|
||||
final ShapeKeyframeAnimation _shapeAnimation;
|
||||
|
||||
bool _isPathValid = false;
|
||||
final _trimPaths = CompoundTrimPathContent();
|
||||
@ -35,6 +36,7 @@ class ShapeContent implements PathContent {
|
||||
|
||||
@override
|
||||
void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
|
||||
List<ShapeModifierContent>? shapeModifierContents;
|
||||
for (var i = 0; i < contentsBefore.length; i++) {
|
||||
var content = contentsBefore[i];
|
||||
if (content is TrimPathContent &&
|
||||
@ -43,8 +45,12 @@ class ShapeContent implements PathContent {
|
||||
var trimPath = content;
|
||||
_trimPaths.addTrimPath(trimPath);
|
||||
trimPath.addListener(_invalidate);
|
||||
} else if (content is ShapeModifierContent) {
|
||||
shapeModifierContents ??= [];
|
||||
shapeModifierContents.add(content);
|
||||
}
|
||||
}
|
||||
_shapeAnimation.setShapeModifiers(shapeModifierContents);
|
||||
}
|
||||
|
||||
@override
|
||||
|
6
lib/src/animation/content/shape_modifier_content.dart
Normal file
6
lib/src/animation/content/shape_modifier_content.dart
Normal file
@ -0,0 +1,6 @@
|
||||
import '../../model/content/shape_data.dart';
|
||||
import 'content.dart';
|
||||
|
||||
abstract class ShapeModifierContent extends Content {
|
||||
ShapeData modifyShape(ShapeData shapeData);
|
||||
}
|
108
lib/src/animation/keyframe/drop_shadow_keyframe_animation.dart
Normal file
108
lib/src/animation/keyframe/drop_shadow_keyframe_animation.dart
Normal file
@ -0,0 +1,108 @@
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui';
|
||||
import '../../lottie_property.dart';
|
||||
import '../../model/content/drop_shadow_effect.dart';
|
||||
import '../../model/layer/base_layer.dart';
|
||||
import '../../value/drop_shadow.dart';
|
||||
import '../../value/lottie_frame_info.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import 'base_keyframe_animation.dart';
|
||||
import 'color_keyframe_animation.dart';
|
||||
|
||||
class DropShadowKeyframeAnimation {
|
||||
static const double _degToRad = math.pi / 180.0;
|
||||
|
||||
final void Function() listener;
|
||||
late final ColorKeyframeAnimation _color;
|
||||
late final BaseKeyframeAnimation<double, double> _opacity;
|
||||
late final BaseKeyframeAnimation<double, double> _direction;
|
||||
late final BaseKeyframeAnimation<double, double> _distance;
|
||||
late final BaseKeyframeAnimation<double, double> _radius;
|
||||
|
||||
Paint? _paint;
|
||||
|
||||
DropShadowKeyframeAnimation(
|
||||
this.listener, BaseLayer layer, DropShadowEffect dropShadowEffect) {
|
||||
_color = dropShadowEffect.color.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_color);
|
||||
_opacity = dropShadowEffect.opacity.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_opacity);
|
||||
_direction = dropShadowEffect.direction.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_direction);
|
||||
_distance = dropShadowEffect.distance.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_distance);
|
||||
_radius = dropShadowEffect.radius.createAnimation()
|
||||
..addUpdateListener(onValueChanged);
|
||||
layer.addAnimation(_radius);
|
||||
}
|
||||
|
||||
void onValueChanged() {
|
||||
_paint = null;
|
||||
listener();
|
||||
}
|
||||
|
||||
void draw(Canvas canvas, Path path) {
|
||||
var directionRad = _direction.value * _degToRad;
|
||||
var distance = _distance.value;
|
||||
var x = math.sin(directionRad) * distance;
|
||||
var y = math.cos(directionRad + math.pi) * distance;
|
||||
var baseColor = _color.value;
|
||||
var opacity = _opacity.value.round();
|
||||
var color = baseColor.withAlpha(opacity);
|
||||
var radius = _radius.value;
|
||||
|
||||
var sigma = radius * 0.57735 + 0.5;
|
||||
|
||||
var paint = _paint;
|
||||
paint ??= _paint = Paint()
|
||||
..color = color
|
||||
..maskFilter = MaskFilter.blur(BlurStyle.normal, sigma);
|
||||
|
||||
canvas.drawPath(path.shift(Offset(x, y)), paint);
|
||||
}
|
||||
|
||||
void setCallback(LottieValueCallback<DropShadow>? callback) {
|
||||
if (callback != null) {
|
||||
_color.setValueCallback(_createCallback(
|
||||
callback, (c) => c?.color ?? const Color(0xff000000)));
|
||||
_opacity.setValueCallback(
|
||||
_createCallback(callback, (c) => c?.color.alpha.toDouble() ?? 255));
|
||||
_direction.setValueCallback(
|
||||
_createCallback(callback, (c) => c?.direction ?? 0));
|
||||
_distance
|
||||
.setValueCallback(_createCallback(callback, (c) => c?.distance ?? 0));
|
||||
_radius
|
||||
.setValueCallback(_createCallback(callback, (c) => c?.radius ?? 0));
|
||||
} else {
|
||||
_color.setValueCallback(null);
|
||||
_opacity.setValueCallback(null);
|
||||
_direction.setValueCallback(null);
|
||||
_distance.setValueCallback(null);
|
||||
_radius.setValueCallback(null);
|
||||
}
|
||||
}
|
||||
|
||||
LottieValueCallback<T> _createCallback<T>(
|
||||
LottieValueCallback<DropShadow> callback,
|
||||
T Function(DropShadow?) selector) {
|
||||
return LottieValueCallback<T>(null)
|
||||
..callback = (info) {
|
||||
onValueChanged();
|
||||
var frameInfo = LottieFrameInfo<DropShadow>(
|
||||
info.startFrame,
|
||||
info.endFrame,
|
||||
LottieProperty.dropShadow,
|
||||
LottieProperty.dropShadow,
|
||||
info.linearKeyframeProgress,
|
||||
info.interpolatedKeyframeProgress,
|
||||
info.overallProgress,
|
||||
);
|
||||
var dropShadow = callback.getValue(frameInfo);
|
||||
return selector(dropShadow);
|
||||
};
|
||||
}
|
||||
}
|
@ -3,11 +3,13 @@ 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();
|
||||
List<ShapeModifierContent>? _shapeModifiers;
|
||||
|
||||
ShapeKeyframeAnimation(List<Keyframe<ShapeData>> keyframes)
|
||||
: super(keyframes);
|
||||
@ -19,7 +21,18 @@ class ShapeKeyframeAnimation extends BaseKeyframeAnimation<ShapeData, Path> {
|
||||
|
||||
_tempShapeData.interpolateBetween(
|
||||
startShapeData, endShapeData, keyframeProgress);
|
||||
MiscUtils.getPathFromData(_tempShapeData, _tempPath);
|
||||
var modifiedShapeData = _tempShapeData;
|
||||
var shapeModifiers = _shapeModifiers;
|
||||
if (shapeModifiers != null) {
|
||||
for (var i = shapeModifiers.length - 1; i >= 0; i--) {
|
||||
modifiedShapeData = shapeModifiers[i].modifyShape(modifiedShapeData);
|
||||
}
|
||||
}
|
||||
MiscUtils.getPathFromData(modifiedShapeData, _tempPath);
|
||||
return _tempPath;
|
||||
}
|
||||
|
||||
void setShapeModifiers(List<ShapeModifierContent>? shapeModifiers) {
|
||||
_shapeModifiers = shapeModifiers;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import '../../model/document_data.dart';
|
||||
import '../../value/keyframe.dart';
|
||||
import '../../value/lottie_frame_info.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import 'keyframe_animation.dart';
|
||||
|
||||
class TextKeyframeAnimation extends KeyframeAnimation<DocumentData> {
|
||||
@ -9,10 +11,58 @@ class TextKeyframeAnimation extends KeyframeAnimation<DocumentData> {
|
||||
@override
|
||||
DocumentData getValue(
|
||||
Keyframe<DocumentData> keyframe, double keyframeProgress) {
|
||||
if (keyframeProgress != 1.0 || keyframe.endValue == null) {
|
||||
var valueCallback = this.valueCallback;
|
||||
if (valueCallback != null) {
|
||||
return valueCallback.getValueInternal(
|
||||
keyframe.startFrame,
|
||||
keyframe.endFrame ?? double.maxFinite,
|
||||
keyframe.startValue,
|
||||
keyframe.endValue ?? keyframe.startValue,
|
||||
keyframeProgress,
|
||||
getInterpolatedCurrentKeyframeProgress(),
|
||||
progress)!;
|
||||
} else if (keyframeProgress != 1.0 || keyframe.endValue == null) {
|
||||
return keyframe.startValue!;
|
||||
} else {
|
||||
return keyframe.endValue!;
|
||||
}
|
||||
}
|
||||
|
||||
void setStringValueCallback(LottieValueCallback<String> valueCallback) {
|
||||
super.setValueCallback(_DocumentDataValueCallback(valueCallback));
|
||||
}
|
||||
}
|
||||
|
||||
class _DocumentDataValueCallback extends LottieValueCallback<DocumentData> {
|
||||
final LottieValueCallback<String> valueCallback;
|
||||
|
||||
_DocumentDataValueCallback(this.valueCallback) : super(null);
|
||||
|
||||
@override
|
||||
DocumentData getValue(LottieFrameInfo<DocumentData> frameInfo) {
|
||||
var stringFrameInfo = LottieFrameInfo<String>(
|
||||
frameInfo.startFrame,
|
||||
frameInfo.endFrame,
|
||||
frameInfo.startValue!.text,
|
||||
frameInfo.endValue!.text,
|
||||
frameInfo.linearKeyframeProgress,
|
||||
frameInfo.interpolatedKeyframeProgress,
|
||||
frameInfo.overallProgress);
|
||||
var text = valueCallback.getValue(stringFrameInfo)!;
|
||||
var baseDocumentData = frameInfo.interpolatedKeyframeProgress == 1
|
||||
? frameInfo.endValue!
|
||||
: frameInfo.startValue!;
|
||||
return DocumentData(
|
||||
text: text,
|
||||
fontName: baseDocumentData.fontName,
|
||||
size: baseDocumentData.size,
|
||||
justification: baseDocumentData.justification,
|
||||
tracking: baseDocumentData.tracking,
|
||||
lineHeight: baseDocumentData.lineHeight,
|
||||
baselineShift: baseDocumentData.baselineShift,
|
||||
color: baseDocumentData.color,
|
||||
strokeColor: baseDocumentData.strokeColor,
|
||||
strokeWidth: baseDocumentData.strokeWidth,
|
||||
strokeOverFill: baseDocumentData.strokeOverFill);
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,9 @@
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import '../lottie.dart';
|
||||
import 'composition.dart';
|
||||
import 'frame_rate.dart';
|
||||
import 'l.dart';
|
||||
import 'lottie_builder.dart';
|
||||
import 'options.dart';
|
||||
import 'providers/load_image.dart';
|
||||
|
||||
/// A widget to display a loaded [LottieComposition].
|
||||
/// The [controller] property allows to specify a custom AnimationController that
|
||||
@ -30,6 +26,7 @@ class Lottie extends StatefulWidget {
|
||||
this.delegates,
|
||||
this.options,
|
||||
bool? addRepaintBoundary,
|
||||
this.filterQuality,
|
||||
}) : animate = animate ?? true,
|
||||
reverse = reverse ?? false,
|
||||
repeat = repeat ?? true,
|
||||
@ -58,6 +55,7 @@ class Lottie extends StatefulWidget {
|
||||
Alignment? alignment,
|
||||
String? package,
|
||||
bool? addRepaintBoundary,
|
||||
FilterQuality? filterQuality,
|
||||
WarningCallback? onWarning,
|
||||
}) =>
|
||||
LottieBuilder.asset(
|
||||
@ -81,6 +79,7 @@ class Lottie extends StatefulWidget {
|
||||
alignment: alignment,
|
||||
package: package,
|
||||
addRepaintBoundary: addRepaintBoundary,
|
||||
filterQuality: filterQuality,
|
||||
onWarning: onWarning,
|
||||
);
|
||||
|
||||
@ -104,6 +103,7 @@ class Lottie extends StatefulWidget {
|
||||
BoxFit? fit,
|
||||
Alignment? alignment,
|
||||
bool? addRepaintBoundary,
|
||||
FilterQuality? filterQuality,
|
||||
WarningCallback? onWarning,
|
||||
}) =>
|
||||
LottieBuilder.file(
|
||||
@ -125,6 +125,7 @@ class Lottie extends StatefulWidget {
|
||||
fit: fit,
|
||||
alignment: alignment,
|
||||
addRepaintBoundary: addRepaintBoundary,
|
||||
filterQuality: filterQuality,
|
||||
onWarning: onWarning,
|
||||
);
|
||||
|
||||
@ -148,6 +149,7 @@ class Lottie extends StatefulWidget {
|
||||
BoxFit? fit,
|
||||
Alignment? alignment,
|
||||
bool? addRepaintBoundary,
|
||||
FilterQuality? filterQuality,
|
||||
WarningCallback? onWarning,
|
||||
}) =>
|
||||
LottieBuilder.memory(
|
||||
@ -169,6 +171,7 @@ class Lottie extends StatefulWidget {
|
||||
fit: fit,
|
||||
alignment: alignment,
|
||||
addRepaintBoundary: addRepaintBoundary,
|
||||
filterQuality: filterQuality,
|
||||
onWarning: onWarning,
|
||||
);
|
||||
|
||||
@ -192,6 +195,7 @@ class Lottie extends StatefulWidget {
|
||||
BoxFit? fit,
|
||||
Alignment? alignment,
|
||||
bool? addRepaintBoundary,
|
||||
FilterQuality? filterQuality,
|
||||
WarningCallback? onWarning,
|
||||
}) =>
|
||||
LottieBuilder.network(
|
||||
@ -213,6 +217,7 @@ class Lottie extends StatefulWidget {
|
||||
fit: fit,
|
||||
alignment: alignment,
|
||||
addRepaintBoundary: addRepaintBoundary,
|
||||
filterQuality: filterQuality,
|
||||
onWarning: onWarning,
|
||||
);
|
||||
|
||||
@ -303,13 +308,19 @@ class Lottie extends StatefulWidget {
|
||||
/// This property is `true` by default.
|
||||
final bool addRepaintBoundary;
|
||||
|
||||
/// The quality of the image layer. See [FilterQuality]
|
||||
/// [FilterQuality.high] is highest quality but slowest.
|
||||
///
|
||||
/// Defaults to [FilterQuality.none]
|
||||
final FilterQuality? filterQuality;
|
||||
|
||||
static bool get traceEnabled => L.traceEnabled;
|
||||
static set traceEnabled(bool enabled) {
|
||||
L.traceEnabled = enabled;
|
||||
}
|
||||
|
||||
@override
|
||||
_LottieState createState() => _LottieState();
|
||||
State<Lottie> createState() => _LottieState();
|
||||
}
|
||||
|
||||
class _LottieState extends State<Lottie> with TickerProviderStateMixin {
|
||||
@ -370,6 +381,7 @@ class _LottieState extends State<Lottie> with TickerProviderStateMixin {
|
||||
height: widget.height,
|
||||
fit: widget.fit,
|
||||
alignment: widget.alignment,
|
||||
filterQuality: widget.filterQuality,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -1,12 +1,12 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import '../lottie.dart';
|
||||
import 'composition.dart';
|
||||
import 'frame_rate.dart';
|
||||
import 'lottie.dart';
|
||||
import 'lottie_delegates.dart';
|
||||
import 'options.dart';
|
||||
import 'providers/asset_provider.dart';
|
||||
import 'providers/file_provider.dart';
|
||||
import 'providers/load_image.dart';
|
||||
@ -59,6 +59,7 @@ class LottieBuilder extends StatefulWidget {
|
||||
this.fit,
|
||||
this.alignment,
|
||||
this.addRepaintBoundary,
|
||||
this.filterQuality,
|
||||
this.onWarning,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -83,6 +84,7 @@ class LottieBuilder extends StatefulWidget {
|
||||
this.fit,
|
||||
this.alignment,
|
||||
this.addRepaintBoundary,
|
||||
this.filterQuality,
|
||||
this.onWarning,
|
||||
}) : lottie = NetworkLottie(src,
|
||||
headers: headers, imageProviderFactory: imageProviderFactory),
|
||||
@ -117,6 +119,7 @@ class LottieBuilder extends StatefulWidget {
|
||||
this.fit,
|
||||
this.alignment,
|
||||
this.addRepaintBoundary,
|
||||
this.filterQuality,
|
||||
this.onWarning,
|
||||
}) : lottie = FileLottie(file, imageProviderFactory: imageProviderFactory),
|
||||
super(key: key);
|
||||
@ -143,6 +146,7 @@ class LottieBuilder extends StatefulWidget {
|
||||
this.alignment,
|
||||
String? package,
|
||||
this.addRepaintBoundary,
|
||||
this.filterQuality,
|
||||
this.onWarning,
|
||||
}) : lottie = AssetLottie(name,
|
||||
bundle: bundle,
|
||||
@ -170,6 +174,7 @@ class LottieBuilder extends StatefulWidget {
|
||||
this.fit,
|
||||
this.alignment,
|
||||
this.addRepaintBoundary,
|
||||
this.filterQuality,
|
||||
this.onWarning,
|
||||
}) : lottie =
|
||||
MemoryLottie(bytes, imageProviderFactory: imageProviderFactory),
|
||||
@ -361,6 +366,12 @@ class LottieBuilder extends StatefulWidget {
|
||||
/// This property is `true` by default.
|
||||
final bool? addRepaintBoundary;
|
||||
|
||||
/// The quality of the image layer. See [FilterQuality]
|
||||
/// [FilterQuality.high] is highest quality but slowest.
|
||||
///
|
||||
/// Defaults to [FilterQuality.none]
|
||||
final FilterQuality? filterQuality;
|
||||
|
||||
/// A callback called when there is a warning during the loading or painting
|
||||
/// of the animation.
|
||||
final WarningCallback? onWarning;
|
||||
@ -398,7 +409,7 @@ class LottieBuilder extends StatefulWidget {
|
||||
final ImageErrorWidgetBuilder? errorBuilder;
|
||||
|
||||
@override
|
||||
_LottieBuilderState createState() => _LottieBuilderState();
|
||||
State<LottieBuilder> createState() => _LottieBuilderState();
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
@ -482,6 +493,7 @@ class _LottieBuilderState extends State<LottieBuilder> {
|
||||
fit: widget.fit,
|
||||
alignment: widget.alignment,
|
||||
addRepaintBoundary: widget.addRepaintBoundary,
|
||||
filterQuality: widget.filterQuality,
|
||||
);
|
||||
|
||||
if (widget.frameBuilder != null) {
|
||||
|
@ -1,7 +1,8 @@
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/widgets.dart';
|
||||
import '../lottie.dart';
|
||||
import 'composition.dart';
|
||||
import 'lottie_drawable.dart';
|
||||
import 'lottie_image_asset.dart';
|
||||
import 'value_delegate.dart';
|
||||
|
||||
// TODO(xha): recognize style Bold, Medium, Regular, SemiBold, etc...
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import 'composition.dart';
|
||||
import 'frame_rate.dart';
|
||||
import 'lottie_delegates.dart';
|
||||
@ -17,16 +16,15 @@ class LottieDrawable {
|
||||
final Size size;
|
||||
LottieDelegates? _delegates;
|
||||
bool _isDirty = true;
|
||||
final bool enableMergePaths;
|
||||
bool enableMergePaths = false;
|
||||
FilterQuality? filterQuality;
|
||||
|
||||
/// Gives a suggestion whether to paint with anti-aliasing, or not. Default is true.
|
||||
bool antiAliasingSuggested = true;
|
||||
|
||||
LottieDrawable(this.composition,
|
||||
{LottieDelegates? delegates, bool? enableMergePaths})
|
||||
LottieDrawable(this.composition, {LottieDelegates? delegates})
|
||||
: size = Size(composition.bounds.width.toDouble(),
|
||||
composition.bounds.height.toDouble()),
|
||||
enableMergePaths = enableMergePaths ?? false {
|
||||
composition.bounds.height.toDouble()) {
|
||||
this.delegates = delegates;
|
||||
_compositionLayer = CompositionLayer(
|
||||
this, LayerParser.parse(composition), composition.layers, composition);
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'dart:ui';
|
||||
import 'value/drop_shadow.dart';
|
||||
|
||||
/// Property values are the same type as the generic type of their corresponding
|
||||
/// {@link LottieValueCallback}. With this, we can use generics to maintain type safety
|
||||
@ -122,8 +123,18 @@ abstract class LottieProperty {
|
||||
/// In Dp
|
||||
static const double textSize = 28.0;
|
||||
|
||||
/// In Px
|
||||
static const double blurRadius = 29.0;
|
||||
|
||||
static const dropShadow = DropShadow(
|
||||
color: Color(0x00000000), direction: 0, distance: 0, radius: 0);
|
||||
|
||||
/// Set the color filter for an entire drawable content. Can be applied to fills, strokes, images, and solids.
|
||||
static const ColorFilter colorFilter =
|
||||
ColorFilter.mode(Color(0xFF000000), BlendMode.dst);
|
||||
|
||||
static final List<Color> gradientColor = [];
|
||||
|
||||
/// Replace the text for a text layer.
|
||||
static const text = 'dynamic_text';
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'dart:ui';
|
||||
import '../../animation/keyframe/base_keyframe_animation.dart';
|
||||
import '../../animation/keyframe/shape_keyframe_animation.dart';
|
||||
import '../../value/keyframe.dart';
|
||||
import '../content/shape_data.dart';
|
||||
@ -10,7 +9,7 @@ class AnimatableShapeValue extends BaseAnimatableValue<ShapeData, Path> {
|
||||
: super.fromKeyframes(keyframes);
|
||||
|
||||
@override
|
||||
BaseKeyframeAnimation<ShapeData, Path> createAnimation() {
|
||||
ShapeKeyframeAnimation createAnimation() {
|
||||
return ShapeKeyframeAnimation(keyframes);
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ abstract class BaseAnimatableValue<V extends Object, O extends Object>
|
||||
String toString() {
|
||||
final sb = StringBuffer();
|
||||
if (keyframes.isNotEmpty) {
|
||||
sb..write('values=')..write('$keyframes');
|
||||
sb
|
||||
..write('values=')
|
||||
..write('$keyframes');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
7
lib/src/model/content/blur_effect.dart
Normal file
7
lib/src/model/content/blur_effect.dart
Normal file
@ -0,0 +1,7 @@
|
||||
import '../animatable/animatable_double_value.dart';
|
||||
|
||||
class BlurEffect {
|
||||
final AnimatableDoubleValue blurriness;
|
||||
|
||||
BlurEffect(this.blurriness);
|
||||
}
|
29
lib/src/model/content/drop_shadow_effect.dart
Normal file
29
lib/src/model/content/drop_shadow_effect.dart
Normal file
@ -0,0 +1,29 @@
|
||||
import 'package:flutter/painting.dart';
|
||||
import '../../value/keyframe.dart';
|
||||
import '../animatable/animatable_color_value.dart';
|
||||
import '../animatable/animatable_double_value.dart';
|
||||
|
||||
class DropShadowEffect {
|
||||
final AnimatableColorValue color;
|
||||
final AnimatableDoubleValue opacity;
|
||||
final AnimatableDoubleValue direction;
|
||||
final AnimatableDoubleValue distance;
|
||||
final AnimatableDoubleValue radius;
|
||||
|
||||
DropShadowEffect({
|
||||
required this.color,
|
||||
required this.opacity,
|
||||
required this.direction,
|
||||
required this.distance,
|
||||
required this.radius,
|
||||
});
|
||||
|
||||
static DropShadowEffect createEmpty() => DropShadowEffect(
|
||||
color: AnimatableColorValue.fromKeyframes(
|
||||
[Keyframe.nonAnimated(const Color(0x00000000))]),
|
||||
direction: AnimatableDoubleValue(),
|
||||
radius: AnimatableDoubleValue(),
|
||||
distance: AnimatableDoubleValue(),
|
||||
opacity: AnimatableDoubleValue(),
|
||||
);
|
||||
}
|
@ -37,6 +37,7 @@ class PolystarShape implements ContentModel {
|
||||
final AnimatableDoubleValue? innerRoundedness;
|
||||
final AnimatableDoubleValue outerRoundedness;
|
||||
final bool hidden;
|
||||
final bool isReversed;
|
||||
|
||||
PolystarShape({
|
||||
this.name,
|
||||
@ -49,6 +50,7 @@ class PolystarShape implements ContentModel {
|
||||
this.innerRoundedness,
|
||||
required this.outerRoundedness,
|
||||
required this.hidden,
|
||||
required this.isReversed,
|
||||
});
|
||||
|
||||
@override
|
||||
|
18
lib/src/model/content/rounded_corners.dart
Normal file
18
lib/src/model/content/rounded_corners.dart
Normal file
@ -0,0 +1,18 @@
|
||||
import '../../animation/content/content.dart';
|
||||
import '../../animation/content/rounded_corners_content.dart';
|
||||
import '../../lottie_drawable.dart';
|
||||
import '../animatable/animatable_value.dart';
|
||||
import '../layer/base_layer.dart';
|
||||
import 'content_model.dart';
|
||||
|
||||
class RoundedCorners implements ContentModel {
|
||||
final String name;
|
||||
final AnimatableValue<double, double> cornerRadius;
|
||||
|
||||
RoundedCorners(this.name, this.cornerRadius);
|
||||
|
||||
@override
|
||||
Content toContent(LottieDrawable drawable, BaseLayer layer) {
|
||||
return RoundedCornersContent(drawable, layer, this);
|
||||
}
|
||||
}
|
@ -22,6 +22,10 @@ class ShapeData {
|
||||
return _initialPoint;
|
||||
}
|
||||
|
||||
void setClosed(bool closed) {
|
||||
_closed = closed;
|
||||
}
|
||||
|
||||
bool get isClosed {
|
||||
return _closed;
|
||||
}
|
||||
|
@ -1,7 +1,44 @@
|
||||
import 'dart:ui';
|
||||
|
||||
/// One cubic path operation. CubicCurveData is structured such that it is easy to iterate through
|
||||
/// it and build a path. However, it is modeled differently than most path operations.
|
||||
///
|
||||
/// CubicCurveData
|
||||
/// | - vertex
|
||||
/// | /
|
||||
/// | cp1 cp2
|
||||
/// | /
|
||||
/// | |
|
||||
/// | /
|
||||
/// --------------------------
|
||||
///
|
||||
/// When incrementally building a path, it will already have a "current point" so that is
|
||||
/// not captured in this data structure.
|
||||
/// The control points here represent {@link android.graphics.Path#cubicTo(float, float, float, float, float, float)}.
|
||||
///
|
||||
/// Most path operations are centered around a vertex and its in control point and out control point like this:
|
||||
/// | outCp
|
||||
/// | /
|
||||
/// | |
|
||||
/// | v
|
||||
/// | /
|
||||
/// | inCp
|
||||
/// --------------------------
|
||||
class CubicCurveData {
|
||||
Offset controlPoint1 = Offset.zero;
|
||||
Offset controlPoint2 = Offset.zero;
|
||||
Offset vertex = Offset.zero;
|
||||
|
||||
void setFrom(CubicCurveData curveData) {
|
||||
vertex = Offset(curveData.vertex.dx, curveData.vertex.dy);
|
||||
controlPoint1 =
|
||||
Offset(curveData.controlPoint1.dx, curveData.controlPoint1.dy);
|
||||
controlPoint2 =
|
||||
Offset(curveData.controlPoint2.dx, curveData.controlPoint2.dy);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'v=$vertex cp1$controlPoint1 cp2=$controlPoint2';
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import 'dart:math';
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart' hide Layer;
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import '../../animation/content/content.dart';
|
||||
import '../../animation/content/drawing_content.dart';
|
||||
import '../../animation/keyframe/base_keyframe_animation.dart';
|
||||
@ -14,6 +13,8 @@ import '../../l.dart';
|
||||
import '../../lottie_drawable.dart';
|
||||
import '../../utils.dart';
|
||||
import '../../value/lottie_value_callback.dart';
|
||||
import '../content/blur_effect.dart';
|
||||
import '../content/drop_shadow_effect.dart';
|
||||
import '../content/mask.dart';
|
||||
import '../content/shape_data.dart';
|
||||
import '../key_path.dart';
|
||||
@ -27,11 +28,14 @@ import 'solid_layer.dart';
|
||||
import 'text_layer.dart';
|
||||
|
||||
abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
static BaseLayer? forModel(Layer layerModel, LottieDrawable drawable,
|
||||
static BaseLayer? forModel(
|
||||
CompositionLayer compositionLayer,
|
||||
Layer layerModel,
|
||||
LottieDrawable drawable,
|
||||
LottieComposition composition) {
|
||||
switch (layerModel.layerType) {
|
||||
case LayerType.shape:
|
||||
return ShapeLayer(drawable, layerModel);
|
||||
return ShapeLayer(drawable, layerModel, compositionLayer);
|
||||
case LayerType.preComp:
|
||||
return CompositionLayer(drawable, layerModel,
|
||||
composition.getPrecomps(layerModel.refId)!, composition);
|
||||
@ -77,6 +81,9 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
final TransformKeyframeAnimation transform;
|
||||
bool _visible = true;
|
||||
|
||||
double blurMaskFilterRadius = 0;
|
||||
MaskFilter? blurMaskFilter;
|
||||
|
||||
BaseLayer(this.lottieDrawable, this.layerModel)
|
||||
: _drawTraceName = '${layerModel.name}#draw',
|
||||
transform = layerModel.transform.createAnimation() {
|
||||
@ -547,6 +554,22 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
return layerModel.name;
|
||||
}
|
||||
|
||||
BlurEffect? get blurEffect {
|
||||
return layerModel.blurEffect;
|
||||
}
|
||||
|
||||
MaskFilter? getBlurMaskFilter(double radius) {
|
||||
if (blurMaskFilterRadius == radius) {
|
||||
return blurMaskFilter;
|
||||
}
|
||||
var sigma = radius * 0.57735 + 0.5;
|
||||
blurMaskFilter = MaskFilter.blur(BlurStyle.normal, sigma);
|
||||
blurMaskFilterRadius = radius;
|
||||
return blurMaskFilter;
|
||||
}
|
||||
|
||||
DropShadowEffect? get dropShadowEffect => layerModel.dropShadowEffect;
|
||||
|
||||
@override
|
||||
void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
|
||||
// Do nothing
|
||||
|
@ -36,7 +36,7 @@ class CompositionLayer extends BaseLayer {
|
||||
BaseLayer? mattedLayer;
|
||||
for (var i = layerModels.length - 1; i >= 0; i--) {
|
||||
var lm = layerModels[i];
|
||||
var layer = BaseLayer.forModel(lm, lottieDrawable, composition);
|
||||
var layer = BaseLayer.forModel(this, lm, lottieDrawable, composition);
|
||||
if (layer == null) {
|
||||
continue;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ class ImageLayer extends BaseLayer {
|
||||
}
|
||||
var density = window.devicePixelRatio;
|
||||
|
||||
paint.filterQuality = lottieDrawable.filterQuality ?? FilterQuality.none;
|
||||
paint.setAlpha(parentAlpha);
|
||||
if (_colorFilterAnimation != null) {
|
||||
paint.colorFilter = _colorFilterAnimation!.value;
|
||||
|
@ -5,7 +5,9 @@ import '../animatable/animatable_double_value.dart';
|
||||
import '../animatable/animatable_text_frame.dart';
|
||||
import '../animatable/animatable_text_properties.dart';
|
||||
import '../animatable/animatable_transform.dart';
|
||||
import '../content/blur_effect.dart';
|
||||
import '../content/content_model.dart';
|
||||
import '../content/drop_shadow_effect.dart';
|
||||
import '../content/mask.dart';
|
||||
|
||||
enum LayerType { preComp, solid, image, nullLayer, shape, text, unknown }
|
||||
@ -35,6 +37,8 @@ class Layer {
|
||||
final MatteType matteType;
|
||||
final AnimatableDoubleValue? timeRemapping;
|
||||
final bool isHidden;
|
||||
final BlurEffect? blurEffect;
|
||||
final DropShadowEffect? dropShadowEffect;
|
||||
|
||||
double get startProgress {
|
||||
return startFrame / composition.durationFrames;
|
||||
@ -63,6 +67,8 @@ class Layer {
|
||||
required this.matteType,
|
||||
this.timeRemapping,
|
||||
required this.isHidden,
|
||||
this.blurEffect,
|
||||
this.dropShadowEffect,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -71,19 +77,32 @@ class Layer {
|
||||
}
|
||||
|
||||
String toStringWithPrefix(String prefix) {
|
||||
var sb = StringBuffer()..write(prefix)..write(name)..write('\n');
|
||||
var sb = StringBuffer()
|
||||
..write(prefix)
|
||||
..write(name)
|
||||
..write('\n');
|
||||
var parent = composition.layerModelForId(parentId);
|
||||
if (parent != null) {
|
||||
sb..write('\t\tParents: ')..write(parent.name);
|
||||
sb
|
||||
..write('\t\tParents: ')
|
||||
..write(parent.name);
|
||||
parent = composition.layerModelForId(parent.parentId);
|
||||
while (parent != null) {
|
||||
sb..write('->')..write(parent.name);
|
||||
sb
|
||||
..write('->')
|
||||
..write(parent.name);
|
||||
parent = composition.layerModelForId(parent.parentId);
|
||||
}
|
||||
sb..write(prefix)..write('\n');
|
||||
sb
|
||||
..write(prefix)
|
||||
..write('\n');
|
||||
}
|
||||
if (masks.isNotEmpty) {
|
||||
sb..write(prefix)..write('\tMasks: ')..write(masks.length)..write('\n');
|
||||
sb
|
||||
..write(prefix)
|
||||
..write('\tMasks: ')
|
||||
..write(masks.length)
|
||||
..write('\n');
|
||||
}
|
||||
if (solidWidth != 0 && solidHeight != 0) {
|
||||
sb
|
||||
@ -92,9 +111,15 @@ class Layer {
|
||||
..write('${solidWidth}x$solidHeight $solidColor');
|
||||
}
|
||||
if (shapes.isNotEmpty) {
|
||||
sb..write(prefix)..write('\tShapes:\n');
|
||||
sb
|
||||
..write(prefix)
|
||||
..write('\tShapes:\n');
|
||||
for (Object shape in shapes) {
|
||||
sb..write(prefix)..write('\t\t')..write(shape)..write('\n');
|
||||
sb
|
||||
..write(prefix)
|
||||
..write('\t\t')
|
||||
..write(shape)
|
||||
..write('\n');
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
|
@ -3,15 +3,20 @@ import 'package:vector_math/vector_math_64.dart';
|
||||
import '../../animation/content/content.dart';
|
||||
import '../../animation/content/content_group.dart';
|
||||
import '../../lottie_drawable.dart';
|
||||
import '../content/blur_effect.dart';
|
||||
import '../content/drop_shadow_effect.dart';
|
||||
import '../content/shape_group.dart';
|
||||
import '../key_path.dart';
|
||||
import 'base_layer.dart';
|
||||
import 'composition_layer.dart';
|
||||
import 'layer.dart';
|
||||
|
||||
class ShapeLayer extends BaseLayer {
|
||||
late ContentGroup _contentGroup;
|
||||
final CompositionLayer _compositionLayer;
|
||||
|
||||
ShapeLayer(LottieDrawable lottieDrawable, Layer layerModel)
|
||||
ShapeLayer(
|
||||
LottieDrawable lottieDrawable, Layer layerModel, this._compositionLayer)
|
||||
: super(lottieDrawable, layerModel) {
|
||||
// Naming this __container allows it to be ignored in KeyPath matching.
|
||||
var shapeGroup =
|
||||
@ -34,6 +39,24 @@ class ShapeLayer extends BaseLayer {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@override
|
||||
BlurEffect? get blurEffect {
|
||||
var layerBlur = super.blurEffect;
|
||||
if (layerBlur != null) {
|
||||
return layerBlur;
|
||||
}
|
||||
return _compositionLayer.blurEffect;
|
||||
}
|
||||
|
||||
@override
|
||||
DropShadowEffect? get dropShadowEffect {
|
||||
var layerDropShadow = super.dropShadowEffect;
|
||||
if (layerDropShadow != null) {
|
||||
return layerDropShadow;
|
||||
}
|
||||
return _compositionLayer.dropShadowEffect;
|
||||
}
|
||||
|
||||
@override
|
||||
void resolveChildKeyPath(KeyPath keyPath, int depth,
|
||||
List<KeyPath> accumulator, KeyPath currentPartialKeyPath) {
|
||||
|
@ -1,7 +1,5 @@
|
||||
import 'dart:ui';
|
||||
import 'package:characters/characters.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import '../../animation/content/content_group.dart';
|
||||
import '../../animation/keyframe/base_keyframe_animation.dart';
|
||||
import '../../animation/keyframe/text_keyframe_animation.dart';
|
||||
@ -486,6 +484,11 @@ class TextLayer extends BaseLayer {
|
||||
..addUpdateListener(invalidateSelf);
|
||||
addAnimation(_textSizeCallbackAnimation);
|
||||
}
|
||||
} else if (property == LottieProperty.text) {
|
||||
if (callback != null) {
|
||||
_textAnimation
|
||||
.setStringValueCallback(callback as LottieValueCallback<String>);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
60
lib/src/parser/blur_effect_parser.dart
Normal file
60
lib/src/parser/blur_effect_parser.dart
Normal file
@ -0,0 +1,60 @@
|
||||
import '../composition.dart';
|
||||
import '../model/content/blur_effect.dart';
|
||||
import 'animatable_value_parser.dart';
|
||||
import 'moshi/json_reader.dart';
|
||||
|
||||
class BlurEffectParser {
|
||||
static final JsonReaderOptions _blurEffectNames =
|
||||
JsonReaderOptions.of(['ef']);
|
||||
static final JsonReaderOptions _innerBlurEffectNames =
|
||||
JsonReaderOptions.of(['ty', 'v']);
|
||||
|
||||
static BlurEffect? parse(JsonReader reader, LottieComposition composition) {
|
||||
BlurEffect? blurEffect;
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_blurEffectNames)) {
|
||||
case 0:
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
var be = _maybeParseInnerEffect(reader, composition);
|
||||
if (be != null) {
|
||||
blurEffect = be;
|
||||
}
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
return blurEffect;
|
||||
}
|
||||
|
||||
static BlurEffect? _maybeParseInnerEffect(
|
||||
JsonReader reader, LottieComposition composition) {
|
||||
BlurEffect? blurEffect;
|
||||
var isCorrectType = false;
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_innerBlurEffectNames)) {
|
||||
case 0:
|
||||
isCorrectType = reader.nextInt() == 0;
|
||||
break;
|
||||
case 1:
|
||||
if (isCorrectType) {
|
||||
blurEffect = BlurEffect(
|
||||
AnimatableValueParser.parseFloat(reader, composition));
|
||||
} else {
|
||||
reader.skipValue();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
return blurEffect;
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import 'moshi/json_reader.dart';
|
||||
import 'polysar_shape_parser.dart';
|
||||
import 'rectangle_shape_parser.dart';
|
||||
import 'repeat_parser.dart';
|
||||
import 'rounded_corners_parser.dart';
|
||||
import 'shape_fill_parser.dart';
|
||||
import 'shape_group_parser.dart';
|
||||
import 'shape_path_parser.dart';
|
||||
@ -80,7 +81,7 @@ class ContentModelParser {
|
||||
model = ShapeTrimPathParser.parse(reader, composition);
|
||||
break;
|
||||
case 'sr':
|
||||
model = PolystarShapeParser.parse(reader, composition);
|
||||
model = PolystarShapeParser.parse(reader, composition, d: d);
|
||||
break;
|
||||
case 'mm':
|
||||
model = MergePathsParser.parse(reader);
|
||||
@ -88,6 +89,9 @@ class ContentModelParser {
|
||||
case 'rp':
|
||||
model = RepeaterParser.parse(reader, composition);
|
||||
break;
|
||||
case 'rd':
|
||||
model = RoundedCornersParser.parse(reader, composition);
|
||||
break;
|
||||
default:
|
||||
composition.addWarning('Unknown shape type $type');
|
||||
}
|
||||
|
@ -3,8 +3,19 @@ import '../model/document_data.dart';
|
||||
import 'json_utils.dart';
|
||||
import 'moshi/json_reader.dart';
|
||||
|
||||
final JsonReaderOptions _names = JsonReaderOptions.of(
|
||||
['t', 'f', 's', 'j', 'tr', 'lh', 'ls', 'fc', 'sc', 'sw', 'of']);
|
||||
final JsonReaderOptions _names = JsonReaderOptions.of([
|
||||
't', // 0
|
||||
'f', // 1
|
||||
's', // 2
|
||||
'j', // 3
|
||||
'tr', // 4
|
||||
'lh', // 5
|
||||
'ls', // 6
|
||||
'fc', // 7
|
||||
'sc', // 8
|
||||
'sw', // 9
|
||||
'of', // 10
|
||||
]);
|
||||
|
||||
DocumentData documentDataParser(JsonReader reader, {required double scale}) {
|
||||
String? text;
|
||||
|
97
lib/src/parser/drop_shadow_effect_parser.dart
Normal file
97
lib/src/parser/drop_shadow_effect_parser.dart
Normal file
@ -0,0 +1,97 @@
|
||||
import '../composition.dart';
|
||||
import '../model/animatable/animatable_color_value.dart';
|
||||
import '../model/animatable/animatable_double_value.dart';
|
||||
import '../model/content/drop_shadow_effect.dart';
|
||||
import 'animatable_value_parser.dart';
|
||||
import 'moshi/json_reader.dart';
|
||||
|
||||
class DropShadowEffectParser {
|
||||
static final JsonReaderOptions _dropShadowEffectNames =
|
||||
JsonReaderOptions.of(['ef']);
|
||||
|
||||
static final JsonReaderOptions _innerEffectNames =
|
||||
JsonReaderOptions.of(['nm', 'v']);
|
||||
|
||||
AnimatableColorValue? _color;
|
||||
AnimatableDoubleValue? _opacity;
|
||||
AnimatableDoubleValue? _direction;
|
||||
AnimatableDoubleValue? _distance;
|
||||
AnimatableDoubleValue? _radius;
|
||||
|
||||
DropShadowEffect? parse(JsonReader reader, LottieComposition composition) {
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_dropShadowEffectNames)) {
|
||||
case 0:
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
_maybeParseInnerEffect(reader, composition);
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
|
||||
var color = _color;
|
||||
var opacity = _opacity;
|
||||
var direction = _direction;
|
||||
var distance = _distance;
|
||||
var radius = _radius;
|
||||
if (color != null &&
|
||||
opacity != null &&
|
||||
direction != null &&
|
||||
distance != null &&
|
||||
radius != null) {
|
||||
return DropShadowEffect(
|
||||
color: color,
|
||||
opacity: opacity,
|
||||
direction: direction,
|
||||
distance: distance,
|
||||
radius: radius);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void _maybeParseInnerEffect(
|
||||
JsonReader reader, LottieComposition composition) {
|
||||
var currentEffectName = '';
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_innerEffectNames)) {
|
||||
case 0:
|
||||
currentEffectName = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
switch (currentEffectName) {
|
||||
case 'Shadow Color':
|
||||
_color = AnimatableValueParser.parseColor(reader, composition);
|
||||
break;
|
||||
case 'Opacity':
|
||||
_opacity = AnimatableValueParser.parseFloat(reader, composition,
|
||||
isDp: false);
|
||||
break;
|
||||
case 'Direction':
|
||||
_direction = AnimatableValueParser.parseFloat(reader, composition,
|
||||
isDp: false);
|
||||
break;
|
||||
case 'Distance':
|
||||
_distance = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 'Softness':
|
||||
_radius = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
}
|
||||
}
|
@ -37,6 +37,17 @@ class GradientColorParser {
|
||||
while (reader.hasNext()) {
|
||||
array.add(reader.nextDouble());
|
||||
}
|
||||
if (array.length == 4 && array[0] == 1) {
|
||||
// If a gradient color only contains one color at position 1, add a second stop with the same
|
||||
// color at position 0. Android's LinearGradient shader requires at least two colors.
|
||||
// https://github.com/airbnb/lottie-android/issues/1967
|
||||
array[0] = 0;
|
||||
array.add(1);
|
||||
array.add(array[1]);
|
||||
array.add(array[2]);
|
||||
array.add(array[3]);
|
||||
_colorPoints = 2;
|
||||
}
|
||||
if (isArray) {
|
||||
reader.endArray();
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ class KeyframeParser {
|
||||
/// PathInterpolator fails to create the interpolator in those cases and hangs.
|
||||
/// Clamping the cp helps prevent that.
|
||||
static const _maxCpValue = 100.0;
|
||||
static final _linearInterpolator = Curves.linear;
|
||||
static const _linearInterpolator = Curves.linear;
|
||||
static final _pathInterpolatorCache = <int, Curve>{};
|
||||
|
||||
static final JsonReaderOptions _names =
|
||||
@ -302,7 +302,7 @@ class KeyframeParser {
|
||||
|
||||
interpolator = _pathInterpolatorCache.putIfAbsent(hash, () {
|
||||
try {
|
||||
return Cubic(cp1.dx, cp1.dy, cp2.dx, cp2.dy);
|
||||
return PathInterpolator.cubic(cp1.dx, cp1.dy, cp2.dx, cp2.dy);
|
||||
} catch (e) {
|
||||
debugPrint('DEBUG: Path interpolator error $e');
|
||||
//TODO(xha): check the error message for Flutter
|
||||
|
@ -4,7 +4,9 @@ import '../model/animatable/animatable_double_value.dart';
|
||||
import '../model/animatable/animatable_text_frame.dart';
|
||||
import '../model/animatable/animatable_text_properties.dart';
|
||||
import '../model/animatable/animatable_transform.dart';
|
||||
import '../model/content/blur_effect.dart';
|
||||
import '../model/content/content_model.dart';
|
||||
import '../model/content/drop_shadow_effect.dart';
|
||||
import '../model/content/mask.dart';
|
||||
import '../model/layer/layer.dart';
|
||||
import '../utils/misc.dart';
|
||||
@ -12,7 +14,9 @@ import '../value/keyframe.dart';
|
||||
import 'animatable_text_properties_parser.dart';
|
||||
import 'animatable_transform_parser.dart';
|
||||
import 'animatable_value_parser.dart';
|
||||
import 'blur_effect_parser.dart';
|
||||
import 'content_model_parser.dart';
|
||||
import 'drop_shadow_effect_parser.dart';
|
||||
import 'mask_parser.dart';
|
||||
import 'moshi/json_reader.dart';
|
||||
|
||||
@ -74,7 +78,8 @@ class LayerParser {
|
||||
|
||||
static final JsonReaderOptions _textNames = JsonReaderOptions.of(['d', 'a']);
|
||||
|
||||
static final JsonReaderOptions _effectsNames = JsonReaderOptions.of(['nm']);
|
||||
static final JsonReaderOptions _effectsNames =
|
||||
JsonReaderOptions.of(['ty', 'nm']);
|
||||
|
||||
static Layer parseJson(JsonReader reader, LottieComposition composition) {
|
||||
// This should always be set by After Effects. However, if somebody wants to minify
|
||||
@ -95,6 +100,8 @@ class LayerParser {
|
||||
var outFrame = 0.0;
|
||||
String? cl;
|
||||
var hidden = false;
|
||||
BlurEffect? blurEffect;
|
||||
DropShadowEffect? dropShadowEffect;
|
||||
|
||||
var matteType = MatteType.none;
|
||||
AnimatableTransform? transform;
|
||||
@ -207,7 +214,17 @@ class LayerParser {
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_effectsNames)) {
|
||||
case 0:
|
||||
effectNames.add(reader.nextString());
|
||||
var type = reader.nextInt();
|
||||
if (type == 29) {
|
||||
blurEffect = BlurEffectParser.parse(reader, composition);
|
||||
} else if (type == 25) {
|
||||
dropShadowEffect =
|
||||
DropShadowEffectParser().parse(reader, composition);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
var effectName = reader.nextString();
|
||||
effectNames.add(effectName);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
@ -292,27 +309,30 @@ class LayerParser {
|
||||
}
|
||||
|
||||
return Layer(
|
||||
shapes: shapes,
|
||||
composition: composition,
|
||||
name: layerName,
|
||||
id: layerId,
|
||||
layerType: layerType,
|
||||
parentId: parentId,
|
||||
refId: refId,
|
||||
masks: masks,
|
||||
transform: transform!,
|
||||
solidWidth: solidWidth,
|
||||
solidHeight: solidHeight,
|
||||
solidColor: solidColor,
|
||||
timeStretch: timeStretch,
|
||||
startFrame: startFrame,
|
||||
preCompWidth: preCompWidth,
|
||||
preCompHeight: preCompHeight,
|
||||
text: text,
|
||||
textProperties: textProperties,
|
||||
inOutKeyframes: inOutKeyframes,
|
||||
matteType: matteType,
|
||||
timeRemapping: timeRemapping,
|
||||
isHidden: hidden);
|
||||
shapes: shapes,
|
||||
composition: composition,
|
||||
name: layerName,
|
||||
id: layerId,
|
||||
layerType: layerType,
|
||||
parentId: parentId,
|
||||
refId: refId,
|
||||
masks: masks,
|
||||
transform: transform!,
|
||||
solidWidth: solidWidth,
|
||||
solidHeight: solidHeight,
|
||||
solidColor: solidColor,
|
||||
timeStretch: timeStretch,
|
||||
startFrame: startFrame,
|
||||
preCompWidth: preCompWidth,
|
||||
preCompHeight: preCompHeight,
|
||||
text: text,
|
||||
textProperties: textProperties,
|
||||
inOutKeyframes: inOutKeyframes,
|
||||
matteType: matteType,
|
||||
timeRemapping: timeRemapping,
|
||||
isHidden: hidden,
|
||||
blurEffect: blurEffect,
|
||||
dropShadowEffect: dropShadowEffect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,10 @@ class JsonScope {
|
||||
switch (stack[i]) {
|
||||
case emptyArray:
|
||||
case nonEmptyArray:
|
||||
result..write('[')..write(pathIndices[i])..write(']');
|
||||
result
|
||||
..write('[')
|
||||
..write(pathIndices[i])
|
||||
..write(']');
|
||||
break;
|
||||
|
||||
case emptyObject:
|
||||
|
@ -9,11 +9,12 @@ import 'moshi/json_reader.dart';
|
||||
|
||||
class PolystarShapeParser {
|
||||
static final JsonReaderOptions _names = JsonReaderOptions.of(
|
||||
['nm', 'sy', 'pt', 'p', 'r', 'or', 'os', 'ir', 'is', 'hd']);
|
||||
['nm', 'sy', 'pt', 'p', 'r', 'or', 'os', 'ir', 'is', 'hd', 'd']);
|
||||
|
||||
PolystarShapeParser._();
|
||||
|
||||
static PolystarShape parse(JsonReader reader, LottieComposition composition) {
|
||||
static PolystarShape parse(JsonReader reader, LottieComposition composition,
|
||||
{required int d}) {
|
||||
String? name;
|
||||
PolystarShapeType? type;
|
||||
late AnimatableDoubleValue points;
|
||||
@ -24,6 +25,7 @@ class PolystarShapeParser {
|
||||
AnimatableDoubleValue? innerRadius;
|
||||
AnimatableDoubleValue? innerRoundedness;
|
||||
var hidden = false;
|
||||
var reversed = d == 3;
|
||||
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_names)) {
|
||||
@ -64,6 +66,10 @@ class PolystarShapeParser {
|
||||
case 9:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
case 10:
|
||||
// "d" is 2 for normal and 3 for reversed.
|
||||
reversed = reader.nextInt() == 3;
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -81,6 +87,7 @@ class PolystarShapeParser {
|
||||
innerRoundedness: innerRoundedness,
|
||||
outerRoundedness: outerRoundedness,
|
||||
hidden: hidden,
|
||||
isReversed: reversed,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
39
lib/src/parser/rounded_corners_parser.dart
Normal file
39
lib/src/parser/rounded_corners_parser.dart
Normal file
@ -0,0 +1,39 @@
|
||||
import '../composition.dart';
|
||||
import '../model/animatable/animatable_value.dart';
|
||||
import '../model/content/rounded_corners.dart';
|
||||
import 'animatable_value_parser.dart';
|
||||
import 'moshi/json_reader.dart';
|
||||
|
||||
class RoundedCornersParser {
|
||||
static final _names = JsonReaderOptions.of([
|
||||
'nm', // 0
|
||||
'r', // 1
|
||||
'hd' // 1
|
||||
]);
|
||||
|
||||
static RoundedCorners? parse(
|
||||
JsonReader reader, LottieComposition composition) {
|
||||
String? name;
|
||||
AnimatableValue<double, double>? cornerRadius;
|
||||
var hidden = false;
|
||||
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0: //nm
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1: // r
|
||||
cornerRadius =
|
||||
AnimatableValueParser.parseFloat(reader, composition, isDp: true);
|
||||
break;
|
||||
case 2: // hd
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
|
||||
return hidden ? null : RoundedCorners(name!, cornerRadius!);
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import '../lottie.dart';
|
||||
import 'composition.dart';
|
||||
import 'frame_rate.dart';
|
||||
import 'lottie_delegates.dart';
|
||||
import 'lottie_drawable.dart';
|
||||
import 'options.dart';
|
||||
import 'render_lottie.dart';
|
||||
|
||||
/// A widget that displays a [LottieDrawable] directly.
|
||||
@ -21,6 +23,7 @@ class RawLottie extends LeafRenderObjectWidget {
|
||||
this.height,
|
||||
this.fit,
|
||||
AlignmentGeometry? alignment,
|
||||
this.filterQuality,
|
||||
}) : progress = progress ?? 0.0,
|
||||
alignment = alignment ?? Alignment.center,
|
||||
super(key: key);
|
||||
@ -76,6 +79,8 @@ class RawLottie extends LeafRenderObjectWidget {
|
||||
/// relative to text direction.
|
||||
final AlignmentGeometry alignment;
|
||||
|
||||
final FilterQuality? filterQuality;
|
||||
|
||||
@override
|
||||
RenderLottie createRenderObject(BuildContext context) {
|
||||
return RenderLottie(
|
||||
@ -88,17 +93,21 @@ class RawLottie extends LeafRenderObjectWidget {
|
||||
height: height,
|
||||
fit: fit,
|
||||
alignment: alignment,
|
||||
filterQuality: filterQuality,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void updateRenderObject(BuildContext context, RenderLottie renderObject) {
|
||||
renderObject
|
||||
..setComposition(composition,
|
||||
progress: progress,
|
||||
frameRate: frameRate,
|
||||
delegates: delegates,
|
||||
enableMergePaths: options?.enableMergePaths)
|
||||
..setComposition(
|
||||
composition,
|
||||
progress: progress,
|
||||
frameRate: frameRate,
|
||||
delegates: delegates,
|
||||
enableMergePaths: options?.enableMergePaths,
|
||||
filterQuality: filterQuality,
|
||||
)
|
||||
..width = width
|
||||
..height = height
|
||||
..alignment = alignment
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user