lottie-ios 3.4.4 → 4.0.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/.gitattributes +1 -0
- package/.github/workflows/main.yml +7 -7
- package/Gemfile.lock +1 -1
- package/Lottie.xcodeproj/project.pbxproj +286 -68
- package/Lottie.xcworkspace/xcshareddata/swiftpm/Package.resolved +18 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +3 -24
- package/Package.swift +2 -2
- package/README.md +10 -3
- package/Rakefile +1 -1
- package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +6 -9
- package/Sources/Private/CoreAnimation/Animations/CustomPathAnimation.swift +42 -3
- package/Sources/Private/CoreAnimation/Animations/EllipseAnimation.swift +5 -17
- package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +25 -17
- package/Sources/Private/CoreAnimation/Animations/LayerProperty.swift +2 -2
- package/Sources/Private/CoreAnimation/Animations/OpacityAnimation.swift +1 -1
- package/Sources/Private/CoreAnimation/Animations/RectangleAnimation.swift +9 -20
- package/Sources/Private/CoreAnimation/Animations/ShapeAnimation.swift +39 -25
- package/Sources/Private/CoreAnimation/Animations/StarAnimation.swift +13 -32
- package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +4 -4
- package/Sources/Private/CoreAnimation/Animations/TransformAnimations.swift +13 -13
- package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +4 -4
- package/Sources/Private/CoreAnimation/Extensions/KeyframeGroup+exactlyOneKeyframe.swift +4 -12
- package/Sources/Private/CoreAnimation/Extensions/Keyframes+combined.swift +222 -0
- package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +1 -1
- package/Sources/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift +8 -6
- package/Sources/Private/CoreAnimation/Layers/GradientRenderLayer.swift +13 -10
- package/Sources/Private/CoreAnimation/Layers/InfiniteOpaqueAnimationLayer.swift +56 -0
- package/Sources/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +1 -1
- package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +2 -3
- package/Sources/Private/CoreAnimation/Layers/RepeaterLayer.swift +9 -9
- package/Sources/Private/CoreAnimation/Layers/ShapeItemLayer.swift +9 -3
- package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +7 -18
- package/Sources/Private/CoreAnimation/ValueProviderStore.swift +2 -3
- package/Sources/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +5 -5
- package/Sources/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift +3 -3
- package/Sources/Private/MainThread/LayerContainers/CompLayers/SolidCompositionLayer.swift +2 -2
- package/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +7 -6
- package/Sources/Private/MainThread/LayerContainers/Utility/InvertedMatteLayer.swift +1 -3
- package/Sources/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +10 -10
- package/Sources/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +7 -0
- package/Sources/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/GroupInterpolator.swift +2 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/RoundedCornersNode.swift +85 -0
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/TrimPathNode.swift +4 -4
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift +11 -12
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift +10 -11
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +2 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +5 -5
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/RectNode.swift +3 -3
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +9 -9
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +14 -14
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift +2 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +3 -3
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +10 -10
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +14 -14
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +11 -11
- package/Sources/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift +1 -1
- package/Sources/Private/Model/DotLottie/DotLottieAnimation.swift +52 -0
- package/Sources/Private/Model/DotLottie/DotLottieConfiguration.swift +15 -0
- package/Sources/Private/Model/DotLottie/DotLottieImageProvider.swift +73 -0
- package/Sources/Private/Model/DotLottie/DotLottieManifest.swift +53 -0
- package/Sources/Private/Model/DotLottie/DotLottieUtils.swift +58 -0
- package/Sources/Private/Model/DotLottie/Zip/Data+Compression.swift +134 -0
- package/Sources/Private/Model/DotLottie/Zip/Data+Serialization.swift +87 -0
- package/Sources/Private/Model/DotLottie/Zip/FileManager+ZIP.swift +130 -0
- package/Sources/Private/Model/DotLottie/Zip/ZipArchive.swift +474 -0
- package/Sources/Private/Model/DotLottie/Zip/ZipEntry+Serialization.swift +189 -0
- package/Sources/Private/Model/DotLottie/Zip/ZipEntry+ZIP64.swift +179 -0
- package/Sources/Private/Model/DotLottie/Zip/ZipEntry.swift +227 -0
- package/Sources/Private/Model/Extensions/Bundle.swift +26 -0
- package/Sources/Private/Model/Keyframes/KeyframeData.swift +12 -12
- package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +9 -2
- package/Sources/Private/Model/Layers/LayerModel.swift +1 -1
- package/Sources/Private/Model/Layers/PreCompLayerModel.swift +3 -3
- package/Sources/Private/Model/Layers/TextLayerModel.swift +1 -1
- package/Sources/Private/Model/Objects/DashPattern.swift +2 -2
- package/Sources/Private/Model/Objects/Mask.swift +10 -8
- package/Sources/Private/Model/Objects/Transform.swift +39 -35
- package/Sources/Private/Model/ShapeItems/Ellipse.swift +6 -6
- package/Sources/Private/Model/ShapeItems/Fill.swift +6 -6
- package/Sources/Private/Model/ShapeItems/GradientFill.swift +15 -15
- package/Sources/Private/Model/ShapeItems/GradientStroke.swift +19 -19
- package/Sources/Private/Model/ShapeItems/Rectangle.swift +9 -9
- package/Sources/Private/Model/ShapeItems/Repeater.swift +37 -32
- package/Sources/Private/Model/ShapeItems/RoundedCorners.swift +47 -0
- package/Sources/Private/Model/ShapeItems/ShapeItem.swift +4 -0
- package/Sources/Private/Model/ShapeItems/ShapeTransform.swift +34 -28
- package/Sources/Private/Model/ShapeItems/Star.swift +21 -21
- package/Sources/Private/Model/ShapeItems/Stroke.swift +10 -10
- package/Sources/Private/Model/ShapeItems/Trim.swift +9 -9
- package/Sources/Private/Model/Text/Font.swift +1 -1
- package/Sources/Private/Model/Text/TextAnimator.swift +33 -33
- package/Sources/Private/Model/Text/TextDocument.swift +8 -8
- package/Sources/Private/RootAnimationLayer.swift +4 -4
- package/Sources/Private/Utility/Debugging/LayerDebugging.swift +12 -18
- package/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift +2 -2
- package/Sources/Private/Utility/Extensions/CGColor+RGB.swift +12 -7
- package/Sources/Private/Utility/Interpolatable/InterpolatableExtensions.swift +1 -1
- package/Sources/Private/Utility/Interpolatable/KeyframeGroup+Extensions.swift +4 -4
- package/Sources/Private/Utility/Primitives/BezierPathRoundExtension.swift +147 -0
- package/Sources/Private/Utility/Primitives/ColorExtension.swift +8 -11
- package/Sources/Private/Utility/Primitives/VectorsExtensions.swift +22 -22
- package/Sources/{Private/Model/Animation.swift → Public/Animation/LottieAnimation.swift} +8 -8
- package/Sources/Public/Animation/{AnimationPublic.swift → LottieAnimationHelpers.swift} +62 -27
- package/Sources/Public/Animation/{AnimationView.swift → LottieAnimationView.swift} +122 -26
- package/Sources/Public/Animation/LottieAnimationViewInitializers.swift +222 -0
- package/Sources/Public/AnimationCache/AnimationCacheProvider.swift +4 -4
- package/Sources/Public/AnimationCache/DefaultAnimationCache.swift +54 -0
- package/Sources/Public/AnimationCache/LRUAnimationCache.swift +4 -52
- package/Sources/Public/AnimationCache/LottieAnimationCache.swift +15 -0
- package/Sources/Public/DotLottie/Cache/DotLottieCache.swift +53 -0
- package/Sources/Public/DotLottie/Cache/DotLottieCacheProvider.swift +23 -0
- package/Sources/Public/DotLottie/DotLottieFile.swift +161 -0
- package/Sources/Public/DotLottie/DotLottieFileHelpers.swift +265 -0
- package/Sources/Public/DynamicProperties/AnimationKeypath.swift +3 -3
- package/Sources/Public/DynamicProperties/AnyValueProvider.swift +2 -2
- package/Sources/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift +10 -10
- package/Sources/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift +4 -4
- package/Sources/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +5 -5
- package/Sources/Public/DynamicProperties/ValueProviders/PointValueProvider.swift +2 -2
- package/Sources/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift +2 -2
- package/Sources/Public/FontProvider/AnimationFontProvider.swift +1 -1
- package/Sources/Public/ImageProvider/AnimationImageProvider.swift +2 -2
- package/Sources/Public/Keyframes/Interpolatable.swift +17 -17
- package/Sources/Public/Keyframes/Keyframe.swift +10 -10
- package/Sources/Public/LottieConfiguration.swift +25 -7
- package/Sources/Public/Primitives/{Color.swift → LottieColor.swift} +3 -3
- package/Sources/Public/Primitives/Vectors.swift +4 -4
- package/Sources/Public/TextProvider/AnimationTextProvider.swift +1 -1
- package/Sources/Public/iOS/AnimatedButton.swift +1 -1
- package/Sources/Public/iOS/AnimatedControl.swift +6 -6
- package/Sources/Public/iOS/AnimatedSwitch.swift +1 -1
- package/Sources/Public/iOS/Compatibility/CompatibleAnimationView.swift +8 -8
- package/Sources/Public/iOS/{AnimationViewBase.swift → LottieAnimationViewBase.swift} +4 -4
- package/Sources/Public/iOS/UIColorExtension.swift +2 -2
- package/Sources/Public/macOS/{AnimationViewBase.macOS.swift → LottieAnimationViewBase.macOS.swift} +4 -4
- package/Tests/AnimationCacheProviderTests.swift +40 -0
- package/Tests/AnimationKeypathTests.swift +20 -13
- package/Tests/AnimationViewTests.swift +64 -0
- package/Tests/AutomaticEngineTests.swift +11 -2
- package/Tests/ParsingTests.swift +4 -2
- package/Tests/PerformanceTests.swift +9 -9
- package/Tests/SnapshotConfiguration.swift +7 -7
- package/Tests/SnapshotTests.swift +57 -27
- package/Tests/ValueProvidersTests.swift +9 -6
- package/lottie-ios.podspec +4 -4
- package/package.json +2 -2
- package/script/test-carthage/Cartfile +1 -1
- package/script/test-carthage/CarthageTest/ViewController.swift +1 -1
- package/script/test-carthage/CarthageTest-macOS/ViewController.swift +1 -1
- package/Sources/Private/CoreAnimation/Extensions/Keyframes+combinedIfPossible.swift +0 -154
- package/Sources/Public/Animation/AnimationViewInitializers.swift +0 -109
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw== +0 -1
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~7IO4FqH8-VUsSfuA0_wMGUgfGdV7MwzpkzjwWbiB50jXZKQRHtU4G0A7ZXTvsR4mDdrWiawpNC_eriOALfZ7Og== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~ClRW5-6rvrgZHHbrPS1VEREaxelpVcKlERPzSa3f2rtFNXdoqATxFCsPge3a_nO4mhhtpmTmbYvyfI-obAu8Qg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~Jr2dFGcJc1188nMoMha82z9wM99lCLm4MKzhjfVVjIxKeCZVGWGZH3HgJFNkTpozdk5p1u5o91dCiY4-cR1Zhg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~MBDeCFoahVzzmtSQrVhhy9VMJV6CmcnUkFya_qwe0XsMFscmY2nS8dxrTEYkY16sH68sEH7WVCCzTuW1z1Hocw== +0 -1
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~U4plJajEDM_uSZdglhDyj6gQO63mbeKxYP9X94aIaOtL0yErtfQnGz5SgsqQ0ToSZcJj6Ao9Wx-nesZVwBTRuw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~UsLY5O-vDMEHEe3bF8XJvkKkYxdsKlIytgJW7zgNuetw53fG3SssfZiiMfbuYnOtvvvYBXTwpbz07V6Czp029Q== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~cpg4cb7H0TaehHy4a-xINJMFfBM2_AEHal_0tIX8ymNVJPsjlCysi3-Cad0Ca_SvuGwVM7ONF55OBUuC9YKZvA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~cuHjdTCuciVumvEpvozxwDj2wAdgWe13bzd1pUAGN45-WOgY0kIid9aUlBX675OnS-xNEc_pyQWo0RO1dKAjcw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~f_-bfn-KRHHFg39_MtwgBulEAuWH6F05yqGYydXhil6kqZ51eAoRX6tsiqOr0Oa6eL3dK1tcCBD1bWX5orCZhw== +0 -1
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~jdIx7vWS6ej1cqYcbCS4KyZErSMF13ELR95YwClVc98tIXcsglh7KuGvI1gIxEPDtPXQpfC3XijIAGn1quL8Dw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~lz3e0YeBa8TvMBSSymToh--gc6zznUIdH2jO0AJ4so5OPNdw6wpYmJebhaENGsRoD3beUXvlyD5f7_WeZrzyNQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~u_5dWbliYJ__YkyUCDFjdxiFds9M8Epr_RvbU1rIRCbBQdhRJ_TUBXXcL_Qq-wVp4umNLTOzud4OpQItSpO6Rg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~v-YGzhC2l_icsAsyp1XAbEWYwxNook-rARAWlVZINioEsgT9LGvhg2oh78nYqoeH78m1fihr5HCcGNfF7SQj0g== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~7IO4FqH8-VUsSfuA0_wMGUgfGdV7MwzpkzjwWbiB50jXZKQRHtU4G0A7ZXTvsR4mDdrWiawpNC_eriOALfZ7Og== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~ClRW5-6rvrgZHHbrPS1VEREaxelpVcKlERPzSa3f2rtFNXdoqATxFCsPge3a_nO4mhhtpmTmbYvyfI-obAu8Qg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~Jr2dFGcJc1188nMoMha82z9wM99lCLm4MKzhjfVVjIxKeCZVGWGZH3HgJFNkTpozdk5p1u5o91dCiY4-cR1Zhg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~MBDeCFoahVzzmtSQrVhhy9VMJV6CmcnUkFya_qwe0XsMFscmY2nS8dxrTEYkY16sH68sEH7WVCCzTuW1z1Hocw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~U4plJajEDM_uSZdglhDyj6gQO63mbeKxYP9X94aIaOtL0yErtfQnGz5SgsqQ0ToSZcJj6Ao9Wx-nesZVwBTRuw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~UsLY5O-vDMEHEe3bF8XJvkKkYxdsKlIytgJW7zgNuetw53fG3SssfZiiMfbuYnOtvvvYBXTwpbz07V6Czp029Q== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~cpg4cb7H0TaehHy4a-xINJMFfBM2_AEHal_0tIX8ymNVJPsjlCysi3-Cad0Ca_SvuGwVM7ONF55OBUuC9YKZvA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~cuHjdTCuciVumvEpvozxwDj2wAdgWe13bzd1pUAGN45-WOgY0kIid9aUlBX675OnS-xNEc_pyQWo0RO1dKAjcw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~f_-bfn-KRHHFg39_MtwgBulEAuWH6F05yqGYydXhil6kqZ51eAoRX6tsiqOr0Oa6eL3dK1tcCBD1bWX5orCZhw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~jdIx7vWS6ej1cqYcbCS4KyZErSMF13ELR95YwClVc98tIXcsglh7KuGvI1gIxEPDtPXQpfC3XijIAGn1quL8Dw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~lz3e0YeBa8TvMBSSymToh--gc6zznUIdH2jO0AJ4so5OPNdw6wpYmJebhaENGsRoD3beUXvlyD5f7_WeZrzyNQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~u_5dWbliYJ__YkyUCDFjdxiFds9M8Epr_RvbU1rIRCbBQdhRJ_TUBXXcL_Qq-wVp4umNLTOzud4OpQItSpO6Rg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~v-YGzhC2l_icsAsyp1XAbEWYwxNook-rARAWlVZINioEsgT9LGvhg2oh78nYqoeH78m1fihr5HCcGNfF7SQj0g== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Info.plist +0 -29
|
@@ -19,6 +19,24 @@
|
|
|
19
19
|
"version": "0.7.0"
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
|
+
{
|
|
23
|
+
"package": "AirbnbSwift",
|
|
24
|
+
"repositoryURL": "https://github.com/airbnb/swift",
|
|
25
|
+
"state": {
|
|
26
|
+
"branch": null,
|
|
27
|
+
"revision": "7884f265499752cc5eccaa9eba08b4a2f8b73357",
|
|
28
|
+
"version": null
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"package": "swift-argument-parser",
|
|
33
|
+
"repositoryURL": "https://github.com/apple/swift-argument-parser",
|
|
34
|
+
"state": {
|
|
35
|
+
"branch": null,
|
|
36
|
+
"revision": "fddd1c00396eed152c45a46bea9f47b98e59301d",
|
|
37
|
+
"version": "1.2.0"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
22
40
|
{
|
|
23
41
|
"package": "swift-snapshot-testing",
|
|
24
42
|
"repositoryURL": "https://github.com/pointfreeco/swift-snapshot-testing.git",
|
package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate
CHANGED
|
Binary file
|
package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
CHANGED
|
@@ -5,33 +5,12 @@
|
|
|
5
5
|
version = "2.0">
|
|
6
6
|
<Breakpoints>
|
|
7
7
|
<BreakpointProxy
|
|
8
|
-
BreakpointExtensionID = "Xcode.Breakpoint.
|
|
8
|
+
BreakpointExtensionID = "Xcode.Breakpoint.SwiftErrorBreakpoint">
|
|
9
9
|
<BreakpointContent
|
|
10
|
-
uuid = "
|
|
11
|
-
shouldBeEnabled = "Yes"
|
|
12
|
-
ignoreCount = "0"
|
|
13
|
-
continueAfterRunningActions = "No"
|
|
14
|
-
filePath = "Sources/Private/CoreAnimation/Animations/VisibilityAnimation.swift"
|
|
15
|
-
startingColumnNumber = "9223372036854775807"
|
|
16
|
-
endingColumnNumber = "9223372036854775807"
|
|
17
|
-
startingLineNumber = "44"
|
|
18
|
-
endingLineNumber = "44">
|
|
19
|
-
</BreakpointContent>
|
|
20
|
-
</BreakpointProxy>
|
|
21
|
-
<BreakpointProxy
|
|
22
|
-
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
23
|
-
<BreakpointContent
|
|
24
|
-
uuid = "90B95B81-4B28-4BCD-AE7B-59ED8AA81AC1"
|
|
10
|
+
uuid = "C6EE3985-FE51-481D-807F-F4B9BE9FB067"
|
|
25
11
|
shouldBeEnabled = "No"
|
|
26
12
|
ignoreCount = "0"
|
|
27
|
-
continueAfterRunningActions = "No"
|
|
28
|
-
filePath = "Sources/Private/MainThread/NodeRenderSystem/NodeProperties/NodeProperty.swift"
|
|
29
|
-
startingColumnNumber = "9223372036854775807"
|
|
30
|
-
endingColumnNumber = "9223372036854775807"
|
|
31
|
-
startingLineNumber = "49"
|
|
32
|
-
endingLineNumber = "49"
|
|
33
|
-
landmarkName = "update(frame:)"
|
|
34
|
-
landmarkType = "7">
|
|
13
|
+
continueAfterRunningActions = "No">
|
|
35
14
|
</BreakpointContent>
|
|
36
15
|
</BreakpointProxy>
|
|
37
16
|
</Breakpoints>
|
package/Package.swift
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// swift-tools-version:5.
|
|
1
|
+
// swift-tools-version:5.5
|
|
2
2
|
import PackageDescription
|
|
3
3
|
|
|
4
4
|
let package = Package(
|
|
5
5
|
name: "Lottie",
|
|
6
6
|
platforms: [.iOS("11.0"), .macOS("10.10"), .tvOS("11.0")],
|
|
7
7
|
products: [.library(name: "Lottie", targets: ["Lottie"])],
|
|
8
|
-
targets: [.target(name: "Lottie", path: "Sources")])
|
|
8
|
+
targets: [.target(name: "Lottie", path: "Sources")])
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Lottie for iOS
|
|
2
2
|
[](https://cocoapods.org/pods/lottie-ios) [](https://github.com/Carthage/Carthage) [](https://swift.org/package-manager/) [](https://cocoapods.org/pods/lottie-ios) [](https://swiftpackageindex.com/airbnb/lottie-ios) [](https://swiftpackageindex.com/airbnb/lottie-ios)
|
|
3
3
|
|
|
4
|
-
**View documentation, FAQ, help, examples, and more at [airbnb.io/lottie](
|
|
4
|
+
**View documentation, FAQ, help, examples, and more at [airbnb.io/lottie](https://airbnb.io/lottie/)**
|
|
5
5
|
|
|
6
|
-
Lottie is a cross-platform library for iOS, macOS, tvOS, [Android](https://github.com/airbnb/lottie), and [Web](https://github.com/airbnb/lottie-web) that natively renders vector-based animations and art in realtime with minimal code.
|
|
6
|
+
Lottie is a cross-platform library for iOS, macOS, tvOS, [Android](https://github.com/airbnb/lottie-android), and [Web](https://github.com/airbnb/lottie-web) that natively renders vector-based animations and art in realtime with minimal code.
|
|
7
7
|
|
|
8
8
|
Lottie loads and renders animations and vectors exported in the bodymovin JSON format. Bodymovin JSON can be created and exported from After Effects with [bodymovin](https://github.com/bodymovin/bodymovin), Sketch with [Lottie Sketch Export](https://github.com/buba447/Lottie-Sketch-Export), and from [Haiku](https://www.haiku.ai).
|
|
9
9
|
|
|
10
|
-
Designers can create **and ship** beautiful animations without an engineer painstakingly recreating
|
|
10
|
+
Designers can create **and ship** beautiful animations without an engineer painstakingly recreating them by hand.
|
|
11
11
|
Since the animation is backed by JSON they are extremely small in size but can be large in complexity!
|
|
12
12
|
Animations can be played, resized, looped, sped up, slowed down, reversed, and even interactively scrubbed.
|
|
13
13
|
Lottie can play or loop just a portion of the animation as well, the possibilities are endless!
|
|
@@ -75,6 +75,13 @@ We always appreciate contributions from the community. To make changes to the pr
|
|
|
75
75
|
- unit tests and snapshot tests (for iOS, must be run on an iPhone 8 simulator)
|
|
76
76
|
- an Example iOS app that lets you browse and test over 100 sample animations included in the repo
|
|
77
77
|
|
|
78
|
+
To reduce the size of the repository, snapshot images are stored using [Git Large File Storage](https://git-lfs.github.com/). Before running the snapshot tests, you'll need to install Git LFS:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
$ brew install git-lfs
|
|
82
|
+
$ git lfs install
|
|
83
|
+
```
|
|
84
|
+
|
|
78
85
|
All pull requests with new features or bug fixes that affect how animations render should include snapshot test cases that validate the included changes.
|
|
79
86
|
- To add a new sample animation to the snapshot testing suite, you can add the `.json` file to `Tests/Samples`. Re-run the snapshot tests to generate the new snapshot image files.
|
|
80
87
|
- To update existing snapshots after making changes, you can set `isRecording = true` in `SnapshotTests.swift` and then re-run the snapshot tests.
|
package/Rakefile
CHANGED
|
@@ -136,7 +136,7 @@ def formatTool(command)
|
|
|
136
136
|
url: "https://github.com/airbnb/swift",
|
|
137
137
|
// Since we don't have a Package.resolved for this, we need to reference a specific commit
|
|
138
138
|
// so changes to the style guide don't cause this repo's checks to start failing.
|
|
139
|
-
.revision("
|
|
139
|
+
.revision("7884f265499752cc5eccaa9eba08b4a2f8b73357")))
|
|
140
140
|
#endif
|
|
141
141
|
EOC
|
|
142
142
|
|
|
@@ -44,8 +44,7 @@ extension CALayer {
|
|
|
44
44
|
keyframes: ContiguousArray<Keyframe<KeyframeValue>>,
|
|
45
45
|
value keyframeValueMapping: (KeyframeValue) throws -> ValueRepresentation,
|
|
46
46
|
context: LayerAnimationContext)
|
|
47
|
-
throws
|
|
48
|
-
-> CAAnimation?
|
|
47
|
+
throws -> CAAnimation?
|
|
49
48
|
{
|
|
50
49
|
guard !keyframes.isEmpty else { return nil }
|
|
51
50
|
|
|
@@ -82,13 +81,12 @@ extension CALayer {
|
|
|
82
81
|
|
|
83
82
|
/// A `CAAnimation` that applies the custom value from the `AnyValueProvider`
|
|
84
83
|
/// registered for this specific property's `AnimationKeypath`,
|
|
85
|
-
/// if one has been registered using `
|
|
84
|
+
/// if one has been registered using `LottieAnimationView.setValueProvider(_:keypath:)`.
|
|
86
85
|
@nonobjc
|
|
87
86
|
private func customizedAnimation<ValueRepresentation>(
|
|
88
87
|
for property: LayerProperty<ValueRepresentation>,
|
|
89
88
|
context: LayerAnimationContext)
|
|
90
|
-
throws
|
|
91
|
-
-> CAPropertyAnimation?
|
|
89
|
+
throws -> CAPropertyAnimation?
|
|
92
90
|
{
|
|
93
91
|
guard
|
|
94
92
|
let customizableProperty = property.customizableProperty,
|
|
@@ -162,8 +160,7 @@ extension CALayer {
|
|
|
162
160
|
animationSegments: [[Keyframe<KeyframeValue>]],
|
|
163
161
|
value keyframeValueMapping: (KeyframeValue) throws -> ValueRepresentation,
|
|
164
162
|
context: LayerAnimationContext)
|
|
165
|
-
throws
|
|
166
|
-
-> CAAnimationGroup
|
|
163
|
+
throws -> CAAnimationGroup
|
|
167
164
|
{
|
|
168
165
|
// Build the `CAKeyframeAnimation` for each segment of keyframes
|
|
169
166
|
// with the same `CAAnimationCalculationMode`.
|
|
@@ -233,8 +230,8 @@ extension CALayer {
|
|
|
233
230
|
NSNumber(value: Float(context.progressTime(for: keyframeModel.time)))
|
|
234
231
|
}
|
|
235
232
|
|
|
236
|
-
var timingFunctions =
|
|
237
|
-
let calculationMode =
|
|
233
|
+
var timingFunctions = timingFunctions(for: keyframes)
|
|
234
|
+
let calculationMode = calculationMode(for: keyframes)
|
|
238
235
|
|
|
239
236
|
let animation = CAKeyframeAnimation(keyPath: property.caLayerKeypath)
|
|
240
237
|
|
|
@@ -10,14 +10,24 @@ extension CAShapeLayer {
|
|
|
10
10
|
for customPath: KeyframeGroup<BezierPath>,
|
|
11
11
|
context: LayerAnimationContext,
|
|
12
12
|
pathMultiplier: PathMultiplier = 1,
|
|
13
|
-
transformPath: (CGPath) -> CGPath = { $0 }
|
|
13
|
+
transformPath: (CGPath) -> CGPath = { $0 },
|
|
14
|
+
roundedCorners: RoundedCorners? = nil)
|
|
14
15
|
throws
|
|
15
16
|
{
|
|
17
|
+
let combinedKeyframes = try BezierPathKeyframe.combining(
|
|
18
|
+
path: customPath,
|
|
19
|
+
cornerRadius: roundedCorners?.radius)
|
|
20
|
+
|
|
16
21
|
try addAnimation(
|
|
17
22
|
for: .path,
|
|
18
|
-
keyframes:
|
|
23
|
+
keyframes: combinedKeyframes.keyframes,
|
|
19
24
|
value: { pathKeyframe in
|
|
20
|
-
|
|
25
|
+
var path = pathKeyframe.path
|
|
26
|
+
if let cornerRadius = pathKeyframe.cornerRadius {
|
|
27
|
+
path = path.roundCorners(radius: cornerRadius.cgFloatValue)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return transformPath(path.cgPath().duplicated(times: pathMultiplier))
|
|
21
31
|
},
|
|
22
32
|
context: context)
|
|
23
33
|
}
|
|
@@ -39,3 +49,32 @@ extension CGPath {
|
|
|
39
49
|
return cgPath
|
|
40
50
|
}
|
|
41
51
|
}
|
|
52
|
+
|
|
53
|
+
// MARK: - BezierPathKeyframe
|
|
54
|
+
|
|
55
|
+
/// Data that represents how to render a bezier path at a specific point in time
|
|
56
|
+
struct BezierPathKeyframe {
|
|
57
|
+
let path: BezierPath
|
|
58
|
+
let cornerRadius: LottieVector1D?
|
|
59
|
+
|
|
60
|
+
/// Creates a single array of animatable keyframes from the given sets of keyframes
|
|
61
|
+
/// that can have different counts / timing parameters
|
|
62
|
+
static func combining(
|
|
63
|
+
path: KeyframeGroup<BezierPath>,
|
|
64
|
+
cornerRadius: KeyframeGroup<LottieVector1D>?) throws
|
|
65
|
+
-> KeyframeGroup<BezierPathKeyframe>
|
|
66
|
+
{
|
|
67
|
+
guard
|
|
68
|
+
let cornerRadius = cornerRadius,
|
|
69
|
+
cornerRadius.keyframes.contains(where: { $0.value.cgFloatValue > 0 })
|
|
70
|
+
else {
|
|
71
|
+
return path.map { path in
|
|
72
|
+
BezierPathKeyframe(path: path, cornerRadius: nil)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return Keyframes.combined(
|
|
77
|
+
path, cornerRadius,
|
|
78
|
+
makeCombinedResult: BezierPathKeyframe.init)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -14,7 +14,7 @@ extension CAShapeLayer {
|
|
|
14
14
|
{
|
|
15
15
|
try addAnimation(
|
|
16
16
|
for: .path,
|
|
17
|
-
keyframes: ellipse.combinedKeyframes(
|
|
17
|
+
keyframes: ellipse.combinedKeyframes().keyframes,
|
|
18
18
|
value: { keyframe in
|
|
19
19
|
BezierPath.ellipse(
|
|
20
20
|
size: keyframe.size.sizeValue,
|
|
@@ -30,26 +30,14 @@ extension CAShapeLayer {
|
|
|
30
30
|
extension Ellipse {
|
|
31
31
|
/// Data that represents how to render an ellipse at a specific point in time
|
|
32
32
|
struct Keyframe {
|
|
33
|
-
let size:
|
|
34
|
-
let position:
|
|
33
|
+
let size: LottieVector3D
|
|
34
|
+
let position: LottieVector3D
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/// Creates a single array of animatable keyframes from the separate arrays of keyframes in this Ellipse
|
|
38
|
-
func combinedKeyframes(
|
|
39
|
-
|
|
38
|
+
func combinedKeyframes() throws -> KeyframeGroup<Ellipse.Keyframe> {
|
|
39
|
+
Keyframes.combined(
|
|
40
40
|
size, position,
|
|
41
41
|
makeCombinedResult: Ellipse.Keyframe.init)
|
|
42
|
-
|
|
43
|
-
if let combinedKeyframes = combinedKeyframes {
|
|
44
|
-
return combinedKeyframes
|
|
45
|
-
} else {
|
|
46
|
-
// If we weren't able to combine all of the keyframes, we have to take the timing values
|
|
47
|
-
// from one property and use a fixed value for the other properties.
|
|
48
|
-
return try size.map { sizeValue in
|
|
49
|
-
Keyframe(
|
|
50
|
-
size: sizeValue,
|
|
51
|
-
position: try position.exactlyOneKeyframe(context: context, description: "ellipse position"))
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
42
|
}
|
|
55
43
|
}
|
|
@@ -7,8 +7,8 @@ import QuartzCore
|
|
|
7
7
|
|
|
8
8
|
/// A `ShapeItem` that represents a gradient
|
|
9
9
|
protocol GradientShapeItem: OpacityAnimationModel {
|
|
10
|
-
var startPoint: KeyframeGroup<
|
|
11
|
-
var endPoint: KeyframeGroup<
|
|
10
|
+
var startPoint: KeyframeGroup<LottieVector3D> { get }
|
|
11
|
+
var endPoint: KeyframeGroup<LottieVector3D> { get }
|
|
12
12
|
var gradientType: GradientType { get }
|
|
13
13
|
var numberOfColors: Int { get }
|
|
14
14
|
var colors: KeyframeGroup<[Double]> { get }
|
|
@@ -111,23 +111,31 @@ extension GradientRenderLayer {
|
|
|
111
111
|
private func addRadialGradientAnimations(for gradient: GradientShapeItem, context: LayerAnimationContext) throws {
|
|
112
112
|
type = .radial
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
114
|
+
let combinedKeyframes = Keyframes.combined(
|
|
115
|
+
gradient.startPoint, gradient.endPoint,
|
|
116
|
+
makeCombinedResult: { absoluteStartPoint, absoluteEndPoint -> (startPoint: CGPoint, endPoint: CGPoint) in
|
|
117
|
+
// Convert the absolute start / end points to the relative structure used by Core Animation
|
|
118
|
+
let relativeStartPoint = percentBasedPointInBounds(from: absoluteStartPoint.pointValue)
|
|
119
|
+
let radius = absoluteStartPoint.pointValue.distanceTo(absoluteEndPoint.pointValue)
|
|
120
|
+
let relativeEndPoint = percentBasedPointInBounds(
|
|
121
|
+
from: CGPoint(
|
|
122
|
+
x: absoluteStartPoint.x + radius,
|
|
123
|
+
y: absoluteStartPoint.y + radius))
|
|
124
|
+
|
|
125
|
+
return (startPoint: relativeStartPoint, endPoint: relativeEndPoint)
|
|
126
|
+
})
|
|
123
127
|
|
|
124
|
-
|
|
128
|
+
try addAnimation(
|
|
129
|
+
for: .startPoint,
|
|
130
|
+
keyframes: combinedKeyframes.keyframes,
|
|
131
|
+
value: \.startPoint,
|
|
132
|
+
context: context)
|
|
125
133
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
134
|
+
try addAnimation(
|
|
135
|
+
for: .endPoint,
|
|
136
|
+
keyframes: combinedKeyframes.keyframes,
|
|
137
|
+
value: \.endPoint,
|
|
138
|
+
context: context)
|
|
131
139
|
}
|
|
132
140
|
}
|
|
133
141
|
|
|
@@ -28,7 +28,7 @@ struct LayerProperty<ValueRepresentation: Equatable> {
|
|
|
28
28
|
// MARK: - CustomizableProperty
|
|
29
29
|
|
|
30
30
|
/// A description of how a `CALayer` property can be customized dynamically
|
|
31
|
-
/// at runtime using `
|
|
31
|
+
/// at runtime using `LottieAnimationView.setValueProvider(_:keypath:)`
|
|
32
32
|
struct CustomizableProperty<ValueRepresentation> {
|
|
33
33
|
/// The name that `AnimationKeypath`s can use to refer to this property
|
|
34
34
|
/// - When building an animation for this property that will be applied
|
|
@@ -219,7 +219,7 @@ extension CustomizableProperty {
|
|
|
219
219
|
.init(
|
|
220
220
|
name: [.color],
|
|
221
221
|
conversion: { typeErasedValue in
|
|
222
|
-
guard let color = typeErasedValue as?
|
|
222
|
+
guard let color = typeErasedValue as? LottieColor else {
|
|
223
223
|
return nil
|
|
224
224
|
}
|
|
225
225
|
|
|
@@ -9,12 +9,13 @@ extension CAShapeLayer {
|
|
|
9
9
|
func addAnimations(
|
|
10
10
|
for rectangle: Rectangle,
|
|
11
11
|
context: LayerAnimationContext,
|
|
12
|
-
pathMultiplier: PathMultiplier
|
|
12
|
+
pathMultiplier: PathMultiplier,
|
|
13
|
+
roundedCorners: RoundedCorners?)
|
|
13
14
|
throws
|
|
14
15
|
{
|
|
15
16
|
try addAnimation(
|
|
16
17
|
for: .path,
|
|
17
|
-
keyframes: try rectangle.combinedKeyframes(
|
|
18
|
+
keyframes: try rectangle.combinedKeyframes(roundedCorners: roundedCorners).keyframes,
|
|
18
19
|
value: { keyframe in
|
|
19
20
|
BezierPath.rectangle(
|
|
20
21
|
position: keyframe.position.pointValue,
|
|
@@ -31,28 +32,16 @@ extension CAShapeLayer {
|
|
|
31
32
|
extension Rectangle {
|
|
32
33
|
/// Data that represents how to render a rectangle at a specific point in time
|
|
33
34
|
struct Keyframe {
|
|
34
|
-
let size:
|
|
35
|
-
let position:
|
|
36
|
-
let cornerRadius:
|
|
35
|
+
let size: LottieVector3D
|
|
36
|
+
let position: LottieVector3D
|
|
37
|
+
let cornerRadius: LottieVector1D
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
/// Creates a single array of animatable keyframes from the separate arrays of keyframes in this Rectangle
|
|
40
|
-
func combinedKeyframes(
|
|
41
|
-
let
|
|
41
|
+
func combinedKeyframes(roundedCorners: RoundedCorners?) throws -> KeyframeGroup<Rectangle.Keyframe> {
|
|
42
|
+
let cornerRadius = roundedCorners?.radius ?? cornerRadius
|
|
43
|
+
return Keyframes.combined(
|
|
42
44
|
size, position, cornerRadius,
|
|
43
45
|
makeCombinedResult: Rectangle.Keyframe.init)
|
|
44
|
-
|
|
45
|
-
if let combinedKeyframes = combinedKeyframes {
|
|
46
|
-
return combinedKeyframes
|
|
47
|
-
} else {
|
|
48
|
-
// If we weren't able to combine all of the keyframes, we have to take the timing values
|
|
49
|
-
// from one property and use a fixed value for the other properties.
|
|
50
|
-
return try size.map { sizeValue in
|
|
51
|
-
Keyframe(
|
|
52
|
-
size: sizeValue,
|
|
53
|
-
position: try position.exactlyOneKeyframe(context: context, description: "rectangle position"),
|
|
54
|
-
cornerRadius: try cornerRadius.exactlyOneKeyframe(context: context, description: "rectangle cornerRadius"))
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
46
|
}
|
|
58
47
|
}
|
|
@@ -9,23 +9,38 @@ extension CAShapeLayer {
|
|
|
9
9
|
func addAnimations(
|
|
10
10
|
for shape: ShapeItem,
|
|
11
11
|
context: LayerAnimationContext,
|
|
12
|
-
pathMultiplier: PathMultiplier
|
|
12
|
+
pathMultiplier: PathMultiplier,
|
|
13
|
+
roundedCorners: RoundedCorners?) throws
|
|
13
14
|
{
|
|
14
15
|
switch shape {
|
|
15
16
|
case let customShape as Shape:
|
|
16
|
-
try addAnimations(
|
|
17
|
+
try addAnimations(
|
|
18
|
+
for: customShape.path,
|
|
19
|
+
context: context,
|
|
20
|
+
pathMultiplier: pathMultiplier,
|
|
21
|
+
roundedCorners: roundedCorners)
|
|
17
22
|
|
|
18
23
|
case let combinedShape as CombinedShapeItem:
|
|
19
24
|
try addAnimations(for: combinedShape, context: context, pathMultiplier: pathMultiplier)
|
|
25
|
+
try context.compatibilityAssert(roundedCorners == nil, """
|
|
26
|
+
Rounded corners support is not currently implemented for combined shape items
|
|
27
|
+
""")
|
|
20
28
|
|
|
21
29
|
case let ellipse as Ellipse:
|
|
22
30
|
try addAnimations(for: ellipse, context: context, pathMultiplier: pathMultiplier)
|
|
23
31
|
|
|
24
32
|
case let rectangle as Rectangle:
|
|
25
|
-
try addAnimations(
|
|
33
|
+
try addAnimations(
|
|
34
|
+
for: rectangle,
|
|
35
|
+
context: context,
|
|
36
|
+
pathMultiplier: pathMultiplier,
|
|
37
|
+
roundedCorners: roundedCorners)
|
|
26
38
|
|
|
27
39
|
case let star as Star:
|
|
28
40
|
try addAnimations(for: star, context: context, pathMultiplier: pathMultiplier)
|
|
41
|
+
try context.compatibilityAssert(roundedCorners == nil, """
|
|
42
|
+
Rounded corners support is currently not implemented for polygon items
|
|
43
|
+
""")
|
|
29
44
|
|
|
30
45
|
default:
|
|
31
46
|
// None of the other `ShapeItem` subclasses draw a `path`
|
|
@@ -51,7 +66,7 @@ extension CAShapeLayer {
|
|
|
51
66
|
/// Adds animations for `strokeStart` and `strokeEnd` from the given `Trim` object
|
|
52
67
|
@nonobjc
|
|
53
68
|
func addAnimations(for trim: Trim, context: LayerAnimationContext) throws -> PathMultiplier {
|
|
54
|
-
let (strokeStartKeyframes, strokeEndKeyframes, pathMultiplier) = try trim.caShapeLayerKeyframes(
|
|
69
|
+
let (strokeStartKeyframes, strokeEndKeyframes, pathMultiplier) = try trim.caShapeLayerKeyframes()
|
|
55
70
|
|
|
56
71
|
try addAnimation(
|
|
57
72
|
for: .strokeStart,
|
|
@@ -87,11 +102,12 @@ extension Trim {
|
|
|
87
102
|
/// The `strokeStart` and `strokeEnd` keyframes to apply to a `CAShapeLayer`,
|
|
88
103
|
/// plus a `pathMultiplier` that should be applied to the layer's `path` so that
|
|
89
104
|
/// trim values larger than 100% can be displayed properly.
|
|
90
|
-
fileprivate func caShapeLayerKeyframes(
|
|
91
|
-
|
|
105
|
+
fileprivate func caShapeLayerKeyframes()
|
|
106
|
+
throws
|
|
107
|
+
-> (strokeStart: KeyframeGroup<LottieVector1D>, strokeEnd: KeyframeGroup<LottieVector1D>, pathMultiplier: PathMultiplier)
|
|
92
108
|
{
|
|
93
|
-
let strokeStart: KeyframeGroup<
|
|
94
|
-
let strokeEnd: KeyframeGroup<
|
|
109
|
+
let strokeStart: KeyframeGroup<LottieVector1D>
|
|
110
|
+
let strokeEnd: KeyframeGroup<LottieVector1D>
|
|
95
111
|
|
|
96
112
|
// CAShapeLayer requires strokeStart to be less than strokeEnd. This
|
|
97
113
|
// isn't required by the Lottie schema, so some animations may have
|
|
@@ -123,14 +139,12 @@ extension Trim {
|
|
|
123
139
|
var adjustedStrokeStart = KeyframeGroup(
|
|
124
140
|
keyframes: try adjustKeyframesForTrimOffsets(
|
|
125
141
|
strokeKeyframes: interpolatedStrokeStart,
|
|
126
|
-
offsetKeyframes: interpolatedStrokeOffset
|
|
127
|
-
context: context))
|
|
142
|
+
offsetKeyframes: interpolatedStrokeOffset))
|
|
128
143
|
|
|
129
144
|
var adjustedStrokeEnd = KeyframeGroup(
|
|
130
145
|
keyframes: try adjustKeyframesForTrimOffsets(
|
|
131
146
|
strokeKeyframes: interpolatedStrokeEnd,
|
|
132
|
-
offsetKeyframes: interpolatedStrokeOffset
|
|
133
|
-
context: context))
|
|
147
|
+
offsetKeyframes: interpolatedStrokeOffset))
|
|
134
148
|
|
|
135
149
|
// If maximum stroke value is larger than 100%, then we have to create copies of the path
|
|
136
150
|
// so the total path length includes the maximum stroke
|
|
@@ -142,8 +156,8 @@ extension Trim {
|
|
|
142
156
|
if minimumStrokeMultiplier < 0 {
|
|
143
157
|
// Core Animation doesn't support negative stroke offsets, so we have to
|
|
144
158
|
// shift all of the offset values up by the minimum
|
|
145
|
-
adjustedStrokeStart = adjustedStrokeStart.map {
|
|
146
|
-
adjustedStrokeEnd = adjustedStrokeEnd.map {
|
|
159
|
+
adjustedStrokeStart = adjustedStrokeStart.map { LottieVector1D($0.value + (abs(minimumStrokeMultiplier) * 100.0)) }
|
|
160
|
+
adjustedStrokeEnd = adjustedStrokeEnd.map { LottieVector1D($0.value + (abs(minimumStrokeMultiplier) * 100.0)) }
|
|
147
161
|
}
|
|
148
162
|
|
|
149
163
|
return (
|
|
@@ -164,8 +178,8 @@ extension Trim {
|
|
|
164
178
|
|
|
165
179
|
for keyframeTime in keyframeTimes {
|
|
166
180
|
guard
|
|
167
|
-
let startAtTime = startInterpolator.value(frame: keyframeTime) as?
|
|
168
|
-
let endAtTime = endInterpolator.value(frame: keyframeTime) as?
|
|
181
|
+
let startAtTime = startInterpolator.value(frame: keyframeTime) as? LottieVector1D,
|
|
182
|
+
let endAtTime = endInterpolator.value(frame: keyframeTime) as? LottieVector1D
|
|
169
183
|
else { continue }
|
|
170
184
|
|
|
171
185
|
if startAtTime.cgFloatValue < endAtTime.cgFloatValue {
|
|
@@ -184,9 +198,9 @@ extension Trim {
|
|
|
184
198
|
///
|
|
185
199
|
/// - Precondition: The keyframes must be interpolated using `KeyframeGroup.manuallyInterpolateKeyframes()`
|
|
186
200
|
private func adjustKeyframesForTrimOffsets(
|
|
187
|
-
strokeKeyframes: ContiguousArray<Keyframe<
|
|
188
|
-
offsetKeyframes: ContiguousArray<Keyframe<
|
|
189
|
-
|
|
201
|
+
strokeKeyframes: ContiguousArray<Keyframe<LottieVector1D>>,
|
|
202
|
+
offsetKeyframes: ContiguousArray<Keyframe<LottieVector1D>>)
|
|
203
|
+
throws -> ContiguousArray<Keyframe<LottieVector1D>>
|
|
190
204
|
{
|
|
191
205
|
guard
|
|
192
206
|
!strokeKeyframes.isEmpty,
|
|
@@ -196,7 +210,7 @@ extension Trim {
|
|
|
196
210
|
}
|
|
197
211
|
|
|
198
212
|
// Map each time to its corresponding stroke/offset keyframe
|
|
199
|
-
var timeMap = [AnimationFrameTime: [Keyframe<
|
|
213
|
+
var timeMap = [AnimationFrameTime: [Keyframe<LottieVector1D>?]]()
|
|
200
214
|
for stroke in strokeKeyframes {
|
|
201
215
|
timeMap[stroke.time] = [stroke, nil]
|
|
202
216
|
}
|
|
@@ -210,9 +224,9 @@ extension Trim {
|
|
|
210
224
|
}
|
|
211
225
|
|
|
212
226
|
// Each time will be mapped to a new, adjusted keyframe
|
|
213
|
-
var output = ContiguousArray<Keyframe<
|
|
214
|
-
var lastKeyframe: Keyframe<
|
|
215
|
-
var lastOffset: Keyframe<
|
|
227
|
+
var output = ContiguousArray<Keyframe<LottieVector1D>>()
|
|
228
|
+
var lastKeyframe: Keyframe<LottieVector1D>?
|
|
229
|
+
var lastOffset: Keyframe<LottieVector1D>?
|
|
216
230
|
|
|
217
231
|
for (time, values) in timeMap.sorted(by: { $0.0 < $1.0 }) {
|
|
218
232
|
// Extract keyframe/offset associated with this timestamp
|
|
@@ -240,8 +254,8 @@ extension Trim {
|
|
|
240
254
|
let adjustedValue = strokeValue + (offsetValue / 360 * 100)
|
|
241
255
|
|
|
242
256
|
// The tangent values are all `nil` as the keyframes should have been manually interpolated
|
|
243
|
-
let adjustedKeyframe = Keyframe<
|
|
244
|
-
value:
|
|
257
|
+
let adjustedKeyframe = Keyframe<LottieVector1D>(
|
|
258
|
+
value: LottieVector1D(adjustedValue),
|
|
245
259
|
time: time,
|
|
246
260
|
isHold: currentKeyframe.isHold,
|
|
247
261
|
inTangent: nil,
|
|
@@ -36,7 +36,7 @@ extension CAShapeLayer {
|
|
|
36
36
|
{
|
|
37
37
|
try addAnimation(
|
|
38
38
|
for: .path,
|
|
39
|
-
keyframes: try star.combinedKeyframes(
|
|
39
|
+
keyframes: try star.combinedKeyframes().keyframes,
|
|
40
40
|
value: { keyframe in
|
|
41
41
|
BezierPath.star(
|
|
42
42
|
position: keyframe.position.pointValue,
|
|
@@ -62,7 +62,7 @@ extension CAShapeLayer {
|
|
|
62
62
|
{
|
|
63
63
|
try addAnimation(
|
|
64
64
|
for: .path,
|
|
65
|
-
keyframes: try star.combinedKeyframes(
|
|
65
|
+
keyframes: try star.combinedKeyframes().keyframes,
|
|
66
66
|
value: { keyframe in
|
|
67
67
|
BezierPath.polygon(
|
|
68
68
|
position: keyframe.position.pointValue,
|
|
@@ -81,44 +81,25 @@ extension CAShapeLayer {
|
|
|
81
81
|
extension Star {
|
|
82
82
|
/// Data that represents how to render a star at a specific point in time
|
|
83
83
|
struct Keyframe {
|
|
84
|
-
let position:
|
|
85
|
-
let outerRadius:
|
|
86
|
-
let innerRadius:
|
|
87
|
-
let outerRoundness:
|
|
88
|
-
let innerRoundness:
|
|
89
|
-
let points:
|
|
90
|
-
let rotation:
|
|
84
|
+
let position: LottieVector3D
|
|
85
|
+
let outerRadius: LottieVector1D
|
|
86
|
+
let innerRadius: LottieVector1D
|
|
87
|
+
let outerRoundness: LottieVector1D
|
|
88
|
+
let innerRoundness: LottieVector1D
|
|
89
|
+
let points: LottieVector1D
|
|
90
|
+
let rotation: LottieVector1D
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/// Creates a single array of animatable keyframes from the separate arrays of keyframes in this star/polygon
|
|
94
|
-
func combinedKeyframes(
|
|
95
|
-
|
|
94
|
+
func combinedKeyframes() throws -> KeyframeGroup<Keyframe> {
|
|
95
|
+
Keyframes.combined(
|
|
96
96
|
position,
|
|
97
97
|
outerRadius,
|
|
98
|
-
innerRadius ?? KeyframeGroup(
|
|
98
|
+
innerRadius ?? KeyframeGroup(LottieVector1D(0)),
|
|
99
99
|
outerRoundness,
|
|
100
|
-
innerRoundness ?? KeyframeGroup(
|
|
100
|
+
innerRoundness ?? KeyframeGroup(LottieVector1D(0)),
|
|
101
101
|
points,
|
|
102
102
|
rotation,
|
|
103
103
|
makeCombinedResult: Star.Keyframe.init)
|
|
104
|
-
|
|
105
|
-
if let combinedKeyframes = combinedKeyframes {
|
|
106
|
-
return combinedKeyframes
|
|
107
|
-
} else {
|
|
108
|
-
// If we weren't able to combine all of the keyframes, we have to take the timing values
|
|
109
|
-
// from one property and use a fixed value for the other properties.
|
|
110
|
-
return try position.map { positionValue in
|
|
111
|
-
Keyframe(
|
|
112
|
-
position: positionValue,
|
|
113
|
-
outerRadius: try outerRadius.exactlyOneKeyframe(context: context, description: "star outerRadius"),
|
|
114
|
-
innerRadius: try innerRadius?.exactlyOneKeyframe(context: context, description: "star innerRadius")
|
|
115
|
-
?? Vector1D(0),
|
|
116
|
-
outerRoundness: try outerRoundness.exactlyOneKeyframe(context: context, description: "star outerRoundness"),
|
|
117
|
-
innerRoundness: try innerRoundness?.exactlyOneKeyframe(context: context, description: "star innerRoundness")
|
|
118
|
-
?? Vector1D(0),
|
|
119
|
-
points: try points.exactlyOneKeyframe(context: context, description: "star points"),
|
|
120
|
-
rotation: try rotation.exactlyOneKeyframe(context: context, description: "star rotation"))
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
104
|
}
|
|
124
105
|
}
|