lottie-ios 4.3.3 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/main.yml +51 -58
- package/Lottie.xcodeproj/project.pbxproj +40 -0
- package/Lottie.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +4 -17
- package/Lottie.xcworkspace/xcshareddata/swiftpm/Package.resolved +37 -40
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +9 -666
- package/Package.resolved +20 -22
- package/Package.swift +4 -2
- package/README.md +21 -3
- package/Rakefile +52 -28
- package/Sources/PrivacyInfo.xcprivacy +23 -0
- package/Sources/Private/CoreAnimation/Animations/CAAnimation+TimingConfiguration.swift +1 -1
- package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +23 -13
- package/Sources/Private/CoreAnimation/Animations/CustomPathAnimation.swift +8 -2
- package/Sources/Private/CoreAnimation/Animations/EllipseAnimation.swift +7 -1
- package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +15 -2
- package/Sources/Private/CoreAnimation/Animations/LayerProperty.swift +8 -1
- package/Sources/Private/CoreAnimation/Animations/RectangleAnimation.swift +8 -1
- package/Sources/Private/CoreAnimation/Animations/StarAnimation.swift +12 -1
- package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +0 -1
- package/Sources/Private/CoreAnimation/Animations/TransformAnimations.swift +19 -11
- package/Sources/Private/CoreAnimation/Animations/VisibilityAnimation.swift +45 -19
- package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +38 -3
- package/Sources/Private/CoreAnimation/Extensions/CALayer+fillBounds.swift +1 -1
- package/Sources/Private/CoreAnimation/Extensions/Keyframes+combined.swift +9 -2
- package/Sources/Private/CoreAnimation/Extensions/Keyframes+timeRemapping.swift +46 -0
- package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +77 -13
- package/Sources/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +1 -1
- package/Sources/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift +2 -2
- package/Sources/Private/CoreAnimation/Layers/ImageLayer.swift +1 -1
- package/Sources/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +1 -7
- package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +19 -53
- package/Sources/Private/CoreAnimation/Layers/ShapeItemLayer.swift +2 -2
- package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +97 -31
- package/Sources/Private/CoreAnimation/Layers/SolidLayer.swift +5 -2
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelArrayBuilder.swift +1 -1
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelProperty.swift +10 -10
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIHostingController.swift +1 -1
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift +1 -3
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIIntrinsicContentSizeInvalidator.swift +2 -0
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUILayoutMargins.swift +2 -0
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxyableView+SwiftUIView.swift +2 -0
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/MeasuringViewRepresentable.swift +2 -0
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift +2 -0
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/SwiftUIView.swift +2 -0
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIView+SwiftUIView.swift +2 -0
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIViewConfiguringSwiftUIView.swift +2 -0
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/Views/ViewType.swift +2 -1
- package/Sources/Private/EmbeddedLibraries/LRUCache/LRUCache.swift +256 -0
- package/Sources/Private/EmbeddedLibraries/LRUCache/README.md +24 -0
- package/Sources/Private/EmbeddedLibraries/README.md +16 -0
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+Helpers.swift +2 -2
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+MemoryFile.swift +7 -7
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/Data+Compression.swift +2 -2
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/FileManager+ZIP.swift +5 -5
- package/Sources/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift +1 -2
- package/Sources/Private/MainThread/LayerContainers/CompLayers/ImageCompositionLayer.swift +1 -3
- package/Sources/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +1 -2
- package/Sources/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift +2 -3
- package/Sources/Private/MainThread/LayerContainers/CompLayers/SolidCompositionLayer.swift +2 -3
- package/Sources/Private/MainThread/LayerContainers/CompLayers/TextCompositionLayer.swift +5 -12
- package/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +0 -1
- package/Sources/Private/MainThread/LayerContainers/Utility/CachedImageProvider.swift +11 -7
- package/Sources/Private/MainThread/LayerContainers/Utility/CompositionLayersInitializer.swift +3 -3
- package/Sources/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift +12 -12
- package/Sources/Private/MainThread/LayerContainers/Utility/InvertedMatteLayer.swift +1 -3
- package/Sources/Private/MainThread/LayerContainers/Utility/LayerFontProvider.swift +0 -2
- package/Sources/Private/MainThread/LayerContainers/Utility/LayerImageProvider.swift +1 -3
- package/Sources/Private/MainThread/LayerContainers/Utility/LayerTextProvider.swift +0 -2
- package/Sources/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +0 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +1 -3
- package/Sources/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/KeypathSearchable.swift +0 -1
- package/Sources/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.swift +0 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/GroupOutputNode.swift +1 -3
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PassThroughOutputNode.swift +1 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PathOutputNode.swift +0 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift +0 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift +0 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift +0 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift +0 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +2 -3
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +1 -3
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +2 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +0 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Protocols/AnimatorNode.swift +0 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Protocols/PathNode.swift +0 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Protocols/RenderNode.swift +0 -2
- package/Sources/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift +0 -1
- package/Sources/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift +0 -1
- package/Sources/Private/Model/Assets/Asset.swift +2 -3
- package/Sources/Private/Model/Assets/AssetLibrary.swift +11 -11
- package/Sources/Private/Model/Assets/ImageAsset.swift +20 -0
- package/Sources/Private/Model/Assets/PrecompAsset.swift +0 -2
- package/Sources/Private/Model/DictionaryInitializable.swift +18 -10
- package/Sources/Private/Model/DotLottie/DotLottieImageProvider.swift +9 -6
- package/Sources/Private/Model/DotLottie/DotLottieUtils.swift +1 -1
- package/Sources/Private/Model/Extensions/KeyedDecodingContainerExtensions.swift +5 -4
- package/Sources/Private/Model/Keyframes/KeyframeData.swift +1 -4
- package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +1 -3
- package/Sources/Private/Model/LayerEffects/DropShadowEffect.swift +0 -2
- package/Sources/Private/Model/LayerEffects/EffectValues/ColorEffectValue.swift +0 -2
- package/Sources/Private/Model/LayerEffects/EffectValues/EffectValue.swift +4 -5
- package/Sources/Private/Model/LayerEffects/EffectValues/Vector1DEffectValue.swift +0 -2
- package/Sources/Private/Model/LayerEffects/LayerEffect.swift +2 -3
- package/Sources/Private/Model/LayerStyles/DropShadowStyle.swift +0 -2
- package/Sources/Private/Model/LayerStyles/LayerStyle.swift +2 -3
- package/Sources/Private/Model/Layers/ImageLayerModel.swift +0 -2
- package/Sources/Private/Model/Layers/LayerModel.swift +16 -5
- package/Sources/Private/Model/Layers/PreCompLayerModel.swift +0 -2
- package/Sources/Private/Model/Layers/ShapeLayerModel.swift +0 -2
- package/Sources/Private/Model/Layers/SolidLayerModel.swift +0 -2
- package/Sources/Private/Model/Layers/TextLayerModel.swift +0 -2
- package/Sources/Private/Model/Objects/DashPattern.swift +1 -3
- package/Sources/Private/Model/Objects/Marker.swift +0 -2
- package/Sources/Private/Model/Objects/Mask.swift +0 -2
- package/Sources/Private/Model/Objects/Transform.swift +46 -9
- package/Sources/Private/Model/ShapeItems/Ellipse.swift +0 -2
- package/Sources/Private/Model/ShapeItems/Fill.swift +0 -2
- package/Sources/Private/Model/ShapeItems/GradientFill.swift +1 -3
- package/Sources/Private/Model/ShapeItems/GradientStroke.swift +1 -3
- package/Sources/Private/Model/ShapeItems/Group.swift +0 -2
- package/Sources/Private/Model/ShapeItems/Merge.swift +1 -3
- package/Sources/Private/Model/ShapeItems/Rectangle.swift +0 -2
- package/Sources/Private/Model/ShapeItems/Repeater.swift +0 -2
- package/Sources/Private/Model/ShapeItems/RoundedCorners.swift +0 -2
- package/Sources/Private/Model/ShapeItems/Shape.swift +0 -2
- package/Sources/Private/Model/ShapeItems/ShapeItem.swift +2 -3
- package/Sources/Private/Model/ShapeItems/ShapeTransform.swift +0 -2
- package/Sources/Private/Model/ShapeItems/Star.swift +1 -3
- package/Sources/Private/Model/ShapeItems/Stroke.swift +0 -2
- package/Sources/Private/Model/ShapeItems/Trim.swift +1 -3
- package/Sources/Private/Model/Text/Font.swift +0 -2
- package/Sources/Private/Model/Text/Glyph.swift +0 -2
- package/Sources/Private/Model/Text/TextAnimator.swift +0 -2
- package/Sources/Private/Model/Text/TextDocument.swift +2 -4
- package/Sources/Private/Utility/Debugging/AnimatorNodeDebugging.swift +0 -2
- package/Sources/Private/Utility/Debugging/LayerDebugging.swift +4 -5
- package/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift +2 -3
- package/Sources/Private/Utility/Extensions/DataExtension.swift +0 -1
- package/Sources/Private/Utility/Extensions/StringExtensions.swift +5 -0
- package/Sources/Private/Utility/Helpers/AnimationContext.swift +2 -3
- package/Sources/Private/Utility/Helpers/AnyEquatable.swift +0 -2
- package/Sources/Private/Utility/Helpers/Binding+Map.swift +2 -0
- package/Sources/Private/Utility/Helpers/View+ValueChanged.swift +2 -0
- package/Sources/Private/Utility/LottieAnimationSource.swift +11 -1
- package/Sources/Private/Utility/Primitives/BezierPath.swift +2 -3
- package/Sources/Private/Utility/Primitives/CGPointExtension.swift +1 -1
- package/Sources/Private/Utility/Primitives/ColorExtension.swift +1 -2
- package/Sources/Private/Utility/Primitives/VectorsExtensions.swift +6 -6
- package/Sources/Public/Animation/LottieAnimation.swift +2 -2
- package/Sources/Public/Animation/LottieAnimationHelpers.swift +7 -5
- package/Sources/Public/Animation/LottieAnimationLayer.swift +30 -43
- package/Sources/Public/Animation/LottieAnimationView.swift +18 -8
- package/Sources/Public/Animation/LottieAnimationViewInitializers.swift +3 -3
- package/Sources/Public/Animation/LottiePlaybackMode.swift +53 -0
- package/Sources/Public/Animation/LottieView.swift +145 -48
- package/Sources/Public/AnimationCache/AnimationCacheProvider.swift +0 -2
- package/Sources/Public/AnimationCache/DefaultAnimationCache.swift +21 -7
- package/Sources/Public/AnimationCache/LRUAnimationCache.swift +0 -2
- package/Sources/Public/Controls/AnimatedButton.swift +4 -6
- package/Sources/Public/Controls/AnimatedControl.swift +1 -3
- package/Sources/Public/Controls/AnimatedSwitch.swift +1 -3
- package/Sources/Public/Controls/LottieButton.swift +2 -1
- package/Sources/Public/Controls/LottieSwitch.swift +2 -0
- package/Sources/Public/DotLottie/Cache/DotLottieCache.swift +17 -4
- package/Sources/Public/DotLottie/Cache/DotLottieCacheProvider.swift +1 -3
- package/Sources/Public/DotLottie/DotLottieConfiguration.swift +53 -5
- package/Sources/Public/DotLottie/DotLottieFile.swift +4 -3
- package/Sources/Public/DotLottie/DotLottieFileHelpers.swift +18 -11
- package/Sources/Public/DynamicProperties/AnimationKeypath.swift +0 -2
- package/Sources/Public/DynamicProperties/AnyValueProvider.swift +0 -1
- package/Sources/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift +2 -2
- package/Sources/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift +1 -1
- package/Sources/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +1 -1
- package/Sources/Public/DynamicProperties/ValueProviders/PointValueProvider.swift +1 -1
- package/Sources/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift +1 -1
- package/Sources/Public/FontProvider/AnimationFontProvider.swift +0 -2
- package/Sources/Public/ImageProvider/AnimationImageProvider.swift +0 -2
- package/Sources/Public/Keyframes/Interpolatable.swift +26 -0
- package/Sources/Public/Primitives/LottieColor.swift +0 -2
- package/Sources/Public/Primitives/Vectors.swift +0 -2
- package/Sources/Public/TextProvider/AnimationTextProvider.swift +0 -2
- package/Sources/Public/iOS/AnimationSubview.swift +0 -1
- package/Sources/Public/iOS/BundleImageProvider.swift +3 -8
- package/Sources/Public/iOS/Compatibility/CompatibleAnimationView.swift +4 -8
- package/Sources/Public/iOS/LottieAnimationViewBase.swift +5 -2
- package/Sources/Public/iOS/UIColorExtension.swift +1 -2
- package/Sources/Public/macOS/BundleImageProvider.macOS.swift +3 -6
- package/lottie-ios.podspec +6 -2
- package/package.json +1 -1
- package/Lottie.xcodeproj/project.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcodeproj/project.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcodeproj/xcuserdata/cal.xcuserdatad/xcschemes/xcschememanagement.plist +0 -37
- package/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -6
- package/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/xcdebugger/Expressions.xcexplist +0 -153
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/IDEFindNavigatorScopes.plist +0 -5
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Expressions.xcexplist +0 -231
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +0 -37
package/Package.resolved
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"version": "1.0.5"
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
"package": "swift-argument-parser",
|
|
15
|
-
"repositoryURL": "https://github.com/apple/swift-argument-parser",
|
|
16
|
-
"state": {
|
|
17
|
-
"branch": null,
|
|
18
|
-
"revision": "df9ee6676cd5b3bf5b330ec7568a5644f547201b",
|
|
19
|
-
"version": "1.1.3"
|
|
20
|
-
}
|
|
2
|
+
"pins" : [
|
|
3
|
+
{
|
|
4
|
+
"identity" : "swift",
|
|
5
|
+
"kind" : "remoteSourceControl",
|
|
6
|
+
"location" : "https://github.com/airbnb/swift",
|
|
7
|
+
"state" : {
|
|
8
|
+
"revision" : "bc6aa7c3e21b6ab951ce75afc0a6e6d16fd6caef",
|
|
9
|
+
"version" : "1.0.6"
|
|
21
10
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"identity" : "swift-argument-parser",
|
|
14
|
+
"kind" : "remoteSourceControl",
|
|
15
|
+
"location" : "https://github.com/apple/swift-argument-parser",
|
|
16
|
+
"state" : {
|
|
17
|
+
"revision" : "df9ee6676cd5b3bf5b330ec7568a5644f547201b",
|
|
18
|
+
"version" : "1.1.3"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"version" : 2
|
|
25
23
|
}
|
package/Package.swift
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// swift-tools-version:5.
|
|
1
|
+
// swift-tools-version:5.7
|
|
2
2
|
import PackageDescription
|
|
3
3
|
|
|
4
4
|
let package = Package(
|
|
@@ -17,5 +17,7 @@ let package = Package(
|
|
|
17
17
|
"Private/EmbeddedLibraries/README.md",
|
|
18
18
|
"Private/EmbeddedLibraries/ZipFoundation/README.md",
|
|
19
19
|
"Private/EmbeddedLibraries/EpoxyCore/README.md",
|
|
20
|
-
|
|
20
|
+
"Private/EmbeddedLibraries/LRUCache/README.md",
|
|
21
|
+
],
|
|
22
|
+
resources: [.copy("PrivacyInfo.xcprivacy")]),
|
|
21
23
|
])
|
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ To install Lottie using [Swift Package Manager](https://github.com/apple/swift-p
|
|
|
41
41
|
or you can add the following dependency to your `Package.swift`:
|
|
42
42
|
|
|
43
43
|
```swift
|
|
44
|
-
.package(url: "https://github.com/airbnb/lottie-spm.git", from: "4.
|
|
44
|
+
.package(url: "https://github.com/airbnb/lottie-spm.git", from: "4.4.0")
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
When using Swift Package Manager we recommend using the [lottie-spm](https://github.com/airbnb/lottie-spm) repo instead of the main lottie-ios repo. The main git repository for [lottie-ios](https://github.com/airbnb/lottie-ios) is somewhat large (300+ MB), and Swift Package Manager always downloads the full repository with all git history. The [lottie-spm](https://github.com/airbnb/lottie-spm) repo is much smaller (less than 500kb), so can be downloaded much more quickly.
|
|
@@ -75,9 +75,27 @@ carthage update
|
|
|
75
75
|
```
|
|
76
76
|
In your application targets “General” tab under the “Linked Frameworks and Libraries” section, drag and drop lottie-ios.framework from the Carthage/Build/iOS directory that `carthage update` produced.
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
## Swift Version Support
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
Lottie supports Swift / Xcode versions back to the minimum version that is permited by Apple for submissions to the App Store. You can see the most up-to-date information for which Swift versions Lottie supports on [Swift Package Index](https://swiftpackageindex.com/airbnb/lottie-ios):
|
|
81
|
+
|
|
82
|
+
[](https://swiftpackageindex.com/airbnb/lottie-ios)
|
|
83
|
+
|
|
84
|
+
## Privacy
|
|
85
|
+
|
|
86
|
+
Lottie does not collect any data. We provide this notice to help you fill out [App Privacy Details](https://developer.apple.com/app-store/app-privacy-details/). We additionally provide a [privacy manifest](https://github.com/airbnb/lottie-ios/blob/master/Sources/PrivacyInfo.xcprivacy) which can be included in your app.
|
|
87
|
+
|
|
88
|
+
## Security
|
|
89
|
+
|
|
90
|
+
We distribute XCFramework bundles for each release on [GitHub](https://github.com/airbnb/lottie-ios/releases/latest). In Lottie 4.4.0 and later, these XCFramework bundles include a [code signature](https://developer.apple.com/documentation/xcode/verifying-the-origin-of-your-xcframeworks). These bundles are self-signed under the name "Lottie iOS" and have the following fingerprint:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
89 2F 1B 43 04 7B 50 53 8F 2F 46 EA D9 29 00 DD 3D 48 11 F358 21 78 C0 61 A5 FB 20 F1 11 CB 26
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
In Xcode you can verify this by selecting `Lottie.xcframework` and confirming that it shows the following information:
|
|
97
|
+
|
|
98
|
+

|
|
81
99
|
|
|
82
100
|
## Contributing
|
|
83
101
|
|
package/Rakefile
CHANGED
|
@@ -68,45 +68,60 @@ namespace :build do
|
|
|
68
68
|
sh 'rm -rf .build/archives'
|
|
69
69
|
|
|
70
70
|
# Build the framework for each supported platform, including simulators
|
|
71
|
-
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination generic/platform=iOS -archivePath ".build/archives/Lottie_iOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO')
|
|
72
|
-
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=iOS Simulator" -archivePath ".build/archives/Lottie_iOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO')
|
|
73
|
-
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=macOS,variant=Mac Catalyst" -archivePath ".build/archives/Lottie_Mac_Catalyst" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO')
|
|
74
|
-
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (macOS)" -destination generic/platform=macOS -archivePath ".build/archives/Lottie_macOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO')
|
|
75
|
-
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination generic/platform=tvOS -archivePath ".build/archives/Lottie_tvOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO')
|
|
76
|
-
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination "generic/platform=tvOS Simulator" -archivePath ".build/archives/Lottie_tvOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO')
|
|
71
|
+
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination generic/platform=iOS -archivePath ".build/archives/Lottie_iOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO SWIFT_SERIALIZE_DEBUGGING_OPTIONS=NO')
|
|
72
|
+
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=iOS Simulator" -archivePath ".build/archives/Lottie_iOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO SWIFT_SERIALIZE_DEBUGGING_OPTIONS=NO')
|
|
73
|
+
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=macOS,variant=Mac Catalyst" -archivePath ".build/archives/Lottie_Mac_Catalyst" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO SWIFT_SERIALIZE_DEBUGGING_OPTIONS=NO')
|
|
74
|
+
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (macOS)" -destination generic/platform=macOS -archivePath ".build/archives/Lottie_macOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO SWIFT_SERIALIZE_DEBUGGING_OPTIONS=NO')
|
|
75
|
+
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination generic/platform=tvOS -archivePath ".build/archives/Lottie_tvOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO SWIFT_SERIALIZE_DEBUGGING_OPTIONS=NO')
|
|
76
|
+
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination "generic/platform=tvOS Simulator" -archivePath ".build/archives/Lottie_tvOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO SWIFT_SERIALIZE_DEBUGGING_OPTIONS=NO')
|
|
77
77
|
|
|
78
78
|
ifVisionOSEnabled {
|
|
79
|
-
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination generic/platform=visionOS -archivePath ".build/archives/Lottie_visionOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO')
|
|
80
|
-
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination "generic/platform=visionOS Simulator" -archivePath ".build/archives/Lottie_visionOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO')
|
|
79
|
+
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination generic/platform=visionOS -archivePath ".build/archives/Lottie_visionOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO SWIFT_SERIALIZE_DEBUGGING_OPTIONS=NO')
|
|
80
|
+
xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination "generic/platform=visionOS Simulator" -archivePath ".build/archives/Lottie_visionOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO SWIFT_SERIALIZE_DEBUGGING_OPTIONS=NO')
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
# Combine all of the platforms into a single XCFramework
|
|
84
84
|
xcframeworkInvocation = [
|
|
85
85
|
'-create-xcframework',
|
|
86
|
-
'-
|
|
87
|
-
'-
|
|
88
|
-
'-
|
|
89
|
-
'-
|
|
90
|
-
'-
|
|
91
|
-
'-
|
|
86
|
+
'-archive .build/archives/Lottie_iOS.xcarchive -framework Lottie.framework',
|
|
87
|
+
'-archive .build/archives/Lottie_iOS_Simulator.xcarchive -framework Lottie.framework',
|
|
88
|
+
'-archive .build/archives/Lottie_Mac_Catalyst.xcarchive -framework Lottie.framework',
|
|
89
|
+
'-archive .build/archives/Lottie_tvOS.xcarchive -framework Lottie.framework',
|
|
90
|
+
'-archive .build/archives/Lottie_tvOS_Simulator.xcarchive -framework Lottie.framework',
|
|
91
|
+
'-archive .build/archives/Lottie_macOS.xcarchive -framework Lottie.framework',
|
|
92
92
|
]
|
|
93
93
|
|
|
94
94
|
ifVisionOSEnabled {
|
|
95
|
-
xcframeworkInvocation.push('-
|
|
96
|
-
xcframeworkInvocation.push('-
|
|
95
|
+
xcframeworkInvocation.push('-archive .build/archives/Lottie_visionOS.xcarchive -framework Lottie.framework')
|
|
96
|
+
xcframeworkInvocation.push('-archive .build/archives/Lottie_visionOS_Simulator.xcarchive -framework Lottie.framework')
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
xcframeworkInvocation.push('-output .build/archives/Lottie.xcframework')
|
|
100
100
|
|
|
101
101
|
xcodebuild(xcframeworkInvocation.join(" "))
|
|
102
102
|
|
|
103
|
-
# Archive the XCFramework into a zip file
|
|
104
103
|
Dir.chdir('.build/archives') do
|
|
104
|
+
# Codesign the XCFramework using the "Lottie iOS" certificate, which should be installed in the keychain.
|
|
105
|
+
# - Check to make sure the certificate is installed before attemtping to codesign.
|
|
106
|
+
# - In GitHub actions CI, only jobs run by contibutors have access to repo secrets,
|
|
107
|
+
# so PR jobs from external contributors won't have access to this certificate.
|
|
108
|
+
# In that case we skip codesigning so the job doesn't fail.
|
|
109
|
+
puts "Checking if signing certificate is installed..."
|
|
110
|
+
`security find-certificate -c 'Lottie iOS'`
|
|
111
|
+
if $?.success?
|
|
112
|
+
puts "Signing certificate is installed. Code signing Lottie.xcframework."
|
|
113
|
+
sh 'codesign --timestamp -v --sign "Lottie iOS" Lottie.xcframework'
|
|
114
|
+
else
|
|
115
|
+
puts "Signing certificate is not installed. Lottie.xcframework will not be code signed."
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Archive the XCFramework into a zip file
|
|
105
119
|
# Use --symlinks to avoid "Multiple binaries share the same codesign path. This can happen if your build process copies frameworks by following symlinks."
|
|
106
120
|
# error when validating macOS apps (#1948)
|
|
107
121
|
sh "zip -r --symlinks #{args[:zip_archive_name]}.xcframework.zip Lottie.xcframework"
|
|
108
122
|
sh 'rm -rf Lottie.xcframework'
|
|
109
123
|
end
|
|
124
|
+
|
|
110
125
|
sh "swift package compute-checksum .build/archives/#{args[:zip_archive_name]}.xcframework.zip"
|
|
111
126
|
end
|
|
112
127
|
end
|
|
@@ -131,7 +146,9 @@ namespace :test do
|
|
|
131
146
|
sh 'cp -R [^script]* script/test-carthage/Carthage/Checkouts/lottie-ios'
|
|
132
147
|
|
|
133
148
|
Dir.chdir('script/test-carthage') do
|
|
134
|
-
|
|
149
|
+
installVisionOSIfNecessary()
|
|
150
|
+
|
|
151
|
+
# Build the Lottie framework scheme
|
|
135
152
|
sh 'carthage build --use-xcframeworks'
|
|
136
153
|
|
|
137
154
|
# Delete Carthage's derived data to verify that the built .xcframework doesn't depend on any
|
|
@@ -139,9 +156,11 @@ namespace :test do
|
|
|
139
156
|
# https://github.com/airbnb/lottie-ios/issues/1492
|
|
140
157
|
sh 'rm -rf ~/Library/Caches/org.carthage.CarthageKit/DerivedData'
|
|
141
158
|
|
|
142
|
-
# Build a test app that imports and uses the
|
|
143
|
-
xcodebuild('build -scheme CarthageTest
|
|
144
|
-
xcodebuild('build -scheme CarthageTest-macOS')
|
|
159
|
+
# Build a test app that imports and uses the Lottie framework built via Carthage
|
|
160
|
+
xcodebuild('build -scheme CarthageTest -destination "platform=iOS Simulator,name=iPhone SE (3rd generation)"')
|
|
161
|
+
xcodebuild('build -scheme CarthageTest -destination generic/platform=macOS')
|
|
162
|
+
xcodebuild('build -scheme CarthageTest -destination "platform=tvOS Simulator,name=Apple TV"')
|
|
163
|
+
xcodebuild('build -scheme CarthageTest -destination "platform=visionOS Simulator,name=Apple Vision Pro"')
|
|
145
164
|
end
|
|
146
165
|
end
|
|
147
166
|
|
|
@@ -232,16 +251,21 @@ def xcodebuild(command)
|
|
|
232
251
|
end
|
|
233
252
|
|
|
234
253
|
# Runs the given code block, unless `SKIP_VISION_OS=true`.
|
|
235
|
-
#
|
|
254
|
+
# TODO: Remove this once CI only uses Xcode 15.2+.
|
|
236
255
|
def ifVisionOSEnabled
|
|
237
256
|
if ENV["SKIP_VISION_OS"] == "true"
|
|
238
257
|
puts "Skipping visionOS build"
|
|
239
258
|
else
|
|
240
|
-
|
|
241
|
-
# so we have to download it manually. Following the suggested workaround from
|
|
242
|
-
# https://github.com/actions/runner-images/issues/8144#issuecomment-1702786388
|
|
243
|
-
`brew install xcodesorg/made/xcodes`
|
|
244
|
-
`xcodes runtimes install 'visionOS 1.0-beta3'`
|
|
259
|
+
installVisionOSIfNecessary()
|
|
245
260
|
yield
|
|
246
261
|
end
|
|
247
|
-
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def installVisionOSIfNecessary
|
|
265
|
+
# visionOS is unsupported by default on Intel, but we can override this
|
|
266
|
+
# https://github.com/actions/runner-images/issues/8144#issuecomment-1902072070
|
|
267
|
+
sh 'defaults write com.apple.dt.Xcode AllowUnsupportedVisionOSHost -bool YES'
|
|
268
|
+
sh 'defaults write com.apple.CoreSimulator AllowUnsupportedVisionOSHost -bool YES'
|
|
269
|
+
|
|
270
|
+
xcodebuild("-downloadPlatform visionOS")
|
|
271
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>NSPrivacyTracking</key>
|
|
6
|
+
<false/>
|
|
7
|
+
<key>NSPrivacyTrackingDomains</key>
|
|
8
|
+
<array/>
|
|
9
|
+
<key>NSPrivacyCollectedDataTypes</key>
|
|
10
|
+
<array/>
|
|
11
|
+
<key>NSPrivacyAccessedAPITypes</key>
|
|
12
|
+
<array>
|
|
13
|
+
<dict>
|
|
14
|
+
<key>NSPrivacyAccessedAPIType</key>
|
|
15
|
+
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
|
16
|
+
<key>NSPrivacyAccessedAPITypeReasons</key>
|
|
17
|
+
<array>
|
|
18
|
+
<string>3B52.1</string>
|
|
19
|
+
</array>
|
|
20
|
+
</dict>
|
|
21
|
+
</array>
|
|
22
|
+
</dict>
|
|
23
|
+
</plist>
|
|
@@ -21,7 +21,7 @@ extension CAAnimation {
|
|
|
21
21
|
// 0% 100%
|
|
22
22
|
//
|
|
23
23
|
let baseAnimation = self
|
|
24
|
-
baseAnimation.duration = context.
|
|
24
|
+
baseAnimation.duration = context.animationDuration
|
|
25
25
|
baseAnimation.speed = (context.endFrame < context.startFrame) ? -1 : 1
|
|
26
26
|
|
|
27
27
|
// To select the subrange of the `baseAnimation` that should be played,
|
|
@@ -10,7 +10,7 @@ extension CALayer {
|
|
|
10
10
|
/// Constructs a `CAKeyframeAnimation` that reflects the given keyframes,
|
|
11
11
|
/// and adds it to this `CALayer`.
|
|
12
12
|
@nonobjc
|
|
13
|
-
func addAnimation<KeyframeValue, ValueRepresentation>(
|
|
13
|
+
func addAnimation<KeyframeValue: AnyInterpolatable, ValueRepresentation>(
|
|
14
14
|
for property: LayerProperty<ValueRepresentation>,
|
|
15
15
|
keyframes: KeyframeGroup<KeyframeValue>,
|
|
16
16
|
value keyframeValueMapping: (KeyframeValue) throws -> ValueRepresentation,
|
|
@@ -39,7 +39,7 @@ extension CALayer {
|
|
|
39
39
|
/// - If the value can be applied directly to the CALayer using KVC,
|
|
40
40
|
/// then no `CAAnimation` will be created and the value will be applied directly.
|
|
41
41
|
@nonobjc
|
|
42
|
-
private func defaultAnimation<KeyframeValue, ValueRepresentation>(
|
|
42
|
+
private func defaultAnimation<KeyframeValue: AnyInterpolatable, ValueRepresentation>(
|
|
43
43
|
for property: LayerProperty<ValueRepresentation>,
|
|
44
44
|
keyframes keyframeGroup: KeyframeGroup<KeyframeValue>,
|
|
45
45
|
value keyframeValueMapping: (KeyframeValue) throws -> ValueRepresentation,
|
|
@@ -61,9 +61,9 @@ extension CALayer {
|
|
|
61
61
|
""")
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
// If there is exactly one keyframe value
|
|
65
|
-
// by applying that value directly to the layer
|
|
66
|
-
// a relatively expensive `CAKeyframeAnimation`.
|
|
64
|
+
// If there is exactly one keyframe value that doesn't animate,
|
|
65
|
+
// we can improve performance by applying that value directly to the layer
|
|
66
|
+
// instead of creating a relatively expensive `CAKeyframeAnimation`.
|
|
67
67
|
if keyframes.count == 1 {
|
|
68
68
|
return singleKeyframeAnimation(
|
|
69
69
|
for: property,
|
|
@@ -71,6 +71,16 @@ extension CALayer {
|
|
|
71
71
|
writeDirectlyToPropertyIfPossible: true)
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/// If we're required to use the `complexTimeRemapping` from some parent `PreCompLayer`,
|
|
75
|
+
/// we have to manually interpolate the keyframes with the time remapping applied.
|
|
76
|
+
if context.mustUseComplexTimeRemapping {
|
|
77
|
+
return try defaultAnimation(
|
|
78
|
+
for: property,
|
|
79
|
+
keyframes: Keyframes.manuallyInterpolatedWithTimeRemapping(keyframeGroup, context: context),
|
|
80
|
+
value: keyframeValueMapping,
|
|
81
|
+
context: context.withoutTimeRemapping())
|
|
82
|
+
}
|
|
83
|
+
|
|
74
84
|
// Split the keyframes into segments with the same `CAAnimationCalculationMode` value
|
|
75
85
|
// - Each of these segments will become their own `CAKeyframeAnimation`
|
|
76
86
|
let animationSegments = keyframes.segmentsSplitByCalculationMode()
|
|
@@ -179,8 +189,8 @@ extension CALayer {
|
|
|
179
189
|
// all of which have a non-zero number of keyframes.
|
|
180
190
|
let segmentAnimations: [CAKeyframeAnimation] = try animationSegments.indices.map { index in
|
|
181
191
|
let animationSegment = animationSegments[index]
|
|
182
|
-
var segmentStartTime = context.time(
|
|
183
|
-
var segmentEndTime = context.time(
|
|
192
|
+
var segmentStartTime = try context.time(forFrame: animationSegment.first!.time)
|
|
193
|
+
var segmentEndTime = try context.time(forFrame: animationSegment.last!.time)
|
|
184
194
|
|
|
185
195
|
// Every portion of the animation timeline has to be covered by a `CAKeyframeAnimation`,
|
|
186
196
|
// so if this is the first or last segment then the start/end time should be exactly
|
|
@@ -190,13 +200,13 @@ extension CALayer {
|
|
|
190
200
|
|
|
191
201
|
if isFirstSegment {
|
|
192
202
|
segmentStartTime = min(
|
|
193
|
-
context.time(
|
|
203
|
+
try context.time(forFrame: context.animation.startFrame),
|
|
194
204
|
segmentStartTime)
|
|
195
205
|
}
|
|
196
206
|
|
|
197
207
|
if isLastSegment {
|
|
198
208
|
segmentEndTime = max(
|
|
199
|
-
context.time(
|
|
209
|
+
try context.time(forFrame: context.animation.endFrame),
|
|
200
210
|
segmentEndTime)
|
|
201
211
|
}
|
|
202
212
|
|
|
@@ -206,8 +216,8 @@ extension CALayer {
|
|
|
206
216
|
// relative to 0 (`segmentStartTime`) and 1 (`segmentEndTime`). This is different
|
|
207
217
|
// from the default behavior of the `keyframeAnimation` method, where times
|
|
208
218
|
// are expressed relative to the entire animation duration.
|
|
209
|
-
let customKeyTimes = animationSegment.map { keyframeModel -> NSNumber in
|
|
210
|
-
let keyframeTime = context.time(
|
|
219
|
+
let customKeyTimes = try animationSegment.map { keyframeModel -> NSNumber in
|
|
220
|
+
let keyframeTime = try context.time(forFrame: keyframeModel.time)
|
|
211
221
|
let segmentProgressTime = ((keyframeTime - segmentStartTime) / segmentDuration)
|
|
212
222
|
return segmentProgressTime as NSNumber
|
|
213
223
|
}
|
|
@@ -241,8 +251,8 @@ extension CALayer {
|
|
|
241
251
|
{
|
|
242
252
|
// Convert the list of `Keyframe<T>` into
|
|
243
253
|
// the representation used by `CAKeyframeAnimation`
|
|
244
|
-
var keyTimes = customKeyTimes ?? keyframes.map { keyframeModel -> NSNumber in
|
|
245
|
-
NSNumber(value: Float(context.progressTime(for: keyframeModel.time)))
|
|
254
|
+
var keyTimes = try customKeyTimes ?? keyframes.map { keyframeModel -> NSNumber in
|
|
255
|
+
NSNumber(value: Float(try context.progressTime(for: keyframeModel.time)))
|
|
246
256
|
}
|
|
247
257
|
|
|
248
258
|
var timingFunctions = timingFunctions(for: keyframes)
|
|
@@ -53,7 +53,7 @@ extension CGPath {
|
|
|
53
53
|
// MARK: - BezierPathKeyframe
|
|
54
54
|
|
|
55
55
|
/// Data that represents how to render a bezier path at a specific point in time
|
|
56
|
-
struct BezierPathKeyframe {
|
|
56
|
+
struct BezierPathKeyframe: Interpolatable {
|
|
57
57
|
let path: BezierPath
|
|
58
58
|
let cornerRadius: LottieVector1D?
|
|
59
59
|
|
|
@@ -65,7 +65,7 @@ struct BezierPathKeyframe {
|
|
|
65
65
|
-> KeyframeGroup<BezierPathKeyframe>
|
|
66
66
|
{
|
|
67
67
|
guard
|
|
68
|
-
let cornerRadius
|
|
68
|
+
let cornerRadius,
|
|
69
69
|
cornerRadius.keyframes.contains(where: { $0.value.cgFloatValue > 0 })
|
|
70
70
|
else {
|
|
71
71
|
return path.map { path in
|
|
@@ -77,4 +77,10 @@ struct BezierPathKeyframe {
|
|
|
77
77
|
path, cornerRadius,
|
|
78
78
|
makeCombinedResult: BezierPathKeyframe.init)
|
|
79
79
|
}
|
|
80
|
+
|
|
81
|
+
func interpolate(to: BezierPathKeyframe, amount: CGFloat) -> BezierPathKeyframe {
|
|
82
|
+
BezierPathKeyframe(
|
|
83
|
+
path: path.interpolate(to: to.path, amount: amount),
|
|
84
|
+
cornerRadius: cornerRadius.interpolate(to: to.cornerRadius, amount: amount))
|
|
85
|
+
}
|
|
80
86
|
}
|
|
@@ -29,9 +29,15 @@ extension CAShapeLayer {
|
|
|
29
29
|
|
|
30
30
|
extension Ellipse {
|
|
31
31
|
/// Data that represents how to render an ellipse at a specific point in time
|
|
32
|
-
struct Keyframe {
|
|
32
|
+
struct Keyframe: Interpolatable {
|
|
33
33
|
let size: LottieVector3D
|
|
34
34
|
let position: LottieVector3D
|
|
35
|
+
|
|
36
|
+
func interpolate(to: Ellipse.Keyframe, amount: CGFloat) -> Ellipse.Keyframe {
|
|
37
|
+
Keyframe(
|
|
38
|
+
size: size.interpolate(to: to.size, amount: amount),
|
|
39
|
+
position: position.interpolate(to: to.position, amount: amount))
|
|
40
|
+
}
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
/// Creates a single array of animatable keyframes from the separate arrays of keyframes in this Ellipse
|
|
@@ -114,7 +114,7 @@ extension GradientRenderLayer {
|
|
|
114
114
|
|
|
115
115
|
let combinedKeyframes = Keyframes.combined(
|
|
116
116
|
gradient.startPoint, gradient.endPoint,
|
|
117
|
-
makeCombinedResult: { absoluteStartPoint, absoluteEndPoint ->
|
|
117
|
+
makeCombinedResult: { absoluteStartPoint, absoluteEndPoint -> RadialGradientKeyframes in
|
|
118
118
|
// Convert the absolute start / end points to the relative structure used by Core Animation
|
|
119
119
|
let relativeStartPoint = percentBasedPointInBounds(from: absoluteStartPoint.pointValue)
|
|
120
120
|
let radius = absoluteStartPoint.pointValue.distanceTo(absoluteEndPoint.pointValue)
|
|
@@ -123,7 +123,7 @@ extension GradientRenderLayer {
|
|
|
123
123
|
x: absoluteStartPoint.x + radius,
|
|
124
124
|
y: absoluteStartPoint.y + radius))
|
|
125
125
|
|
|
126
|
-
return (startPoint: relativeStartPoint, endPoint: relativeEndPoint)
|
|
126
|
+
return RadialGradientKeyframes(startPoint: relativeStartPoint, endPoint: relativeEndPoint)
|
|
127
127
|
})
|
|
128
128
|
|
|
129
129
|
try addAnimation(
|
|
@@ -140,6 +140,19 @@ extension GradientRenderLayer {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
// MARK: - RadialGradientKeyframes
|
|
144
|
+
|
|
145
|
+
private struct RadialGradientKeyframes: Interpolatable {
|
|
146
|
+
let startPoint: CGPoint
|
|
147
|
+
let endPoint: CGPoint
|
|
148
|
+
|
|
149
|
+
func interpolate(to: RadialGradientKeyframes, amount: CGFloat) -> RadialGradientKeyframes {
|
|
150
|
+
RadialGradientKeyframes(
|
|
151
|
+
startPoint: startPoint.interpolate(to: to.startPoint, amount: amount),
|
|
152
|
+
endPoint: endPoint.interpolate(to: to.endPoint, amount: amount))
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
143
156
|
// MARK: - GradientContentType
|
|
144
157
|
|
|
145
158
|
/// Each type of gradient that can be constructed from a `GradientShapeItem`
|
|
@@ -165,11 +165,18 @@ extension LayerProperty {
|
|
|
165
165
|
customizableProperty: .opacity)
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
static var isHidden: LayerProperty<Bool> {
|
|
169
|
+
.init(
|
|
170
|
+
caLayerKeypath: #keyPath(CALayer.isHidden),
|
|
171
|
+
defaultValue: false,
|
|
172
|
+
customizableProperty: nil /* unsupported */ )
|
|
173
|
+
}
|
|
174
|
+
|
|
168
175
|
static var transform: LayerProperty<CATransform3D> {
|
|
169
176
|
.init(
|
|
170
177
|
caLayerKeypath: #keyPath(CALayer.transform),
|
|
171
178
|
isDefaultValue: { transform in
|
|
172
|
-
guard let transform
|
|
179
|
+
guard let transform else { return false }
|
|
173
180
|
return CATransform3DIsIdentity(transform)
|
|
174
181
|
},
|
|
175
182
|
customizableProperty: nil /* currently unsupported */ )
|
|
@@ -31,10 +31,17 @@ extension CAShapeLayer {
|
|
|
31
31
|
|
|
32
32
|
extension Rectangle {
|
|
33
33
|
/// Data that represents how to render a rectangle at a specific point in time
|
|
34
|
-
struct Keyframe {
|
|
34
|
+
struct Keyframe: Interpolatable {
|
|
35
35
|
let size: LottieVector3D
|
|
36
36
|
let position: LottieVector3D
|
|
37
37
|
let cornerRadius: LottieVector1D
|
|
38
|
+
|
|
39
|
+
func interpolate(to: Rectangle.Keyframe, amount: CGFloat) -> Rectangle.Keyframe {
|
|
40
|
+
Rectangle.Keyframe(
|
|
41
|
+
size: size.interpolate(to: to.size, amount: amount),
|
|
42
|
+
position: position.interpolate(to: to.position, amount: amount),
|
|
43
|
+
cornerRadius: cornerRadius.interpolate(to: to.cornerRadius, amount: amount))
|
|
44
|
+
}
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
/// Creates a single array of animatable keyframes from the separate arrays of keyframes in this Rectangle
|
|
@@ -80,7 +80,7 @@ extension CAShapeLayer {
|
|
|
80
80
|
|
|
81
81
|
extension Star {
|
|
82
82
|
/// Data that represents how to render a star at a specific point in time
|
|
83
|
-
struct Keyframe {
|
|
83
|
+
struct Keyframe: Interpolatable {
|
|
84
84
|
let position: LottieVector3D
|
|
85
85
|
let outerRadius: LottieVector1D
|
|
86
86
|
let innerRadius: LottieVector1D
|
|
@@ -88,6 +88,17 @@ extension Star {
|
|
|
88
88
|
let innerRoundness: LottieVector1D
|
|
89
89
|
let points: LottieVector1D
|
|
90
90
|
let rotation: LottieVector1D
|
|
91
|
+
|
|
92
|
+
func interpolate(to: Star.Keyframe, amount: CGFloat) -> Star.Keyframe {
|
|
93
|
+
Star.Keyframe(
|
|
94
|
+
position: position.interpolate(to: to.position, amount: amount),
|
|
95
|
+
outerRadius: outerRadius.interpolate(to: to.outerRadius, amount: amount),
|
|
96
|
+
innerRadius: innerRadius.interpolate(to: to.innerRadius, amount: amount),
|
|
97
|
+
outerRoundness: outerRoundness.interpolate(to: to.outerRoundness, amount: amount),
|
|
98
|
+
innerRoundness: innerRoundness.interpolate(to: to.innerRoundness, amount: amount),
|
|
99
|
+
points: points.interpolate(to: to.points, amount: amount),
|
|
100
|
+
rotation: rotation.interpolate(to: to.rotation, amount: amount))
|
|
101
|
+
}
|
|
91
102
|
}
|
|
92
103
|
|
|
93
104
|
/// Creates a single array of animatable keyframes from the separate arrays of keyframes in this star/polygon
|
|
@@ -253,10 +253,16 @@ extension CALayer {
|
|
|
253
253
|
context: LayerAnimationContext)
|
|
254
254
|
throws
|
|
255
255
|
{
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
256
|
+
let requiresManualInterpolation =
|
|
257
|
+
// Core Animation doesn't animate skew changes properly. If the skew value
|
|
258
|
+
// changes over the course of the animation then we have to manually
|
|
259
|
+
// compute the `CATransform3D` for each frame individually.
|
|
260
|
+
transformModel.hasSkewAnimation
|
|
261
|
+
// `addAnimation` requires that we use an `Interpolatable` value, but we can't interpolate a `CATransform3D`.
|
|
262
|
+
// Since this is only necessary when using `complexTimeRemapping`, we can avoid this by manually interpolating
|
|
263
|
+
// when `context.mustUseComplexTimeRemapping` is true and just returning a `Hold` container.
|
|
264
|
+
// Since our keyframes are already manually interpolated, they won't need to be interpolated again.
|
|
265
|
+
|| context.mustUseComplexTimeRemapping
|
|
260
266
|
|
|
261
267
|
let combinedTransformKeyframes = Keyframes.combined(
|
|
262
268
|
transformModel.anchorPoint,
|
|
@@ -272,7 +278,7 @@ extension CALayer {
|
|
|
272
278
|
requiresManualInterpolation: requiresManualInterpolation,
|
|
273
279
|
makeCombinedResult: {
|
|
274
280
|
anchor, position, positionX, positionY, scale, rotationX, rotationY, rotationZ, skew, skewAxis
|
|
275
|
-
-> CATransform3D in
|
|
281
|
+
-> Hold<CATransform3D> in
|
|
276
282
|
|
|
277
283
|
let transformPosition: CGPoint
|
|
278
284
|
if transformModel._positionX != nil, transformModel._positionY != nil {
|
|
@@ -281,7 +287,7 @@ extension CALayer {
|
|
|
281
287
|
transformPosition = position.pointValue
|
|
282
288
|
}
|
|
283
289
|
|
|
284
|
-
|
|
290
|
+
let transform = CATransform3D.makeTransform(
|
|
285
291
|
anchor: anchor.pointValue,
|
|
286
292
|
position: transformPosition,
|
|
287
293
|
scale: scale.sizeValue,
|
|
@@ -290,12 +296,14 @@ extension CALayer {
|
|
|
290
296
|
rotationZ: rotationZ.cgFloatValue,
|
|
291
297
|
skew: skew.cgFloatValue,
|
|
292
298
|
skewAxis: skewAxis.cgFloatValue)
|
|
299
|
+
|
|
300
|
+
return Hold(value: transform)
|
|
293
301
|
})
|
|
294
302
|
|
|
295
303
|
try addAnimation(
|
|
296
304
|
for: .transform,
|
|
297
305
|
keyframes: combinedTransformKeyframes,
|
|
298
|
-
value: { $0 },
|
|
306
|
+
value: { $0.value },
|
|
299
307
|
context: context)
|
|
300
308
|
}
|
|
301
309
|
|
|
@@ -305,8 +313,8 @@ extension TransformModel {
|
|
|
305
313
|
/// Whether or not this transform has a non-zero skew value
|
|
306
314
|
var hasSkew: Bool {
|
|
307
315
|
guard
|
|
308
|
-
let _skew
|
|
309
|
-
let _skewAxis
|
|
316
|
+
let _skew,
|
|
317
|
+
let _skewAxis,
|
|
310
318
|
!_skew.keyframes.isEmpty,
|
|
311
319
|
!_skewAxis.keyframes.isEmpty
|
|
312
320
|
else {
|
|
@@ -320,8 +328,8 @@ extension TransformModel {
|
|
|
320
328
|
var hasSkewAnimation: Bool {
|
|
321
329
|
guard
|
|
322
330
|
hasSkew,
|
|
323
|
-
let _skew
|
|
324
|
-
let _skewAxis
|
|
331
|
+
let _skew,
|
|
332
|
+
let _skewAxis
|
|
325
333
|
else { return false }
|
|
326
334
|
|
|
327
335
|
return _skew.keyframes.count > 1
|