lottie-ios 3.4.2 → 3.4.4
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/FUNDING.yml +0 -11
- package/Lottie.xcodeproj/project.pbxproj +6 -2
- package/Lottie.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +22 -0
- package/Lottie.xcworkspace/xcshareddata/swiftpm/Package.resolved +2 -2
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +16 -0
- package/Sources/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift +10 -7
- package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +17 -5
- package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +5 -4
- package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +25 -12
- package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +3 -0
- package/Sources/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +1 -0
- package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +2 -2
- package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +4 -4
- package/Sources/Private/CoreAnimation/Layers/TextLayer.swift +15 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +12 -1
- package/Sources/Private/Model/Objects/Marker.swift +4 -0
- package/Sources/Public/Animation/AnimationPublic.swift +17 -1
- package/Sources/Public/Animation/AnimationView.swift +43 -0
- package/Sources/Public/iOS/AnimatedButton.swift +25 -23
- package/Sources/Public/iOS/AnimatedSwitch.swift +15 -10
- package/Sources/Public/iOS/Compatibility/CompatibleAnimationView.swift +15 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw== +1 -0
- 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== +1 -0
- 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== +1 -0
- 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 +29 -0
- package/Tests/AutomaticEngineTests.swift +1 -0
- package/Tests/SnapshotConfiguration.swift +15 -1
- package/Tests/SnapshotTests.swift +4 -0
- package/Tests/Utils/HardcodedTextProvider.swift +27 -0
- package/lottie-ios.podspec +1 -1
- package/package.json +1 -1
- package/Tests/Samples/9squares_AlBoardman.json +0 -1
- package/Tests/Samples/Boat_Loader.json +0 -1
- package/Tests/Samples/HamburgerArrow.json +0 -1
- package/Tests/Samples/IconTransitions.json +0 -1
- package/Tests/Samples/Images/dog.png +0 -0
- package/Tests/Samples/Issues/issue_1125.json +0 -1
- package/Tests/Samples/Issues/issue_1260.json +0 -1
- package/Tests/Samples/Issues/issue_1403.json +0 -1
- package/Tests/Samples/Issues/issue_1407.json +0 -1
- package/Tests/Samples/Issues/issue_1460.json +0 -1
- package/Tests/Samples/Issues/issue_1488.json +0 -1
- package/Tests/Samples/Issues/issue_1505.json +0 -1
- package/Tests/Samples/Issues/issue_1541.json +0 -1
- package/Tests/Samples/Issues/issue_1557.json +0 -1
- package/Tests/Samples/Issues/issue_1603.json +0 -1
- package/Tests/Samples/Issues/issue_1628.json +0 -1
- package/Tests/Samples/Issues/issue_1636.json +0 -1
- package/Tests/Samples/Issues/issue_1643.json +0 -1
- package/Tests/Samples/Issues/issue_1655.json +0 -1
- package/Tests/Samples/Issues/issue_1664.json +0 -1
- package/Tests/Samples/Issues/issue_1683.json +0 -1
- package/Tests/Samples/Issues/issue_1687.json +0 -1
- package/Tests/Samples/Issues/issue_1711.json +0 -1
- package/Tests/Samples/Issues/issue_1717.json +0 -1
- package/Tests/Samples/Issues/issue_769.json +0 -1
- package/Tests/Samples/Issues/issue_885.json +0 -1
- package/Tests/Samples/Issues/issue_965.json +0 -1
- package/Tests/Samples/Issues/pr_1536.json +0 -1
- package/Tests/Samples/Issues/pr_1563.json +0 -8439
- package/Tests/Samples/Issues/pr_1592.json +0 -5527
- package/Tests/Samples/Issues/pr_1599.json +0 -738
- package/Tests/Samples/Issues/pr_1604_1.json +0 -1
- package/Tests/Samples/Issues/pr_1604_2.json +0 -1
- package/Tests/Samples/Issues/pr_1632_1.json +0 -1
- package/Tests/Samples/Issues/pr_1632_2.json +0 -1
- package/Tests/Samples/Issues/pr_1686.json +0 -513
- package/Tests/Samples/Issues/pr_1698.json +0 -1
- package/Tests/Samples/Issues/pr_1699.json +0 -1
- package/Tests/Samples/LottieFiles/LICENSE.md +0 -14
- package/Tests/Samples/LottieFiles/bounce_strokes.json +0 -1
- package/Tests/Samples/LottieFiles/cactus.json +0 -1
- package/Tests/Samples/LottieFiles/dog_car_ride.json +0 -1
- package/Tests/Samples/LottieFiles/draft_icon.json +0 -1
- package/Tests/Samples/LottieFiles/fireworks.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_1.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_2.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_pill.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_shapes.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_square.json +0 -1
- package/Tests/Samples/LottieFiles/growth.json +0 -1
- package/Tests/Samples/LottieFiles/infinity_loader.json +0 -1
- package/Tests/Samples/LottieFiles/loading_dots_1.json +0 -1
- package/Tests/Samples/LottieFiles/loading_dots_2.json +0 -1
- package/Tests/Samples/LottieFiles/loading_dots_3.json +0 -1
- package/Tests/Samples/LottieFiles/loading_gradient_strokes.json +0 -1
- package/Tests/Samples/LottieFiles/settings_slider.json +0 -1
- package/Tests/Samples/LottieFiles/shop.json +0 -1
- package/Tests/Samples/LottieFiles/step_loader.json +0 -1
- package/Tests/Samples/LottieLogo1.json +0 -1
- package/Tests/Samples/LottieLogo1_masked.json +0 -1
- package/Tests/Samples/LottieLogo2.json +0 -1
- package/Tests/Samples/MotionCorpse_Jrcanest.json +0 -1
- package/Tests/Samples/Nonanimating/BasicLayers.json +0 -1
- package/Tests/Samples/Nonanimating/DisableNodesTest.json +0 -1
- package/Tests/Samples/Nonanimating/FirstText.json +0 -1
- package/Tests/Samples/Nonanimating/GeometryTransformTest.json +0 -1
- package/Tests/Samples/Nonanimating/Text_AnimatedProperties.json +0 -1
- package/Tests/Samples/Nonanimating/Text_Glyph.json +0 -1
- package/Tests/Samples/Nonanimating/Text_NoAnimation.json +0 -1
- package/Tests/Samples/Nonanimating/Text_NoGlyph.json +0 -1
- package/Tests/Samples/Nonanimating/Zoom.json +0 -1
- package/Tests/Samples/Nonanimating/_dog.json +0 -1
- package/Tests/Samples/Nonanimating/base64Test.json +0 -1
- package/Tests/Samples/Nonanimating/blend_mode_test.json +0 -1
- package/Tests/Samples/Nonanimating/keypathTest.json +0 -1
- package/Tests/Samples/Nonanimating/verifyLineHeight.json +0 -1
- package/Tests/Samples/PinJump.json +0 -1
- package/Tests/Samples/Switch.json +0 -1
- package/Tests/Samples/Switch_States.json +0 -1
- package/Tests/Samples/TwitterHeart.json +0 -1
- package/Tests/Samples/TwitterHeartButton.json +0 -1
- package/Tests/Samples/TypeFace/A.json +0 -1
- package/Tests/Samples/TypeFace/Apostrophe.json +0 -1
- package/Tests/Samples/TypeFace/B.json +0 -1
- package/Tests/Samples/TypeFace/BlinkingCursor.json +0 -1
- package/Tests/Samples/TypeFace/C.json +0 -1
- package/Tests/Samples/TypeFace/Colon.json +0 -1
- package/Tests/Samples/TypeFace/Comma.json +0 -1
- package/Tests/Samples/TypeFace/D.json +0 -1
- package/Tests/Samples/TypeFace/E.json +0 -1
- package/Tests/Samples/TypeFace/F.json +0 -1
- package/Tests/Samples/TypeFace/G.json +0 -1
- package/Tests/Samples/TypeFace/H.json +0 -1
- package/Tests/Samples/TypeFace/I.json +0 -1
- package/Tests/Samples/TypeFace/J.json +0 -1
- package/Tests/Samples/TypeFace/K.json +0 -1
- package/Tests/Samples/TypeFace/L.json +0 -1
- package/Tests/Samples/TypeFace/M.json +0 -1
- package/Tests/Samples/TypeFace/N.json +0 -1
- package/Tests/Samples/TypeFace/O.json +0 -1
- package/Tests/Samples/TypeFace/P.json +0 -1
- package/Tests/Samples/TypeFace/Q.json +0 -1
- package/Tests/Samples/TypeFace/R.json +0 -1
- package/Tests/Samples/TypeFace/S.json +0 -1
- package/Tests/Samples/TypeFace/T.json +0 -1
- package/Tests/Samples/TypeFace/U.json +0 -1
- package/Tests/Samples/TypeFace/V.json +0 -1
- package/Tests/Samples/TypeFace/W.json +0 -1
- package/Tests/Samples/TypeFace/X.json +0 -1
- package/Tests/Samples/TypeFace/Y.json +0 -1
- package/Tests/Samples/TypeFace/Z.json +0 -1
- package/Tests/Samples/Watermelon.json +0 -1
- package/Tests/Samples/setValueTest.json +0 -1
- package/Tests/Samples/timeremap.json +0 -1
- package/Tests/Samples/vcTransition1.json +0 -1
- package/Tests/Samples/vcTransition2.json +0 -1
package/.github/FUNDING.yml
CHANGED
|
@@ -1,12 +1 @@
|
|
|
1
|
-
# These are supported funding model platforms
|
|
2
|
-
|
|
3
|
-
github: [buba447]
|
|
4
|
-
patreon: # Replace with a single Patreon username
|
|
5
1
|
open_collective: lottie
|
|
6
|
-
ko_fi: # Replace with a single Ko-fi username
|
|
7
|
-
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
8
|
-
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
9
|
-
liberapay: # Replace with a single Liberapay username
|
|
10
|
-
issuehunt: # Replace with a single IssueHunt username
|
|
11
|
-
otechie: # Replace with a single Otechie username
|
|
12
|
-
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
@@ -554,6 +554,7 @@
|
|
|
554
554
|
2EAF5B0427A0798700E00531 /* AnimationFontProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */; };
|
|
555
555
|
2EAF5B0527A0798700E00531 /* AnimationFontProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */; };
|
|
556
556
|
2EAF5B0627A0798700E00531 /* AnimationFontProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */; };
|
|
557
|
+
36E57EAC28AF7ADF00B7EFDA /* HardcodedTextProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36E57EAB28AF7ADF00B7EFDA /* HardcodedTextProvider.swift */; };
|
|
557
558
|
6D0E635F28246BD0007C5DB6 /* Difference in Frameworks */ = {isa = PBXBuildFile; productRef = 6D0E635E28246BD0007C5DB6 /* Difference */; };
|
|
558
559
|
6D99D6432823790700E5205B /* LegacyGradientFillRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D99D6422823790700E5205B /* LegacyGradientFillRenderer.swift */; };
|
|
559
560
|
6D99D6442823790700E5205B /* LegacyGradientFillRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D99D6422823790700E5205B /* LegacyGradientFillRenderer.swift */; };
|
|
@@ -783,6 +784,7 @@
|
|
|
783
784
|
2EAF59EF27A0798700E00531 /* GradientValueProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientValueProvider.swift; sourceTree = "<group>"; };
|
|
784
785
|
2EAF59F027A0798700E00531 /* PointValueProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PointValueProvider.swift; sourceTree = "<group>"; };
|
|
785
786
|
2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimationFontProvider.swift; sourceTree = "<group>"; };
|
|
787
|
+
36E57EAB28AF7ADF00B7EFDA /* HardcodedTextProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HardcodedTextProvider.swift; sourceTree = "<group>"; };
|
|
786
788
|
6D99D6422823790700E5205B /* LegacyGradientFillRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyGradientFillRenderer.swift; sourceTree = "<group>"; };
|
|
787
789
|
6DB3BDB528243FA5002A276D /* ValueProvidersTests.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = ValueProvidersTests.swift; sourceTree = "<group>"; tabWidth = 2; };
|
|
788
790
|
6DB3BDB7282454A6002A276D /* DictionaryInitializable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryInitializable.swift; sourceTree = "<group>"; };
|
|
@@ -876,6 +878,7 @@
|
|
|
876
878
|
2E8040BF27A07343006E74CB /* Snapshotting+presentationLayer.swift */,
|
|
877
879
|
2EAF59A627A076BC00E00531 /* Bundle+Module.swift */,
|
|
878
880
|
2E09FA0527B6CEB600BA84E5 /* HardcodedFontProvider.swift */,
|
|
881
|
+
36E57EAB28AF7ADF00B7EFDA /* HardcodedTextProvider.swift */,
|
|
879
882
|
);
|
|
880
883
|
path = Utils;
|
|
881
884
|
sourceTree = "<group>";
|
|
@@ -1876,6 +1879,7 @@
|
|
|
1876
1879
|
6DEF696E2824A76C007D640F /* BundleTests.swift in Sources */,
|
|
1877
1880
|
2EAF59A727A076BC00E00531 /* Bundle+Module.swift in Sources */,
|
|
1878
1881
|
2E8044AE27A07347006E74CB /* Snapshotting+presentationLayer.swift in Sources */,
|
|
1882
|
+
36E57EAC28AF7ADF00B7EFDA /* HardcodedTextProvider.swift in Sources */,
|
|
1879
1883
|
2E72128527BB32DB0027BC56 /* PerformanceTests.swift in Sources */,
|
|
1880
1884
|
6DB3BDC328245AA2002A276D /* ParsingTests.swift in Sources */,
|
|
1881
1885
|
6DB3BDB628243FA5002A276D /* ValueProvidersTests.swift in Sources */,
|
|
@@ -2670,8 +2674,8 @@
|
|
|
2670
2674
|
isa = XCRemoteSwiftPackageReference;
|
|
2671
2675
|
repositoryURL = "https://github.com/pointfreeco/swift-snapshot-testing.git";
|
|
2672
2676
|
requirement = {
|
|
2673
|
-
|
|
2674
|
-
|
|
2677
|
+
kind = revision;
|
|
2678
|
+
revision = 0c2826f26d00ff5ddf2de92cb6b2139b0dd3d1ee;
|
|
2675
2679
|
};
|
|
2676
2680
|
};
|
|
2677
2681
|
6D0E635D28246BD0007C5DB6 /* XCRemoteSwiftPackageReference "Difference" */ = {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pins" : [
|
|
3
|
+
{
|
|
4
|
+
"identity" : "difference",
|
|
5
|
+
"kind" : "remoteSourceControl",
|
|
6
|
+
"location" : "https://github.com/krzysztofzablocki/Difference",
|
|
7
|
+
"state" : {
|
|
8
|
+
"revision" : "02fe1111edc8318c4f8a0da96336fcbcc201f38b",
|
|
9
|
+
"version" : "1.0.1"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"identity" : "swift-snapshot-testing",
|
|
14
|
+
"kind" : "remoteSourceControl",
|
|
15
|
+
"location" : "https://github.com/pointfreeco/swift-snapshot-testing.git",
|
|
16
|
+
"state" : {
|
|
17
|
+
"revision" : "0c2826f26d00ff5ddf2de92cb6b2139b0dd3d1ee"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"version" : 2
|
|
22
|
+
}
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"package": "swift-snapshot-testing",
|
|
24
24
|
"repositoryURL": "https://github.com/pointfreeco/swift-snapshot-testing.git",
|
|
25
25
|
"state": {
|
|
26
|
-
"branch":
|
|
27
|
-
"revision": "
|
|
26
|
+
"branch": null,
|
|
27
|
+
"revision": "0c2826f26d00ff5ddf2de92cb6b2139b0dd3d1ee",
|
|
28
28
|
"version": null
|
|
29
29
|
}
|
|
30
30
|
}
|
package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate
CHANGED
|
Binary file
|
package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
CHANGED
|
@@ -18,5 +18,21 @@
|
|
|
18
18
|
endingLineNumber = "44">
|
|
19
19
|
</BreakpointContent>
|
|
20
20
|
</BreakpointProxy>
|
|
21
|
+
<BreakpointProxy
|
|
22
|
+
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
23
|
+
<BreakpointContent
|
|
24
|
+
uuid = "90B95B81-4B28-4BCD-AE7B-59ED8AA81AC1"
|
|
25
|
+
shouldBeEnabled = "No"
|
|
26
|
+
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">
|
|
35
|
+
</BreakpointContent>
|
|
36
|
+
</BreakpointProxy>
|
|
21
37
|
</Breakpoints>
|
|
22
38
|
</Bucket>
|
|
@@ -56,22 +56,25 @@ extension CombinedShapeItem {
|
|
|
56
56
|
/// Manually combines the given shape keyframes by manually interpolating at each frame
|
|
57
57
|
static func manuallyInterpolating(
|
|
58
58
|
shapes: [KeyframeGroup<BezierPath>],
|
|
59
|
-
name: String
|
|
60
|
-
context: LayerContext)
|
|
59
|
+
name: String)
|
|
61
60
|
-> CombinedShapeItem
|
|
62
61
|
{
|
|
63
|
-
let animationTimeRange = Int(context.animation.startFrame)...Int(context.animation.endFrame)
|
|
64
|
-
|
|
65
62
|
let interpolators = shapes.map { shape in
|
|
66
63
|
KeyframeInterpolator(keyframes: shape.keyframes)
|
|
67
64
|
}
|
|
68
65
|
|
|
69
|
-
let
|
|
66
|
+
let times = shapes.flatMap { $0.keyframes.map { $0.time } }
|
|
67
|
+
|
|
68
|
+
let minimumTime = times.min() ?? 0
|
|
69
|
+
let maximumTime = times.max() ?? 0
|
|
70
|
+
let animationLocalTimeRange = Int(minimumTime)...Int(maximumTime)
|
|
71
|
+
|
|
72
|
+
let interpolatedKeyframes = animationLocalTimeRange.map { localTime in
|
|
70
73
|
Keyframe(
|
|
71
74
|
value: interpolators.compactMap { interpolator in
|
|
72
|
-
interpolator.value(frame: AnimationFrameTime(
|
|
75
|
+
interpolator.value(frame: AnimationFrameTime(localTime)) as? BezierPath
|
|
73
76
|
},
|
|
74
|
-
time: AnimationFrameTime(
|
|
77
|
+
time: AnimationFrameTime(localTime))
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
return CombinedShapeItem(
|
|
@@ -36,11 +36,23 @@ extension GradientRenderLayer {
|
|
|
36
36
|
type: GradientContentType,
|
|
37
37
|
context: LayerAnimationContext) throws
|
|
38
38
|
{
|
|
39
|
-
// We have to set `colors` to
|
|
40
|
-
// for the
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
// We have to set `colors` and `locations` to non-nil values
|
|
40
|
+
// for the animations below to actually take effect
|
|
41
|
+
locations = []
|
|
42
|
+
|
|
43
|
+
// The initial value for `colors` must be an array with the exact same number of colors
|
|
44
|
+
// as the gradient that will be applied in the `CAAnimation`
|
|
45
|
+
switch type {
|
|
46
|
+
case .rgb:
|
|
47
|
+
colors = .init(
|
|
48
|
+
repeating: CGColor.rgb(0, 0, 0),
|
|
49
|
+
count: gradient.numberOfColors)
|
|
50
|
+
|
|
51
|
+
case .alpha:
|
|
52
|
+
colors = .init(
|
|
53
|
+
repeating: CGColor.rgb(0, 0, 0),
|
|
54
|
+
count: gradient.colorConfiguration(from: gradient.colors.keyframes[0].value, type: .alpha).count)
|
|
55
|
+
}
|
|
44
56
|
|
|
45
57
|
try addAnimation(
|
|
46
58
|
for: .colors,
|
|
@@ -55,12 +55,13 @@ extension CAShapeLayer {
|
|
|
55
55
|
try addOpacityAnimation(for: stroke, context: context)
|
|
56
56
|
|
|
57
57
|
if let (dashPattern, dashPhase) = stroke.dashPattern?.shapeLayerConfiguration {
|
|
58
|
-
lineDashPattern = try dashPattern.map {
|
|
58
|
+
let lineDashPattern = try dashPattern.map {
|
|
59
59
|
try KeyframeGroup(keyframes: $0)
|
|
60
|
-
.exactlyOneKeyframe(context: context, description: "stroke dashPattern").cgFloatValue
|
|
60
|
+
.exactlyOneKeyframe(context: context, description: "stroke dashPattern").cgFloatValue
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
|
|
63
|
+
if lineDashPattern.isSupportedLayerDashPattern {
|
|
64
|
+
self.lineDashPattern = lineDashPattern as [NSNumber]
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
try addAnimation(
|
|
@@ -17,6 +17,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
17
17
|
init(
|
|
18
18
|
animation: Animation,
|
|
19
19
|
imageProvider: AnimationImageProvider,
|
|
20
|
+
textProvider: AnimationTextProvider,
|
|
20
21
|
fontProvider: AnimationFontProvider,
|
|
21
22
|
compatibilityTrackerMode: CompatibilityTracker.Mode,
|
|
22
23
|
logger: LottieLogger)
|
|
@@ -24,6 +25,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
24
25
|
{
|
|
25
26
|
self.animation = animation
|
|
26
27
|
self.imageProvider = imageProvider
|
|
28
|
+
self.textProvider = textProvider
|
|
27
29
|
self.fontProvider = fontProvider
|
|
28
30
|
self.logger = logger
|
|
29
31
|
compatibilityTracker = CompatibilityTracker(mode: compatibilityTrackerMode, logger: logger)
|
|
@@ -44,6 +46,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
44
46
|
animation = typedLayer.animation
|
|
45
47
|
currentAnimationConfiguration = typedLayer.currentAnimationConfiguration
|
|
46
48
|
imageProvider = typedLayer.imageProvider
|
|
49
|
+
textProvider = typedLayer.textProvider
|
|
47
50
|
fontProvider = typedLayer.fontProvider
|
|
48
51
|
didSetUpAnimation = typedLayer.didSetUpAnimation
|
|
49
52
|
compatibilityTracker = typedLayer.compatibilityTracker
|
|
@@ -92,6 +95,16 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
92
95
|
didSet { reloadImages() }
|
|
93
96
|
}
|
|
94
97
|
|
|
98
|
+
/// The `AnimationTextProvider` that `TextLayer`'s use to retrieve texts,
|
|
99
|
+
/// that they should use to render their text context
|
|
100
|
+
var textProvider: AnimationTextProvider {
|
|
101
|
+
didSet {
|
|
102
|
+
// We need to rebuild the current animation after updating the text provider,
|
|
103
|
+
// since this is used in `TextLayer.setupAnimations(context:)`
|
|
104
|
+
rebuildCurrentAnimation()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
95
108
|
/// The `FontProvider` that `TextLayer`s use to retrieve the `CTFont`
|
|
96
109
|
/// that they should use to render their text content
|
|
97
110
|
var fontProvider: AnimationFontProvider {
|
|
@@ -203,6 +216,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
203
216
|
LayerContext(
|
|
204
217
|
animation: animation,
|
|
205
218
|
imageProvider: imageProvider,
|
|
219
|
+
textProvider: textProvider,
|
|
206
220
|
fontProvider: fontProvider,
|
|
207
221
|
compatibilityTracker: compatibilityTracker,
|
|
208
222
|
layerName: "root layer")
|
|
@@ -234,6 +248,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
234
248
|
compatibilityTracker: compatibilityTracker,
|
|
235
249
|
logger: logger,
|
|
236
250
|
currentKeypath: AnimationKeypath(keys: []),
|
|
251
|
+
textProvider: textProvider,
|
|
237
252
|
logHierarchyKeypaths: configuration.logHierarchyKeypaths)
|
|
238
253
|
|
|
239
254
|
// Perform a layout pass if necessary so all of the sublayers
|
|
@@ -314,11 +329,18 @@ extension CoreAnimationLayer: RootAnimationLayer {
|
|
|
314
329
|
}
|
|
315
330
|
|
|
316
331
|
var isAnimationPlaying: Bool? {
|
|
317
|
-
switch playbackState {
|
|
332
|
+
switch pendingAnimationConfiguration?.playbackState {
|
|
318
333
|
case .playing:
|
|
319
|
-
return
|
|
320
|
-
case
|
|
334
|
+
return true
|
|
335
|
+
case .paused:
|
|
321
336
|
return false
|
|
337
|
+
case nil:
|
|
338
|
+
switch playbackState {
|
|
339
|
+
case .playing:
|
|
340
|
+
return animation(forKey: #keyPath(animationProgress)) != nil
|
|
341
|
+
case nil, .paused:
|
|
342
|
+
return false
|
|
343
|
+
}
|
|
322
344
|
}
|
|
323
345
|
}
|
|
324
346
|
|
|
@@ -383,15 +405,6 @@ extension CoreAnimationLayer: RootAnimationLayer {
|
|
|
383
405
|
(sublayers ?? []).filter { $0 is AnimationLayer }
|
|
384
406
|
}
|
|
385
407
|
|
|
386
|
-
var textProvider: AnimationTextProvider {
|
|
387
|
-
get { DictionaryTextProvider([:]) }
|
|
388
|
-
set {
|
|
389
|
-
logger.assertionFailure("""
|
|
390
|
-
The Core Animation rendering engine currently doesn't support `textProvider`s")
|
|
391
|
-
""")
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
408
|
func reloadImages() {
|
|
396
409
|
// When the image provider changes, we have to update all `ImageLayer`s
|
|
397
410
|
// so they can query the most up-to-date image from the new image provider.
|
|
@@ -41,6 +41,9 @@ struct LayerAnimationContext {
|
|
|
41
41
|
/// The AnimationKeypath represented by the current layer
|
|
42
42
|
var currentKeypath: AnimationKeypath
|
|
43
43
|
|
|
44
|
+
/// The `AnimationTextProvider`
|
|
45
|
+
var textProvider: AnimationTextProvider
|
|
46
|
+
|
|
44
47
|
/// Whether or not to log `AnimationKeypath`s for all of the animation's layers
|
|
45
48
|
/// - Used for `CoreAnimationLayer.logHierarchyKeypaths()`
|
|
46
49
|
var logHierarchyKeypaths: Bool
|
|
@@ -9,6 +9,7 @@ import QuartzCore
|
|
|
9
9
|
struct LayerContext {
|
|
10
10
|
let animation: Animation
|
|
11
11
|
let imageProvider: AnimationImageProvider
|
|
12
|
+
let textProvider: AnimationTextProvider
|
|
12
13
|
let fontProvider: AnimationFontProvider
|
|
13
14
|
let compatibilityTracker: CompatibilityTracker
|
|
14
15
|
var layerName: String
|
|
@@ -68,12 +68,12 @@ final class PreCompLayer: BaseCompositionLayer {
|
|
|
68
68
|
try setupLayerAnimations(context: context)
|
|
69
69
|
|
|
70
70
|
// Precomp layers can adjust the local time of their child layers (relative to the
|
|
71
|
-
// animation's global time) via `timeRemapping` or a custom `startTime`
|
|
71
|
+
// animation's global time) via `timeRemapping` or a custom `startTime` / `timeStretch`
|
|
72
72
|
let contextForChildren = context.withTimeRemapping { [preCompLayer, timeRemappingInterpolator] layerLocalFrame in
|
|
73
73
|
if let timeRemappingInterpolator = timeRemappingInterpolator {
|
|
74
74
|
return timeRemappingInterpolator.value(frame: layerLocalFrame) as? AnimationFrameTime ?? layerLocalFrame
|
|
75
75
|
} else {
|
|
76
|
-
return layerLocalFrame + AnimationFrameTime(preCompLayer.startTime)
|
|
76
|
+
return (layerLocalFrame * AnimationFrameTime(preCompLayer.timeStretch)) + AnimationFrameTime(preCompLayer.startTime)
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -157,7 +157,7 @@ final class GroupLayer: BaseAnimationLayer {
|
|
|
157
157
|
// interpolate the path for each shape at each frame ahead of time so we can combine them
|
|
158
158
|
// into a single set of bezier path keyframes.
|
|
159
159
|
else {
|
|
160
|
-
combinedShape = .manuallyInterpolating(shapes: allPathKeyframes, name: group.name
|
|
160
|
+
combinedShape = .manuallyInterpolating(shapes: allPathKeyframes, name: group.name)
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
let sublayer = try ShapeItemLayer(
|
|
@@ -253,9 +253,9 @@ extension CALayer {
|
|
|
253
253
|
pathForChildren.append(group.name)
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
let childItems = group.items
|
|
257
|
-
|
|
258
|
-
|
|
256
|
+
let childItems = group.items
|
|
257
|
+
.filter { !$0.hidden }
|
|
258
|
+
.map { ShapeItemLayer.Item(item: $0, groupPath: pathForChildren) }
|
|
259
259
|
|
|
260
260
|
return try GroupLayer(
|
|
261
261
|
group: group,
|
|
@@ -36,6 +36,21 @@ final class TextLayer: BaseCompositionLayer {
|
|
|
36
36
|
|
|
37
37
|
// MARK: Internal
|
|
38
38
|
|
|
39
|
+
override func setupAnimations(context: LayerAnimationContext) throws {
|
|
40
|
+
try super.setupAnimations(context: context)
|
|
41
|
+
let textAnimationContext = context.addingKeypathComponent(textLayerModel.name)
|
|
42
|
+
|
|
43
|
+
let sourceText = try textLayerModel.text.exactlyOneKeyframe(
|
|
44
|
+
context: textAnimationContext,
|
|
45
|
+
description: "text layer text")
|
|
46
|
+
|
|
47
|
+
renderLayer.text = context.textProvider.textFor(
|
|
48
|
+
keypathName: textAnimationContext.currentKeypath.fullPath,
|
|
49
|
+
sourceText: sourceText.text)
|
|
50
|
+
|
|
51
|
+
renderLayer.sizeToFit()
|
|
52
|
+
}
|
|
53
|
+
|
|
39
54
|
func configureRenderLayer(with context: LayerContext) throws {
|
|
40
55
|
// We can't use `CATextLayer`, because it doesn't support enough features we use.
|
|
41
56
|
// Instead, we use the same `CoreTextRenderLayer` (with a custom `draw` implementation)
|
|
@@ -54,7 +69,6 @@ final class TextLayer: BaseCompositionLayer {
|
|
|
54
69
|
""")
|
|
55
70
|
}
|
|
56
71
|
|
|
57
|
-
renderLayer.text = text.text
|
|
58
72
|
renderLayer.font = context.fontProvider.fontFor(family: text.fontFamily, size: CGFloat(text.fontSize))
|
|
59
73
|
|
|
60
74
|
renderLayer.alignment = text.justification.textAlignment
|
|
@@ -80,7 +80,7 @@ extension Array where Element == ShapeItem {
|
|
|
80
80
|
nodeTree.paths.append(contentsOf: tree.paths)
|
|
81
81
|
nodeTree.renderContainers.append(node.container)
|
|
82
82
|
} else if item is Repeater {
|
|
83
|
-
LottieLogger.shared.
|
|
83
|
+
LottieLogger.shared.warn("""
|
|
84
84
|
The Main Thread rendering engine doesn't currently support repeaters.
|
|
85
85
|
To play an animation with repeaters, you can use the Core Animation rendering engine instead.
|
|
86
86
|
""")
|
package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift
CHANGED
|
@@ -140,7 +140,7 @@ final class GradientStrokeNode: AnimatorNode, RenderNode {
|
|
|
140
140
|
|
|
141
141
|
/// Get dash lengths
|
|
142
142
|
let dashLengths = strokeProperties.dashPattern.value.map { $0.cgFloatValue }
|
|
143
|
-
if dashLengths.count > 0,
|
|
143
|
+
if dashLengths.count > 0, dashLengths.isSupportedLayerDashPattern {
|
|
144
144
|
strokeRender.strokeRender.dashPhase = strokeProperties.dashPhase.value.cgFloatValue
|
|
145
145
|
strokeRender.strokeRender.dashLengths = dashLengths
|
|
146
146
|
} else {
|
|
@@ -118,7 +118,7 @@ final class StrokeNode: AnimatorNode, RenderNode {
|
|
|
118
118
|
|
|
119
119
|
/// Get dash lengths
|
|
120
120
|
let dashLengths = strokeProperties.dashPattern.value.map { $0.cgFloatValue }
|
|
121
|
-
if dashLengths.count > 0,
|
|
121
|
+
if dashLengths.count > 0, dashLengths.isSupportedLayerDashPattern {
|
|
122
122
|
strokeRender.dashPhase = strokeProperties.dashPhase.value.cgFloatValue
|
|
123
123
|
strokeRender.dashLengths = dashLengths
|
|
124
124
|
} else {
|
|
@@ -167,3 +167,14 @@ extension Array where Element == DashElement {
|
|
|
167
167
|
return (dashPatterns, dashPhase)
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
|
+
|
|
171
|
+
extension Array where Element == CGFloat {
|
|
172
|
+
// If all of the items in the dash pattern are zeros, then we shouldn't attempt to render it.
|
|
173
|
+
// This causes Core Animation to have extremely poor performance for some reason, even though
|
|
174
|
+
// it doesn't affect the appearance of the animation.
|
|
175
|
+
// - We check for `== 0.01` instead of `== 0` because `dashPattern.shapeLayerConfiguration`
|
|
176
|
+
// converts all `0` values to `0.01` to work around a different Core Animation rendering issue.
|
|
177
|
+
var isSupportedLayerDashPattern: Bool {
|
|
178
|
+
!allSatisfy { $0 == 0.01 }
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -15,6 +15,7 @@ final class Marker: Codable, DictionaryInitializable {
|
|
|
15
15
|
init(dictionary: [String: Any]) throws {
|
|
16
16
|
name = try dictionary.value(for: CodingKeys.name)
|
|
17
17
|
frameTime = try dictionary.value(for: CodingKeys.frameTime)
|
|
18
|
+
durationFrameTime = try dictionary.value(for: CodingKeys.durationFrameTime)
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
// MARK: Internal
|
|
@@ -22,6 +23,7 @@ final class Marker: Codable, DictionaryInitializable {
|
|
|
22
23
|
enum CodingKeys: String, CodingKey {
|
|
23
24
|
case name = "cm"
|
|
24
25
|
case frameTime = "tm"
|
|
26
|
+
case durationFrameTime = "dr"
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
/// The Marker Name
|
|
@@ -30,4 +32,6 @@ final class Marker: Codable, DictionaryInitializable {
|
|
|
30
32
|
/// The Frame time of the marker
|
|
31
33
|
let frameTime: AnimationFrameTime
|
|
32
34
|
|
|
35
|
+
/// The duration of the marker, in frames.
|
|
36
|
+
let durationFrameTime: AnimationFrameTime
|
|
33
37
|
}
|
|
@@ -172,13 +172,14 @@ extension Animation {
|
|
|
172
172
|
///
|
|
173
173
|
public static func loadedFrom(
|
|
174
174
|
url: URL,
|
|
175
|
+
session: URLSession = .shared,
|
|
175
176
|
closure: @escaping Animation.DownloadClosure,
|
|
176
177
|
animationCache: AnimationCacheProvider?)
|
|
177
178
|
{
|
|
178
179
|
if let animationCache = animationCache, let animation = animationCache.animation(forKey: url.absoluteString) {
|
|
179
180
|
closure(animation)
|
|
180
181
|
} else {
|
|
181
|
-
let task =
|
|
182
|
+
let task = session.dataTask(with: url) { data, _, error in
|
|
182
183
|
guard error == nil, let jsonData = data else {
|
|
183
184
|
DispatchQueue.main.async {
|
|
184
185
|
closure(nil)
|
|
@@ -233,6 +234,21 @@ extension Animation {
|
|
|
233
234
|
return marker.frameTime
|
|
234
235
|
}
|
|
235
236
|
|
|
237
|
+
/// Markers are a way to describe a point in time and a duration by a key name.
|
|
238
|
+
///
|
|
239
|
+
/// Markers are encoded into animation JSON. By using markers a designer can mark
|
|
240
|
+
/// playback points for a developer to use without having to worry about keeping
|
|
241
|
+
/// track of animation frames. If the animation file is updated, the developer
|
|
242
|
+
/// does not need to update playback code.
|
|
243
|
+
///
|
|
244
|
+
/// - Returns: The duration frame time for the marker, or `nil` if no marker found.
|
|
245
|
+
public func durationFrameTime(forMarker named: String) -> AnimationFrameTime? {
|
|
246
|
+
guard let marker = markerMap?[named] else {
|
|
247
|
+
return nil
|
|
248
|
+
}
|
|
249
|
+
return marker.durationFrameTime
|
|
250
|
+
}
|
|
251
|
+
|
|
236
252
|
/// Converts Frame Time (Seconds * Framerate) into Progress Time
|
|
237
253
|
/// (optionally clamped to between 0 and 1).
|
|
238
254
|
public func progressTime(
|
|
@@ -513,6 +513,32 @@ final public class AnimationView: AnimationViewBase {
|
|
|
513
513
|
addNewAnimationForContext(context)
|
|
514
514
|
}
|
|
515
515
|
|
|
516
|
+
/// Plays the animation from a named marker to the end of the marker's duration.
|
|
517
|
+
///
|
|
518
|
+
/// A marker is a point in time with an associated duration that is encoded into the
|
|
519
|
+
/// animation data and assigned a name.
|
|
520
|
+
///
|
|
521
|
+
/// NOTE: If marker is not found the play command will exit.
|
|
522
|
+
///
|
|
523
|
+
/// - Parameter marker: The start marker for the animation playback.
|
|
524
|
+
/// - Parameter loopMode: The loop behavior of the animation. If `nil` the view's `loopMode` property will be used.
|
|
525
|
+
/// - Parameter completion: An optional completion closure to be called when the animation stops.
|
|
526
|
+
public func play(
|
|
527
|
+
marker: String,
|
|
528
|
+
loopMode: LottieLoopMode? = nil,
|
|
529
|
+
completion: LottieCompletionBlock? = nil)
|
|
530
|
+
{
|
|
531
|
+
guard let from = animation?.markerMap?[marker] else {
|
|
532
|
+
return
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
play(
|
|
536
|
+
fromFrame: from.frameTime,
|
|
537
|
+
toFrame: from.frameTime + from.durationFrameTime,
|
|
538
|
+
loopMode: loopMode,
|
|
539
|
+
completion: completion)
|
|
540
|
+
}
|
|
541
|
+
|
|
516
542
|
/// Stops the animation and resets the view to its start frame.
|
|
517
543
|
///
|
|
518
544
|
/// The completion closure will be called with `false`
|
|
@@ -713,6 +739,21 @@ final public class AnimationView: AnimationViewBase {
|
|
|
713
739
|
return animation.frameTime(forMarker: named)
|
|
714
740
|
}
|
|
715
741
|
|
|
742
|
+
/// Markers are a way to describe a point in time and a duration by a key name.
|
|
743
|
+
///
|
|
744
|
+
/// Markers are encoded into animation JSON. By using markers a designer can mark
|
|
745
|
+
/// playback points for a developer to use without having to worry about keeping
|
|
746
|
+
/// track of animation frames. If the animation file is updated, the developer
|
|
747
|
+
/// does not need to update playback code.
|
|
748
|
+
///
|
|
749
|
+
/// - Returns: The duration frame time for the marker, or `nil` if no marker found.
|
|
750
|
+
public func durationFrameTime(forMarker named: String) -> AnimationFrameTime? {
|
|
751
|
+
guard let animation = animation else {
|
|
752
|
+
return nil
|
|
753
|
+
}
|
|
754
|
+
return animation.durationFrameTime(forMarker: named)
|
|
755
|
+
}
|
|
756
|
+
|
|
716
757
|
// MARK: Internal
|
|
717
758
|
|
|
718
759
|
var animationLayer: RootAnimationLayer? = nil
|
|
@@ -996,6 +1037,7 @@ final public class AnimationView: AnimationViewBase {
|
|
|
996
1037
|
let coreAnimationLayer = try CoreAnimationLayer(
|
|
997
1038
|
animation: animation,
|
|
998
1039
|
imageProvider: imageProvider.cachedImageProvider,
|
|
1040
|
+
textProvider: textProvider,
|
|
999
1041
|
fontProvider: fontProvider,
|
|
1000
1042
|
compatibilityTrackerMode: .track,
|
|
1001
1043
|
logger: logger)
|
|
@@ -1030,6 +1072,7 @@ final public class AnimationView: AnimationViewBase {
|
|
|
1030
1072
|
let coreAnimationLayer = try CoreAnimationLayer(
|
|
1031
1073
|
animation: animation,
|
|
1032
1074
|
imageProvider: imageProvider.cachedImageProvider,
|
|
1075
|
+
textProvider: textProvider,
|
|
1033
1076
|
fontProvider: fontProvider,
|
|
1034
1077
|
compatibilityTrackerMode: .abort,
|
|
1035
1078
|
logger: logger)
|
|
@@ -31,29 +31,9 @@ open class AnimatedButton: AnimatedControl {
|
|
|
31
31
|
isAccessibilityElement = true
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
// MARK:
|
|
35
|
-
|
|
36
|
-
public override var accessibilityTraits: UIAccessibilityTraits {
|
|
37
|
-
set { super.accessibilityTraits = newValue }
|
|
38
|
-
get { super.accessibilityTraits.union(.button) }
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/// Sets the play range for the given UIControlEvent.
|
|
42
|
-
public func setPlayRange(fromProgress: AnimationProgressTime, toProgress: AnimationProgressTime, event: UIControl.Event) {
|
|
43
|
-
rangesForEvents[event.rawValue] = (from: fromProgress, to: toProgress)
|
|
44
|
-
}
|
|
34
|
+
// MARK: Open
|
|
45
35
|
|
|
46
|
-
|
|
47
|
-
public func setPlayRange(fromMarker fromName: String, toMarker toName: String, event: UIControl.Event) {
|
|
48
|
-
if
|
|
49
|
-
let start = animationView.progressTime(forMarker: fromName),
|
|
50
|
-
let end = animationView.progressTime(forMarker: toName)
|
|
51
|
-
{
|
|
52
|
-
rangesForEvents[event.rawValue] = (from: start, to: end)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
public override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
|
|
36
|
+
open override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
|
|
57
37
|
let _ = super.beginTracking(touch, with: event)
|
|
58
38
|
let touchEvent = UIControl.Event.touchDown
|
|
59
39
|
if let playrange = rangesForEvents[touchEvent.rawValue] {
|
|
@@ -62,7 +42,7 @@ open class AnimatedButton: AnimatedControl {
|
|
|
62
42
|
return true
|
|
63
43
|
}
|
|
64
44
|
|
|
65
|
-
|
|
45
|
+
open override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
|
|
66
46
|
super.endTracking(touch, with: event)
|
|
67
47
|
let touchEvent: UIControl.Event
|
|
68
48
|
if let touch = touch, bounds.contains(touch.location(in: self)) {
|
|
@@ -76,6 +56,28 @@ open class AnimatedButton: AnimatedControl {
|
|
|
76
56
|
}
|
|
77
57
|
}
|
|
78
58
|
|
|
59
|
+
// MARK: Public
|
|
60
|
+
|
|
61
|
+
public override var accessibilityTraits: UIAccessibilityTraits {
|
|
62
|
+
set { super.accessibilityTraits = newValue }
|
|
63
|
+
get { super.accessibilityTraits.union(.button) }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// Sets the play range for the given UIControlEvent.
|
|
67
|
+
public func setPlayRange(fromProgress: AnimationProgressTime, toProgress: AnimationProgressTime, event: UIControl.Event) {
|
|
68
|
+
rangesForEvents[event.rawValue] = (from: fromProgress, to: toProgress)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/// Sets the play range for the given UIControlEvent.
|
|
72
|
+
public func setPlayRange(fromMarker fromName: String, toMarker toName: String, event: UIControl.Event) {
|
|
73
|
+
if
|
|
74
|
+
let start = animationView.progressTime(forMarker: fromName),
|
|
75
|
+
let end = animationView.progressTime(forMarker: toName)
|
|
76
|
+
{
|
|
77
|
+
rangesForEvents[event.rawValue] = (from: start, to: end)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
79
81
|
// MARK: Private
|
|
80
82
|
|
|
81
83
|
private var rangesForEvents: [UInt : (from: CGFloat, to: CGFloat)] =
|