├── Resources
└── sample.gif
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── Package.resolved
├── Tests
└── LottieSwiftUITests
│ └── LottieSwiftUITests.swift
├── Package.swift
├── LICENSE
├── Sources
└── LottieSwiftUI
│ ├── LottieAnimationContainerView.swift
│ ├── InternalLottieView.swift
│ └── LottieView.swift
├── .gitignore
└── README.md
/Resources/sample.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yarosl4v/LottieSwiftUI/HEAD/Resources/sample.gif
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "pins" : [
3 | {
4 | "identity" : "lottie-spm",
5 | "kind" : "remoteSourceControl",
6 | "location" : "https://github.com/airbnb/lottie-spm.git",
7 | "state" : {
8 | "revision" : "60ea4f82fba8b4cb21a75665a889e86ed4d81c6e",
9 | "version" : "4.2.0"
10 | }
11 | }
12 | ],
13 | "version" : 2
14 | }
15 |
--------------------------------------------------------------------------------
/Tests/LottieSwiftUITests/LottieSwiftUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LottieSwiftUITests.swift
3 | //
4 | //
5 | // Created by Yaroslav Spirin on 18.07.2023.
6 | //
7 |
8 | import XCTest
9 | import SwiftUI
10 | import Lottie
11 | @testable import LottieSwiftUI
12 |
13 | final class LottieSwiftUITests: XCTestCase {
14 | func testLottieViewCreation() {
15 | let lottieView = LottieView(name: "ExampleAnimation", playbackState: .constant(.playing))
16 | XCTAssertNotNil(lottieView)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.7
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "LottieSwiftUI",
8 | platforms: [.iOS(.v13)],
9 | products: [
10 | .library(
11 | name: "LottieSwiftUI",
12 | targets: ["LottieSwiftUI"]
13 | ),
14 | ],
15 | dependencies: [
16 | .package(url: "https://github.com/airbnb/lottie-spm.git", from: "4.2.0")
17 | ],
18 | targets: [
19 | .target(
20 | name: "LottieSwiftUI",
21 | dependencies: [.product(name: "Lottie", package: "lottie-spm")]
22 | ),
23 | .testTarget(
24 | name: "LottieSwiftUITests",
25 | dependencies: ["LottieSwiftUI", .product(name: "Lottie", package: "lottie-spm")]
26 | ),
27 | ]
28 | )
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Yaroslav Spirin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Sources/LottieSwiftUI/LottieAnimationContainerView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LottieAnimationContainerView.swift
3 | //
4 | //
5 | // Created by Yaroslav Spirin on 18.07.2023.
6 | //
7 |
8 | import UIKit
9 | import Lottie
10 |
11 | final class LottieAnimationContainerView: UIView {
12 |
13 | let animationView: LottieAnimationView
14 |
15 | init(name: String) {
16 | animationView = LottieAnimationView()
17 | animationView.animation = .named(name)
18 |
19 | super.init(frame: .zero)
20 |
21 | addSubview(animationView)
22 | enforceLayout()
23 | }
24 |
25 | private func enforceLayout() {
26 | animationView.translatesAutoresizingMaskIntoConstraints = false
27 | NSLayoutConstraint.activate([
28 | topAnchor.constraint(equalTo: animationView.topAnchor),
29 | bottomAnchor.constraint(equalTo: animationView.bottomAnchor),
30 | leadingAnchor.constraint(equalTo: animationView.leadingAnchor),
31 | trailingAnchor.constraint(equalTo: animationView.trailingAnchor),
32 | ])
33 | }
34 |
35 | @available(*, unavailable)
36 | required init?(coder: NSCoder) {
37 | fatalError("init(coder:) has not been implemented")
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/LottieSwiftUI/InternalLottieView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InternalLottieView.swift
3 | //
4 | //
5 | // Created by Yaroslav Spirin on 18.07.2023.
6 | //
7 |
8 | import SwiftUI
9 | import Lottie
10 |
11 | struct InternalLottieView {
12 | let name: String
13 | let animationSpeed: CGFloat
14 | let loopMode: LottieLoopMode
15 | @Binding var playbackState: LottieView.PlaybackState
16 |
17 | init(
18 | name: String,
19 | animationSpeed: CGFloat = 1.0,
20 | loopMode: LottieLoopMode = .loop,
21 | playbackState: Binding
22 | ) {
23 | self.name = name
24 | self.animationSpeed = animationSpeed
25 | self.loopMode = loopMode
26 | self._playbackState = playbackState
27 | }
28 | }
29 |
30 | extension InternalLottieView: UIViewRepresentable {
31 | func makeUIView(context: UIViewRepresentableContext) -> LottieAnimationContainerView {
32 | let container = LottieAnimationContainerView(name: name)
33 | container.animationView.loopMode = loopMode
34 | container.animationView.animationSpeed = animationSpeed
35 | updatePlaybackState(for: container.animationView)
36 | return container
37 | }
38 |
39 | func updateUIView(_ uiView: LottieAnimationContainerView, context: UIViewRepresentableContext) {
40 | updatePlaybackState(for: uiView.animationView)
41 | }
42 |
43 | private func updatePlaybackState(for animationView: LottieAnimationView) {
44 | switch playbackState {
45 | case .playing:
46 | animationView.play()
47 | case .paused:
48 | animationView.pause()
49 | case .stopped:
50 | animationView.stop()
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Sources/LottieSwiftUI/LottieView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LottieView.swift
3 | //
4 | //
5 | // Created by Yaroslav Spirin on 18.07.2023.
6 | //
7 |
8 | import SwiftUI
9 | import Lottie
10 |
11 | /// Lottie animation view accessible from SwiftUI.
12 | public struct LottieView: View {
13 | /// The state of playback for the Lottie animation.
14 | public enum PlaybackState {
15 | case playing
16 | case paused
17 | case stopped
18 | }
19 |
20 | /// The filename of the Lottie JSON animation file.
21 | let name: String
22 |
23 | /// The speed at which the animation should be played.
24 | let animationSpeed: CGFloat
25 |
26 | /// The loop mode of the animation.
27 | let loopMode: LottieLoopMode
28 |
29 | /// The playback state of the animation.
30 | @Binding var playbackState: PlaybackState
31 |
32 | /// Initializes a new `LottieView` instance with customizable options.
33 | ///
34 | /// - Parameters:
35 | /// - name: The name of the Lottie animation file (without the file extension). This file should be added to your project's assets.
36 | /// - animationSpeed: The speed of the animation. It should be a `Double` value, where `1.0` represents
37 | /// the normal speed. Defaults to `1.0`.
38 | /// - loopMode: The loop mode for the animation. Default is `LottieLoopMode.playOnce`.
39 | /// Other options include `.loop` and `.autoReverse`.
40 | /// - playbackState: The playback state of the animation. It should be a `Binding`, allowing the state to be shared between multiple views.
41 | /// This allows for the control of the animation (play, pause, stop) from the parent view.
42 | public init(
43 | name: String,
44 | animationSpeed: CGFloat = 1.0,
45 | loopMode: LottieLoopMode = .loop,
46 | playbackState: Binding
47 | ) {
48 | self.name = name
49 | self.animationSpeed = animationSpeed
50 | self.loopMode = loopMode
51 | self._playbackState = playbackState
52 | }
53 |
54 | /// Provides the content and behavior of this view.
55 | public var body: some View {
56 | InternalLottieView(
57 | name: name,
58 | animationSpeed: animationSpeed,
59 | loopMode: loopMode,
60 | playbackState: $playbackState
61 | )
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | # .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LottieSwiftUI
2 |
3 | A Swift package that provides a SwiftUI interface to the popular [Lottie](https://airbnb.design/lottie/) animation library. The LottieSwiftUI package allows you to easily add and control Lottie animations in your SwiftUI project. It offers a clean and easy-to-use API with customizable options like animation speed and loop mode.
4 |
5 |
6 |
7 | ## Features
8 |
9 | - Swift/SwiftUI native integration.
10 | - Customize animation speed.
11 | - Choose loop mode: play once, loop, or auto reverse.
12 | - Control of animation playback (play, pause, stop).
13 | - Clean, organized, and thoroughly documented code.
14 | - Efficient and performance-optimized design.
15 |
16 | ## Installation
17 |
18 | This package uses Swift Package Manager, which is integrated with Xcode. Here's how you can add **LottieSwiftUI** to your project:
19 |
20 | 1. In Xcode, select "File" > "Swift Packages" > "Add Package Dependency"
21 | 2. Enter the URL for this repository (https://github.com/yarspirin/LottieSwiftUI)
22 |
23 | ## Usage
24 |
25 | Here's an example of how you can use `LottieView` in your SwiftUI code:
26 |
27 | ```swift
28 | import SwiftUI
29 | import LottieSwiftUI
30 |
31 | struct ContentView: View {
32 | @State private var playbackState: LottieView.PlaybackState = .playing
33 |
34 | var body: some View {
35 | LottieView(
36 | name: "london_animation", // Replace with your Lottie animation name
37 | animationSpeed: 1.0,
38 | loopMode: .loop,
39 | playbackState: $playbackState
40 | )
41 | }
42 | }
43 | ```
44 |
45 |
46 |
47 | Properties:
48 |
49 | - `name`: The name of the Lottie animation file (without the file extension). This file should be added to your project's assets.
50 | - `animationSpeed`: The speed of the animation. It should be a CGFloat value, where 1.0 represents the normal speed. Defaults to 1.0.
51 | - `loopMode`: The loop mode for the animation. Default is LottieLoopMode.playOnce. Other options include .loop and .autoReverse.
52 | - `playbackState`: The playback state of the animation. It should be a `Binding`, allowing the state to be shared between multiple views. This allows for the control of the animation (play, pause, stop) from the parent view.
53 |
54 | ### Controlling Animation Playback
55 |
56 | To control the animation playback, pass a `Binding` to `PlaybackState` to `LottieView`. This will allow you to control the animation's state (play, pause, stop) from its parent view or any other part of your app. For example, you could bind it to a SwiftUI `@State` property, and then modify that state when a button is pressed to control the animation.
57 |
58 | ## Requirements
59 | - iOS 13.0+
60 | - Xcode 14.0+
61 | - Swift 5.7+
62 |
63 | ## Contributing
64 | Contributions are welcome! If you have a bug to report, a feature to request, or have the desire to contribute in another way, feel free to file an issue.
65 |
66 | ## License
67 | LottieSwiftUI is available under the MIT license. See the LICENSE file for more info.
68 |
--------------------------------------------------------------------------------