├── .DS_Store ├── .github └── FUNDING.yml ├── LICENSE.md ├── README.md ├── SwiftUI-Animations.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ ├── shubham.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ ├── shubhamsingh.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── zero.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcshareddata │ └── xcschemes │ │ └── SwiftUI-Animations.xcscheme └── xcuserdata │ ├── shubham.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ └── xcschememanagement.plist │ └── shubhamsingh.xcuserdatad │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist └── SwiftUI-Animations ├── .DS_Store ├── AppDelegate.swift ├── Assets ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── axis.imageset │ │ ├── Contents.json │ │ └── axis.png │ ├── cart-fill.imageset │ │ ├── Contents.json │ │ └── cart-fill.png │ ├── cart.imageset │ │ ├── Contents.json │ │ └── shopping-cart.png │ ├── face.imageset │ │ ├── Contents.json │ │ └── face.png │ ├── medium.imageset │ │ ├── Contents.json │ │ └── medium.png │ ├── shirt-black.imageset │ │ ├── Contents.json │ │ └── shirt-black.png │ ├── shirt-white.imageset │ │ ├── Contents.json │ │ └── shirt-white.png │ └── visa.imageset │ │ ├── Contents.json │ │ └── visa-blue-gradient-800x450-removebg-preview.png ├── Base.lproj │ └── LaunchScreen.storyboard └── Preview Content │ └── Preview Assets.xcassets │ └── Contents.json ├── Code ├── .DS_Store ├── Animations │ ├── .DS_Store │ ├── 3dLoader │ │ ├── RotatingLoaderView.swift │ │ └── Support Shapes │ │ │ ├── DashedLoaderView.swift │ │ │ ├── DotsLoaderView.swift │ │ │ ├── FlickeringView.swift │ │ │ └── RectangleLoaderView.swift │ ├── AddView │ │ ├── AddView.swift │ │ └── ExpandingView.swift │ ├── Bank Card │ │ ├── .DS_Store │ │ ├── CardBackView.swift │ │ ├── CardFrontView.swift │ │ ├── CardView.swift │ │ ├── Model │ │ │ ├── AppConstants.swift │ │ │ └── Card.swift │ │ └── Support Shapes │ │ │ ├── CardPatternOneView.swift │ │ │ └── SnapCarousel.swift │ ├── BookLoader │ │ ├── BookLoaderView.swift │ │ ├── BookPagesView.swift │ │ └── Support Shapes │ │ │ └── BookHold.swift │ ├── Cart │ │ ├── .DS_Store │ │ ├── AddCartView.swift │ │ ├── CartView.swift │ │ ├── ShirtView.swift │ │ └── SupportShapes │ │ │ ├── Tick.swift │ │ │ └── Triangle.swift │ ├── ChatBar │ │ ├── AttachmentButton.swift │ │ └── ChatBarView.swift │ ├── CircleLoader │ │ ├── .DS_Store │ │ └── CircleLoader.swift │ ├── DownloadButton │ │ ├── .DS_Store │ │ ├── DownloadButton.swift │ │ ├── DownloadStateView.swift │ │ ├── Model │ │ │ └── Downloader.swift │ │ └── Support │ │ │ ├── CircleTickShape.swift │ │ │ ├── DownloadStateView.swift │ │ │ └── DownloadingIndicatorView.swift │ ├── GithubLoader │ │ ├── GithubLoader.swift │ │ └── Support Shapes │ │ │ └── Octocat.swift │ ├── InfinityLoader │ │ ├── InfinityView.swift │ │ └── Support Shapes │ │ │ └── InfinityShape.swift │ ├── LightSwitch │ │ └── LightSwitchView.swift │ ├── Like │ │ ├── .DS_Store │ │ ├── LikeButtonView.swift │ │ ├── LikeView.swift │ │ └── Support Shapes │ │ │ ├── .DS_Store │ │ │ ├── CapusuleGroupView.swift │ │ │ ├── FloatingLike.swift │ │ │ ├── HeartImageView.swift │ │ │ ├── LowerCapsuleView.swift │ │ │ └── ShrinkingCapsule.swift │ ├── Loader │ │ ├── LoaderState.swift │ │ ├── LoaderView.swift │ │ └── Support Shapes │ │ │ └── Loader.swift │ ├── Loader2 │ │ ├── LoaderIIView.swift │ │ └── Support Shapes │ │ │ └── MovingCircleView.swift │ ├── LoginView │ │ ├── LoginView.swift │ │ └── Support Shapes │ │ │ ├── Bolt.swift │ │ │ ├── Plus.swift │ │ │ ├── RoundedTriangle.swift │ │ │ ├── ShrinkingPlus.swift │ │ │ └── SwiftUIView.swift │ ├── Octocat-Wink │ │ ├── .DS_Store │ │ ├── OctocatView.swift │ │ └── Support Shapes │ │ │ ├── OctoHead.swift │ │ │ └── OctocatLoader.swift │ ├── PillLoader │ │ ├── PillLoader.swift │ │ └── Support Shapes │ │ │ ├── FillShapes.swift │ │ │ ├── Pill 2.swift │ │ │ ├── Pill.swift │ │ │ ├── PillGroupView.swift │ │ │ ├── PillsDropView.swift │ │ │ └── WaveFill.swift │ ├── SpinningLoader │ │ └── SpinningView.swift │ ├── SubmitView │ │ ├── SubmitView.swift │ │ └── Support Shapes │ │ │ └── RotatingCircle.swift │ ├── TriangleLoader │ │ ├── Support │ │ │ └── TriangleShape.swift │ │ └── TriangleLoader.swift │ ├── Wifi │ │ ├── .DS_Store │ │ ├── ArcView.swift │ │ ├── CircleEmitter.swift │ │ ├── Support Shapes │ │ │ ├── Arc.swift │ │ │ └── Circles.swift │ │ └── WifiView.swift │ └── YinYang-Toggle │ │ ├── ViewModels │ │ └── YinYangViewModel.swift │ │ └── Views │ │ ├── Support Shapes │ │ └── YinYangShape.swift │ │ ├── Support Views │ │ ├── YinYangToggleView.swift │ │ └── YinYangView.swift │ │ └── YinYangAnimationView.swift ├── Modules │ └── Home │ │ └── IntroView.swift ├── Services │ └── HapticManager.swift └── Utils │ └── Colors.swift ├── GIFs ├── .DS_Store ├── 3-d-Loader.gif ├── addView.gif ├── book-loader.gif ├── cards.gif ├── cart.gif ├── chat-bar.gif ├── circle-loader.gif ├── downloadButton.gif ├── github-loader.gif ├── infinity.gif ├── lightswitch.gif ├── likeVIew.gif ├── loader.gif ├── login.gif ├── octocat-wink.gif ├── pill-loader.gif ├── spinningloader.gif ├── submit-button.gif ├── triLoader.gif └── wifi.gif ├── Info.plist └── SceneDelegate.swift /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/.DS_Store -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: shubham_iosdev 2 | -------------------------------------------------------------------------------- /SwiftUI-Animations.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftUI-Animations.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftUI-Animations.xcodeproj/project.xcworkspace/xcuserdata/shubham.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations.xcodeproj/project.xcworkspace/xcuserdata/shubham.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SwiftUI-Animations.xcodeproj/project.xcworkspace/xcuserdata/shubhamsingh.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations.xcodeproj/project.xcworkspace/xcuserdata/shubhamsingh.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SwiftUI-Animations.xcodeproj/project.xcworkspace/xcuserdata/zero.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations.xcodeproj/project.xcworkspace/xcuserdata/zero.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SwiftUI-Animations.xcodeproj/xcshareddata/xcschemes/SwiftUI-Animations.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /SwiftUI-Animations.xcodeproj/xcuserdata/shubham.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /SwiftUI-Animations.xcodeproj/xcuserdata/shubham.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftUI-Animations.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 518E822C24DAA665002CB679 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /SwiftUI-Animations.xcodeproj/xcuserdata/shubhamsingh.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /SwiftUI-Animations/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 05/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/axis.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "axis.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/axis.imageset/axis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Assets/Assets.xcassets/axis.imageset/axis.png -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/cart-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "cart-fill.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/cart-fill.imageset/cart-fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Assets/Assets.xcassets/cart-fill.imageset/cart-fill.png -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/cart.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "shopping-cart.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/cart.imageset/shopping-cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Assets/Assets.xcassets/cart.imageset/shopping-cart.png -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/face.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "face.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/face.imageset/face.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Assets/Assets.xcassets/face.imageset/face.png -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/medium.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "medium.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/medium.imageset/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Assets/Assets.xcassets/medium.imageset/medium.png -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/shirt-black.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "shirt-black.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/shirt-black.imageset/shirt-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Assets/Assets.xcassets/shirt-black.imageset/shirt-black.png -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/shirt-white.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "shirt-white.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/shirt-white.imageset/shirt-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Assets/Assets.xcassets/shirt-white.imageset/shirt-white.png -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/visa.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "visa-blue-gradient-800x450-removebg-preview.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Assets.xcassets/visa.imageset/visa-blue-gradient-800x450-removebg-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Assets/Assets.xcassets/visa.imageset/visa-blue-gradient-800x450-removebg-preview.png -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Assets/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Code/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Code/Animations/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/3dLoader/Support Shapes/DashedLoaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DashedLoader.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 17/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct DashedLoaderView: View { 12 | 13 | // MARK:- variables 14 | @State var isAnimating: Bool = false 15 | 16 | let animationDuration: TimeInterval = 5 17 | 18 | // MARK:- views 19 | var body: some View { 20 | GeometryReader { geometry in 21 | ZStack { 22 | Color.white 23 | .edgesIgnoringSafeArea(.all) 24 | Circle() 25 | .stroke(style: StrokeStyle(lineWidth: 2, lineCap: .round, miterLimit: 2, dash: [10, 40, 20], dashPhase: 6)) 26 | .foregroundColor(Color.black) 27 | .frame(width: geometry.size.width / 2, height: geometry.size.height / 2) 28 | .rotationEffect(self.isAnimating ? .degrees(360) : .degrees(0)) 29 | .shadow(color: Color.black.opacity(0.2), radius: 10) 30 | .animation(Animation.linear(duration: animationDuration).repeatForever(autoreverses: false)) 31 | Circle() 32 | .frame(width: geometry.size.width * 0.06, height: geometry.size.width * 0.1) 33 | .offset(x: -geometry.size.width / 4) 34 | .foregroundColor(Color.black) 35 | .rotationEffect(self.isAnimating ? .degrees(360) : .degrees(0)) 36 | .shadow(color: Color.black.opacity(0.2), radius: 10) 37 | .animation(Animation.linear(duration: animationDuration * 0.75).repeatForever(autoreverses: false)) 38 | Circle() 39 | .frame(width: geometry.size.width * 0.06, height: geometry.size.width * 0.1) 40 | .offset(x: geometry.size.width / 4) 41 | .foregroundColor(Color.black) 42 | .rotationEffect(self.isAnimating ? .degrees(360) : .degrees(0)) 43 | .shadow(color: Color.black.opacity(0.2), radius: 10) 44 | .animation(Animation.linear(duration: animationDuration * 0.75).repeatForever(autoreverses: false)) 45 | } 46 | }.onAppear() { 47 | self.isAnimating.toggle() 48 | } 49 | } 50 | } 51 | 52 | struct DashedLoader_Previews: PreviewProvider { 53 | static var previews: some View { 54 | DashedLoaderView() 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/3dLoader/Support Shapes/DotsLoaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DotsLoaderView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 17/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct DotsLoaderView: View { 12 | 13 | // MARK:- variables 14 | @State var leftOffset: CGFloat = -75 15 | @State var rightOffset: CGFloat = 75 16 | 17 | let animationDuration: TimeInterval = 1 18 | 19 | // MARK:- views 20 | var body: some View { 21 | ZStack { 22 | Circle() 23 | .fill(Color.white) 24 | .frame(width: 20, height: 20) 25 | .offset(x: leftOffset) 26 | .opacity(0.7) 27 | .animation(Animation.easeInOut(duration: animationDuration)) 28 | Circle() 29 | .fill(Color.white) 30 | .frame(width: 20, height: 20) 31 | .offset(x: leftOffset) 32 | .opacity(0.7) 33 | .animation(Animation.easeInOut(duration: animationDuration).delay(0.2)) 34 | Circle() 35 | .fill(Color.white) 36 | .frame(width: 20, height: 20) 37 | .offset(x: leftOffset) 38 | .opacity(0.7) 39 | .animation(Animation.easeInOut(duration: animationDuration).delay(0.4)) 40 | } 41 | .onAppear() { 42 | swap(&self.leftOffset, &self.rightOffset) 43 | Timer.scheduledTimer(withTimeInterval: animationDuration * 1.5, repeats: true) { _ in 44 | swap(&self.leftOffset, &self.rightOffset) 45 | } 46 | } 47 | } 48 | } 49 | 50 | struct DotsLoaderView_Previews: PreviewProvider { 51 | static var previews: some View { 52 | ZStack { 53 | Color.black 54 | .edgesIgnoringSafeArea(.all) 55 | DotsLoaderView() 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/3dLoader/Support Shapes/FlickeringView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FlickeringView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 17/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct FlickeringView: View { 12 | 13 | // MARK:- variables 14 | let backgroundColor: Color 15 | let initialOffset: CGSize 16 | let initialSize: CGSize 17 | 18 | let finalSize: CGSize 19 | let finalOffset: CGSize 20 | 21 | let fadeDuration: TimeInterval 22 | let animationDuration: TimeInterval = 0.75 23 | 24 | @State var rectangleOpacity: Double = 1 25 | @State var isAnimating: Bool = false 26 | 27 | // MARK:- views 28 | var body: some View { 29 | ZStack { 30 | Rectangle() 31 | .foregroundColor(backgroundColor) 32 | .offset(self.isAnimating ? finalOffset : initialOffset) 33 | .frame(width: self.isAnimating ? self.finalSize.width : initialSize.width, height: self.isAnimating ? finalSize.height : initialSize.height) 34 | .opacity(rectangleOpacity) 35 | }.onAppear() { 36 | Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false) { _ in 37 | withAnimation(Animation.easeOut(duration: 0.25)) { 38 | isAnimating.toggle() 39 | } 40 | withAnimation(Animation.easeOut(duration: animationDuration)) { 41 | self.rectangleOpacity = 0.8 42 | } 43 | withAnimation(Animation.easeOut(duration: animationDuration).delay(animationDuration * 1.5)) { 44 | self.rectangleOpacity = 0.1 45 | } 46 | withAnimation(Animation.easeOut(duration: animationDuration).delay(animationDuration * 1.75)) { 47 | self.rectangleOpacity = 0.7 48 | } 49 | withAnimation(Animation.easeOut(duration: animationDuration).delay(fadeDuration)) { 50 | self.rectangleOpacity = 0 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | struct FlickeringView_Previews: PreviewProvider { 58 | static var previews: some View { 59 | FlickeringView(backgroundColor: Color.black, initialOffset: CGSize(width: 50, height: -200), initialSize: CGSize(width: 200, height: 40), finalSize: CGSize(width: 40, height: 40), finalOffset: CGSize(width: -100, height: -200), fadeDuration: 4) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/3dLoader/Support Shapes/RectangleLoaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RectangleLoaderView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 17/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct RectangleLoaderView: View { 12 | 13 | // MARK:- variables 14 | @State var yOffset: CGFloat = 0 15 | @State var rectangleHeight: CGFloat = 12 16 | 17 | // MARK:- views 18 | var body: some View { 19 | GeometryReader { geometry in 20 | ZStack { 21 | Color.materialBlack 22 | .edgesIgnoringSafeArea(.all) 23 | HStack(alignment: .center, spacing: 8) { 24 | Rectangle() 25 | .foregroundColor(.white) 26 | .frame(width: 12, height: rectangleHeight) 27 | .offset(x: 0, y: yOffset) 28 | .animation(Animation.easeOut.delay(0)) 29 | Rectangle() 30 | .foregroundColor(.white) 31 | .frame(width: 12, height: rectangleHeight) 32 | .offset(x: 0, y: yOffset) 33 | .animation(Animation.easeOut.delay(0.2)) 34 | Rectangle() 35 | .foregroundColor(.white) 36 | .frame(width: 12, height: rectangleHeight) 37 | .offset(x: 0, y: yOffset) 38 | .animation(Animation.easeOut.delay(0.4)) 39 | Rectangle() 40 | .foregroundColor(.white) 41 | .frame(width: 12, height: rectangleHeight) 42 | .offset(x: 0, y: yOffset) 43 | .animation(Animation.easeOut.delay(0.6)) 44 | }.onAppear() { 45 | rectangleHeight = geometry.size.width * 0.25 46 | animateRectangles(in: geometry) 47 | Timer.scheduledTimer(withTimeInterval: 1.5, repeats: true) { _ in 48 | animateRectangles(in: geometry) 49 | } 50 | } 51 | } 52 | } 53 | } 54 | 55 | // MARK:- functions 56 | func animateRectangles(in geometry: GeometryProxy) { 57 | rectangleHeight = geometry.size.width * 0.25 58 | Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in 59 | rectangleHeight = geometry.size.width * 0.1 60 | } 61 | } 62 | } 63 | 64 | struct RectangleLoaderView_Previews: PreviewProvider { 65 | static var previews: some View { 66 | RectangleLoaderView() 67 | .frame(width: 200, height: 200) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/AddView/AddView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 21/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct AddView: View { 12 | 13 | // MARK:- variables 14 | @State var isAnimating: Bool = false 15 | 16 | // MARK:- views 17 | var body: some View { 18 | ZStack { 19 | Color.black 20 | .edgesIgnoringSafeArea(.all) 21 | ZStack { 22 | ExpandingView(expand: $isAnimating, direction: .bottom, symbolName: "note.text") 23 | ExpandingView(expand: $isAnimating, direction: .left, symbolName: "doc") 24 | ExpandingView(expand: $isAnimating, direction: .top, symbolName: "photo") 25 | ExpandingView(expand: $isAnimating, direction: .right, symbolName: "mic.fill") 26 | Image(systemName: "plus") 27 | .font(.system(size: 40, weight: self.isAnimating ? .regular : .semibold, design: .rounded)) 28 | .foregroundColor(self.isAnimating ? Color.white : Color.black) 29 | .rotationEffect(self.isAnimating ? .degrees(45) : .degrees(0)) 30 | .scaleEffect(self.isAnimating ? 3 : 1) 31 | .opacity(self.isAnimating ? 0.5 : 1) 32 | .animation(Animation.spring(response: 0.35, dampingFraction: 0.85, blendDuration: 1)) 33 | .onTapGesture { 34 | self.isAnimating.toggle() 35 | } 36 | }.frame(height: 300) 37 | .padding() 38 | } 39 | } 40 | } 41 | 42 | struct AddButton_Previews: PreviewProvider { 43 | static var previews: some View { 44 | AddView() 45 | } 46 | } 47 | 48 | enum ExpandDirection { 49 | case bottom 50 | case left 51 | case right 52 | case top 53 | 54 | var offsets: (CGFloat, CGFloat) { 55 | switch self { 56 | case .bottom: 57 | return (32, 62) 58 | case .left: 59 | return (-62, 32) 60 | case .top: 61 | return (-32, -62) 62 | case .right: 63 | return (62, -32) 64 | } 65 | } 66 | 67 | var containerOffset: (CGFloat, CGFloat) { 68 | switch self { 69 | case .bottom: 70 | return (18, 18) 71 | case .left: 72 | return (-18, 18) 73 | case .top: 74 | return (-18, -18) 75 | case .right: 76 | return (18, -18) 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/AddView/ExpandingView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExpandingView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 22/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ExpandingView: View { 12 | 13 | // MARK:- variables 14 | @Binding var expand: Bool 15 | var direction: ExpandDirection 16 | var symbolName: String 17 | 18 | var body: some View { 19 | ZStack { 20 | ZStack { 21 | Image(systemName: symbolName) 22 | .font(.system(size: 32, weight: .medium, design: .rounded)) 23 | .foregroundColor(Color.black) 24 | .padding() 25 | .opacity(self.expand ? 0.85 : 0) 26 | .scaleEffect(self.expand ? 1: 0) 27 | .rotationEffect(self.expand ? .degrees(-43) : .degrees(0)) 28 | .animation(Animation.easeOut(duration: 0.15)) 29 | } 30 | .frame(width: 82, height: 82) 31 | .background(Color.white) 32 | .cornerRadius(self.expand ? 41 : 8) 33 | .scaleEffect(self.expand ? 1 : 0.5) 34 | .offset(x: self.expand ? self.direction.offsets.0 : 0, y: self.expand ? self.direction.offsets.1 : 0) 35 | .rotationEffect(self.expand ? .degrees(43) : .degrees(0)) 36 | .animation(Animation.easeOut(duration: 0.25).delay(0.05)) 37 | }.offset(x: self.direction.containerOffset.0, y: self.direction.containerOffset.1) 38 | } 39 | } 40 | 41 | struct ExpandButton_Previews: PreviewProvider { 42 | static var previews: some View { 43 | ExpandingView(expand: .constant(true), direction: .bottom, symbolName: "doc.fill") 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Bank Card/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Code/Animations/Bank Card/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Bank Card/CardBackView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CardBackView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 29/11/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct CardBackView: View { 12 | 13 | // MARK:- variables 14 | let width: CGFloat 15 | let ratioConstant: CGFloat = 1.593 16 | 17 | let card: Card 18 | 19 | // MARK:- views 20 | var body: some View { 21 | ZStack(alignment: Alignment(horizontal: .leading, vertical: .top)) { 22 | LinearGradient(gradient: Gradient(colors: [card.cardPalatte.colorTwo.opacity(0.9), card.cardPalatte.colorOne.opacity(0.9)]), startPoint: .trailing, endPoint: .leading) 23 | VStack { 24 | Rectangle() 25 | .frame(height: 40) 26 | .opacity(0.5) 27 | .foregroundColor(.black) 28 | .overlay( 29 | Rectangle() 30 | .frame(width: 180, height: 38) 31 | .cornerRadius(3) 32 | .foregroundColor(.white) 33 | .overlay( 34 | HStack { 35 | Spacer() 36 | Text(card.security) 37 | .foregroundColor(.black) 38 | .font(.system(size: 16, weight: .semibold, design: .monospaced)) 39 | .opacity(0.75) 40 | }.padding() 41 | ) 42 | .offset(x: 40) 43 | ) 44 | Spacer() 45 | Text(card.cardNumber) 46 | .font(.system(size: width * 0.065, weight: .bold, design: .monospaced)) 47 | .foregroundColor(.white) 48 | .opacity(0.35) 49 | .shadow(color: Color.black, radius: 5) 50 | .rotation3DEffect(.degrees(180), axis: (x: 0.0, y: 1.0, z: 0.0)) 51 | .animation(Animation.default) 52 | .offset(y: -12) 53 | Spacer() 54 | Spacer() 55 | }.padding(.top, 24) 56 | } 57 | .shadow(radius: 5) 58 | .cornerRadius(20) 59 | .frame(width: width, height: width / ratioConstant) 60 | } 61 | } 62 | 63 | struct CardBackView_Previews: PreviewProvider { 64 | static var previews: some View { 65 | CardBackView(width: UIScreen.main.bounds.width * 0.85, card: AppConstants.cards[0]) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Bank Card/CardFrontView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CardFrontView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 29/11/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct CardFrontView: View { 12 | 13 | // MARK:- variables 14 | let width: CGFloat 15 | 16 | let ratioConstant: CGFloat = 1.593 17 | let visaRatio: CGFloat = 2.095 18 | 19 | var card: Card 20 | 21 | @State var rotationAngle: Double = 0 22 | 23 | // MARK:- views 24 | var body: some View { 25 | ZStack { 26 | ZStack(alignment: Alignment(horizontal: .leading, vertical: .top)) { 27 | LinearGradient(gradient: Gradient(colors: [card.cardPalatte.colorOne, card.cardPalatte.colorTwo]), startPoint: .topLeading, endPoint: .bottomTrailing) 28 | .overlay( 29 | ZStack { 30 | Circle() 31 | .frame(width: 400) 32 | .offset(x: 180, y: -10) 33 | .opacity(0.05) 34 | .rotationEffect(.degrees(-40)) 35 | CardPatternOneView() 36 | .opacity(0.075) 37 | .offset(x: -width * 0.3) 38 | .scaleEffect(1.4) 39 | .rotationEffect(.degrees(-27.5)) 40 | } 41 | ) 42 | .animation(Animation.easeOut(duration: 0.3)) 43 | VStack(alignment: .leading) { 44 | HStack { 45 | Text("\(card.cardType.rawValue) Card") 46 | .font(.system(size: 18, weight: .medium, design: .default)) 47 | .foregroundColor(Color.white) 48 | Spacer() 49 | ZStack { 50 | Image("axis") 51 | .resizable() 52 | }.frame(width: 34, height: 34) 53 | 54 | } 55 | Spacer() 56 | HStack { 57 | Spacer() 58 | Text(card.cardNumber) 59 | .font(.system(size: width * 0.065, weight: .bold, design: .monospaced)) 60 | .foregroundColor(Color.white) 61 | .offset(y: 15) 62 | .frame(minHeight: 29) 63 | .animation(Animation.default) 64 | Spacer() 65 | } 66 | Spacer() 67 | VStack(alignment: .leading) { 68 | Text("VALID THRU") 69 | .font(.system(size: 09, weight: .semibold, design: .monospaced)) 70 | .foregroundColor(Color.white.opacity(0.6)) 71 | Text(card.validity) 72 | .font(.system(size: 15, weight: .semibold, design: .monospaced)) 73 | .foregroundColor(Color.white) 74 | }.offset(y: 8) 75 | HStack { 76 | Text(card.cardHolderName) 77 | .font(.system(size: 18, weight: .semibold, design: .rounded)) 78 | .textCase(.uppercase) 79 | .foregroundColor(Color.white) 80 | Spacer() 81 | Image("visa") 82 | .resizable() 83 | .frame(width: 72, height: 72 / visaRatio) 84 | } 85 | }.padding() 86 | .shadow(radius: 5) 87 | } 88 | } 89 | .cornerRadius(20) 90 | .frame(width: width, height: width / ratioConstant) 91 | .rotation3DEffect( 92 | .degrees(rotationAngle), 93 | axis: (x: 1.0, y: 0, z: 0.0) 94 | ) 95 | } 96 | } 97 | 98 | struct CardFrontView_Previews: PreviewProvider { 99 | static var previews: some View { 100 | ZStack { 101 | Color.black 102 | .edgesIgnoringSafeArea(.all) 103 | CardFrontView(width: 370, card: AppConstants.cards[0]) 104 | } } 105 | } 106 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Bank Card/Model/AppConstants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DummyData.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 29/11/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct AppConstants { 12 | static var cards = [ 13 | Card(id: 0, cardNumber: "4231 5161 3694 2135", cardHolderName: "Shubham Singh", security: "137", balance: "32134.35", validity: "05/24", cardPalatte: palattes[0], cardType: .debit), 14 | Card(id: 2, cardNumber: "3512 6909 1223 1960", cardHolderName: "Shubham Singh", security: "819", balance: "7424.12", validity: "12/20", cardPalatte: palattes[1], cardType: .debit), 15 | Card(id: 3, cardNumber: "8656 1457 5421 8900", cardHolderName: "Shubham Singh", security: "591", balance: "51236.69", validity: "05/22", cardPalatte: palattes[2], cardType: .credit), 16 | ] 17 | 18 | static var palattes: [CardPalatte] = [ 19 | CardPalatte(colorOne: Color(hex: "fbc2eb"), colorTwo: Color(hex: "a6c1ee")), 20 | CardPalatte(colorOne: Color(hex: "43cea2"), colorTwo: Color(hex: "185a9d")), 21 | CardPalatte(colorOne: Color(hex: "fa709a"), colorTwo: Color(hex: "fee140")) 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Bank Card/Model/Card.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Card.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 29/11/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Card: Identifiable, Hashable { 12 | enum CardType: String { 13 | case credit = "Credit" 14 | case debit = "Debit" 15 | } 16 | 17 | let id: Int 18 | let cardNumber: String 19 | let cardHolderName: String 20 | let security: String 21 | 22 | let balance: String 23 | let validity: String 24 | var cardPalatte: CardPalatte 25 | let cardType: CardType 26 | 27 | mutating func changePalatte(palatte: CardPalatte) { 28 | self.cardPalatte = palatte 29 | } 30 | } 31 | 32 | 33 | struct CardPalatte: Hashable { 34 | let colorOne: Color 35 | let colorTwo: Color 36 | } 37 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Bank Card/Support Shapes/CardPatternOneView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CardPatternOneView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 29/11/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct CardPatternOneView: Shape { 12 | 13 | func path(in rect: CGRect) -> Path { 14 | let cX: CGFloat = rect.midX 15 | let cY: CGFloat = rect.midY 16 | 17 | var path = Path() 18 | path.move(to: CGPoint(x: cX - 140, y: cY)) 19 | 20 | path.addCurve(to: CGPoint(x: cX + 160 , y: cY + 150), control1: CGPoint(x: cX + 10, y: cY - 150), control2: CGPoint(x: cX + 150 , y: cY)) 21 | path.closeSubpath() 22 | return path 23 | } 24 | } 25 | 26 | struct CardPatternOneView_Previews: PreviewProvider { 27 | static var previews: some View { 28 | CardPatternOneView() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Bank Card/Support Shapes/SnapCarousel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapCarousel.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by T. Abbas Khan 6 | // Modified by Shubham Singh on 29/11/20. 7 | // Copyright © 2020 Shubham Singh. All rights reserved. 8 | // 9 | 10 | import SwiftUI 11 | 12 | public class UIStateModel: ObservableObject { 13 | @Published var activeCard: Int = 0 14 | @Published var screenDrag: Float = 0.0 15 | } 16 | 17 | struct Canvas : View { 18 | let content: Content 19 | @inlinable init(@ViewBuilder _ content: () -> Content) { 20 | self.content = content() 21 | } 22 | 23 | var body: some View { 24 | content 25 | .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top) 26 | .background( 27 | Color.black 28 | .edgesIgnoringSafeArea(.all) 29 | ) 30 | } 31 | } 32 | 33 | struct Carousel : View { 34 | // MARK:- variables 35 | let items: Items 36 | let numberOfItems: CGFloat 37 | let spacing: CGFloat 38 | let widthOfHiddenCards: CGFloat 39 | let totalSpacing: CGFloat 40 | let cardWidth: CGFloat 41 | 42 | @GestureState var isDetectingLongPress = false 43 | @EnvironmentObject var UIState: UIStateModel 44 | 45 | // MARK:- initializers 46 | @inlinable public init( 47 | numberOfItems: CGFloat, 48 | spacing: CGFloat, 49 | widthOfHiddenCards: CGFloat, 50 | @ViewBuilder _ items: () -> Items) { 51 | 52 | self.items = items() 53 | self.numberOfItems = numberOfItems 54 | self.spacing = spacing 55 | self.widthOfHiddenCards = widthOfHiddenCards 56 | self.totalSpacing = (numberOfItems - 1) * spacing 57 | self.cardWidth = UIScreen.main.bounds.width - (widthOfHiddenCards*2) - (spacing*2) //279 58 | 59 | } 60 | 61 | // MARK:- views 62 | var body: some View { 63 | 64 | let totalCanvasWidth: CGFloat = (cardWidth * numberOfItems) + totalSpacing 65 | let xOffsetToShift = (totalCanvasWidth - UIScreen.main.bounds.width) / 2 66 | let leftPadding = widthOfHiddenCards + spacing 67 | let totalMovement = cardWidth + spacing 68 | 69 | let activeOffset = xOffsetToShift + (leftPadding) - (totalMovement * CGFloat(UIState.activeCard)) 70 | let nextOffset = xOffsetToShift + (leftPadding) - (totalMovement * CGFloat(UIState.activeCard) + 1) 71 | 72 | var calcOffset = Float(activeOffset) 73 | if (calcOffset != Float(nextOffset)) { 74 | calcOffset = Float(activeOffset) + UIState.screenDrag 75 | } 76 | 77 | return HStack(alignment: .center, spacing: spacing) { 78 | items 79 | } 80 | .offset(x: CGFloat(calcOffset), y: 0) 81 | .gesture(DragGesture().updating($isDetectingLongPress) { currentState, gestureState, transaction in 82 | self.UIState.screenDrag = Float(currentState.translation.width) 83 | 84 | }.onEnded { value in 85 | self.UIState.screenDrag = 0 86 | if (value.translation.width < -50) { 87 | self.UIState.activeCard = self.UIState.activeCard + 1 88 | let impactMed = UIImpactFeedbackGenerator(style: .medium) 89 | impactMed.impactOccurred() 90 | } 91 | 92 | if (value.translation.width > 50) { 93 | self.UIState.activeCard = self.UIState.activeCard - 1 94 | let impactMed = UIImpactFeedbackGenerator(style: .medium) 95 | impactMed.impactOccurred() 96 | } 97 | }) 98 | } 99 | } 100 | 101 | struct Item: View { 102 | let cardWidth: CGFloat 103 | let cardHeight: CGFloat 104 | 105 | var _id: Int 106 | var content: Content 107 | @Binding var selectedIndex: Int 108 | 109 | @inlinable public init( 110 | _id: Int, 111 | spacing: CGFloat, 112 | widthOfHiddenCards: CGFloat, 113 | cardWidth: CGFloat, 114 | selectedIndex: Binding, 115 | @ViewBuilder _ content: () -> Content 116 | ) { 117 | self.content = content() 118 | self.cardWidth = UIScreen.main.bounds.width - (widthOfHiddenCards*2) - (spacing*2) //279 119 | self.cardHeight = cardWidth / 1.593 120 | self._id = _id 121 | self._selectedIndex = selectedIndex 122 | } 123 | 124 | var body: some View { 125 | content 126 | .frame(width: cardWidth, height: cardHeight, alignment: .top) 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/BookLoader/BookPagesView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BookPagesView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 17/11/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct BookPagesView: View { 12 | 13 | // MARK:- variables 14 | @State var isAppeared: Bool = false 15 | 16 | @State var leftEndDegree: Angle = .zero 17 | @State var leftYOffset: CGFloat = 0 18 | 19 | @State var rightEndDegree: Angle = .zero 20 | @State var rightYOffset: CGFloat = -20 21 | 22 | @State var pagesDegree: Angle = .zero 23 | @Binding var animationStarted: Bool 24 | 25 | let bookCoverWidth: CGFloat = 100 26 | let barsOffset: CGFloat = -78 27 | let animationDuration: TimeInterval 28 | 29 | // MARK:- views 30 | var body: some View { 31 | ZStack { 32 | Capsule() 33 | .foregroundColor(.white) 34 | .frame(width: bookCoverWidth, height: 8) 35 | .offset(x: barsOffset, y: leftYOffset) 36 | .rotationEffect(leftEndDegree) 37 | .animation(Animation.easeOut(duration: animationDuration)) 38 | 39 | Capsule() 40 | .foregroundColor(.white) 41 | .frame(width: bookCoverWidth, height: 8) 42 | .offset(x: barsOffset, y: rightYOffset) 43 | .rotationEffect(rightEndDegree) 44 | .animation(Animation.easeOut(duration: animationDuration)) 45 | 46 | // // Bars 47 | ForEach(0..<13) { num in 48 | Capsule() 49 | .foregroundColor(.white) 50 | .frame(width: bookCoverWidth, height: 8) 51 | .offset(x: barsOffset) 52 | .rotationEffect(pagesDegree) 53 | .animation(Animation.easeOut(duration: animationDuration).delay((animationDuration * 0.21) * Double(num))) 54 | } 55 | }.onAppear() { 56 | Timer.scheduledTimer(withTimeInterval: 0.3, repeats: true) { animationTimer in 57 | if (animationStarted) { 58 | animatePages() 59 | Timer.scheduledTimer(withTimeInterval: animationDuration * 10, repeats: true) { _ in 60 | animatePages() 61 | } 62 | animationTimer.invalidate() 63 | } 64 | } 65 | } 66 | } 67 | 68 | // MARK:- functions 69 | func animatePages() { 70 | self.isAppeared.toggle() 71 | self.rightEndDegree = .degrees(180) 72 | self.pagesDegree = .degrees(180) 73 | self.rightYOffset = 0 74 | 75 | 76 | Timer.scheduledTimer(withTimeInterval: animationDuration * 2.7, repeats: false) { _ in 77 | self.leftYOffset = 20 78 | self.leftEndDegree = .degrees(180) 79 | } 80 | 81 | Timer.scheduledTimer(withTimeInterval: animationDuration * 5, repeats: false) { _ in 82 | self.leftYOffset = 0 83 | self.leftEndDegree = .zero 84 | } 85 | 86 | Timer.scheduledTimer(withTimeInterval: animationDuration * 5.25, repeats: false) { _ in 87 | self.pagesDegree = .degrees(0) 88 | } 89 | 90 | Timer.scheduledTimer(withTimeInterval: animationDuration * 7, repeats: false) { _ in 91 | self.rightEndDegree = .degrees(0) 92 | self.rightYOffset = -20 93 | } 94 | } 95 | 96 | } 97 | 98 | struct BookPagesView_Previews: PreviewProvider { 99 | static var previews: some View { 100 | ZStack { 101 | Color.black 102 | .edgesIgnoringSafeArea(.all) 103 | BookPagesView(animationStarted: .constant(true), animationDuration: 0.5) 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/BookLoader/Support Shapes/BookHold.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BookHold.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 15/11/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct BookHoldView: Shape { 12 | 13 | // MARK:- functions 14 | func path(in rect: CGRect) -> Path { 15 | 16 | let cX: CGFloat = rect.midX - 28 17 | let cY: CGFloat = rect.midY 18 | 19 | var path = Path() 20 | 21 | path.move(to: CGPoint(x: cX, y: cY)) 22 | path.addLine(to: CGPoint(x: cX, y: cY + 12)) 23 | path.addLine(to: CGPoint(x: cX + 56, y: cY + 12)) 24 | path.addLine(to: CGPoint(x: cX + 56, y: cY)) 25 | return path 26 | } 27 | } 28 | 29 | struct BookHoldView_Previews: PreviewProvider { 30 | static var previews: some View { 31 | ZStack{ 32 | Color.black 33 | .edgesIgnoringSafeArea(.all) 34 | BookHoldView() 35 | .stroke(style: StrokeStyle(lineWidth: 8, lineCap: .round, lineJoin: .miter)) 36 | .foregroundColor(.white) 37 | Capsule() 38 | .frame(width: 5) 39 | .foregroundColor(.white) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Cart/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Code/Animations/Cart/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Cart/AddCartView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 05/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | enum CartState { 12 | case ready 13 | case center 14 | case moveToEnd 15 | case origin 16 | 17 | var offset: CGFloat { 18 | switch self { 19 | case .origin, .ready: 20 | return -(UIScreen.main.bounds.width / 2 - 80) 21 | case .center: 22 | return -4 23 | case .moveToEnd: 24 | return (UIScreen.main.bounds.width / 2 + 42) 25 | } 26 | } 27 | 28 | var image: String { 29 | switch self { 30 | case .origin, .ready: 31 | return "cart" 32 | default: 33 | return "cart-fill" 34 | } 35 | } 36 | 37 | var animation: Animation { 38 | switch self { 39 | case .origin: 40 | return Animation.linear(duration: 0) 41 | default: 42 | return Animation.easeIn(duration: 0.55).delay(0.25) 43 | } 44 | } 45 | } 46 | 47 | struct AddCartView: View { 48 | // MARK:- variables 49 | @State var isAnimating: Bool = false 50 | @State var addItem: Bool = false 51 | @State var cartAnimation: CartState 52 | @State var bounceAnimation: Bool = false 53 | 54 | var backgroundColor: Color 55 | var color: Color 56 | 57 | // MARK:- views 58 | var body: some View { 59 | ZStack { 60 | self.backgroundColor 61 | .edgesIgnoringSafeArea(.all) 62 | ZStack { 63 | self.color 64 | CartView(itemAdded: $addItem, animation: self.cartAnimation.animation) 65 | .offset(x: self.cartAnimation.offset) 66 | .scaleEffect(self.isAnimating ? 1.1 : 1) 67 | .animation(Animation.linear(duration: 0.5).delay(0.25)) 68 | 69 | 70 | Text("Add to cart") 71 | .foregroundColor(self.backgroundColor) 72 | .font(.system(size: 24, weight: .bold, design: .rounded)) 73 | .opacity(self.isAnimating ? 0 : 1) 74 | .animation(Animation.spring()) 75 | 76 | }.frame(height: 72) 77 | .cornerRadius(12) 78 | .padding() 79 | .padding([.leading, .trailing], 24) 80 | .shadow(radius: 10) 81 | .scaleEffect(x: self.bounceAnimation ? 0.98 : 1, y: 1, anchor: .center) 82 | .animation( 83 | Animation.spring(response: 0.25, dampingFraction: 0.85, blendDuration: 1) 84 | .delay(0.15) 85 | ) 86 | 87 | .onTapGesture { 88 | self.cartAnimation = .center 89 | self.isAnimating.toggle() 90 | self.bounceAnimation.toggle() 91 | 92 | Timer.scheduledTimer(withTimeInterval: 0.7, repeats: false) { (Timer) in 93 | self.bounceAnimation.toggle() 94 | } 95 | 96 | Timer.scheduledTimer(withTimeInterval: 1.4, repeats: false) { (Timer) in 97 | self.addItem.toggle() 98 | } 99 | Timer.scheduledTimer(withTimeInterval: 1.6, repeats: false) { (Timer) in 100 | self.cartAnimation = .moveToEnd 101 | } 102 | Timer.scheduledTimer(withTimeInterval: 2.5, repeats: false) { (Timer) in 103 | self.isAnimating.toggle() 104 | self.addItem.toggle() 105 | self.cartAnimation = .origin 106 | } 107 | } 108 | Triangle() 109 | .fill(Color.white) 110 | .frame(width: 120, height: self.bounceAnimation ? 22 : 0) 111 | .animation( 112 | Animation.spring(response: 0.25, dampingFraction: 0.85, blendDuration: 1) 113 | .delay(0.35) 114 | ) 115 | .offset(y: -36) 116 | if (self.isAnimating) { 117 | ShirtView(itemAdded: $isAnimating) 118 | .frame(width: 22, height: 22) 119 | } 120 | } 121 | } 122 | } 123 | 124 | struct ContentView_Previews: PreviewProvider { 125 | static var previews: some View { 126 | Group { 127 | AddCartView(cartAnimation: .ready, backgroundColor: Color.black, color: Color.white) 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Cart/CartView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CartView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 05/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct CartView: View { 12 | 13 | @Binding var itemAdded: Bool 14 | 15 | var animationDuration: Double = 0.55 16 | var animationDelay: Double = 0.25 17 | var animation: Animation 18 | 19 | var body: some View { 20 | ZStack { 21 | Image(self.itemAdded ? "cart-fill" : "cart") 22 | .resizable() 23 | .frame(width: 42, height: 42) 24 | .rotationEffect(self.itemAdded ? .degrees(-22) : .degrees(0)) 25 | .animation(self.animation) 26 | Tick(scaleFactor: 0.125) 27 | .trim(from: 0, to: self.itemAdded ? 1 : 0) 28 | .stroke(style: StrokeStyle(lineWidth: 2.4, lineCap: .round)) 29 | .foregroundColor(Color.red) 30 | .frame(width: 42, height: 42) 31 | .animation(.easeOut(duration: 0.35)) 32 | .rotationEffect(self.itemAdded ? .degrees(-22) : .degrees(0)) 33 | .animation(Animation.easeIn(duration: self.animationDuration).delay(self.animationDelay)) 34 | }.onTapGesture { 35 | self.itemAdded.toggle() 36 | } 37 | } 38 | } 39 | 40 | 41 | 42 | struct CartView_Previews: PreviewProvider { 43 | static var previews: some View { 44 | CartView(itemAdded: .constant(true), animation: Animation.easeIn(duration: 0.55).delay(0.25)) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Cart/ShirtView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShirtView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 05/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | enum ShirtState { 12 | case origin 13 | case top 14 | case end 15 | 16 | var scale: CGFloat { 17 | switch self { 18 | case .origin: 19 | return 0.2 20 | case .top: 21 | return 1 22 | case .end: 23 | return 0.5 24 | } 25 | } 26 | 27 | var opacity: Double { 28 | switch self { 29 | case .end: 30 | return 0 31 | default: 32 | return 1 33 | } 34 | } 35 | } 36 | 37 | struct ShirtView: View { 38 | @Binding var itemAdded: Bool 39 | 40 | @State var iconOffset: CGFloat = -12 41 | @State var changeShirtColor: Bool = false 42 | @State var shirtState: ShirtState = .origin 43 | 44 | 45 | var body: some View { 46 | ZStack { 47 | Color.clear 48 | .edgesIgnoringSafeArea(.all) 49 | Image(self.changeShirtColor ? "shirt-black" : "shirt-white") 50 | .resizable() 51 | .frame(width: 27, height: 27) 52 | .scaleEffect(self.itemAdded ? self.shirtState.scale : 0.5) 53 | .animation(Animation.spring().speed(0.6)) 54 | .offset(y: self.iconOffset) 55 | .animation(Animation.easeOut(duration: 0.35)) 56 | .opacity(self.shirtState.opacity) 57 | .animation(Animation.default.delay(0.15)) 58 | .onAppear() { 59 | Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { checkingTimer in 60 | if (self.itemAdded) { 61 | checkingTimer.invalidate() 62 | Timer.scheduledTimer(withTimeInterval: 0.35, repeats: false) { (Timer) in 63 | self.iconOffset = -120 64 | self.shirtState = .top 65 | } 66 | Timer.scheduledTimer(withTimeInterval: 1.25, repeats: false) { (Timer) in 67 | self.changeShirtColor.toggle() 68 | self.shirtState = .end 69 | } 70 | Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (Timer) in 71 | self.iconOffset = -6 72 | } 73 | } 74 | } 75 | } 76 | } 77 | } 78 | } 79 | 80 | struct ShirtView_Previews: PreviewProvider { 81 | static var previews: some View { 82 | ZStack { 83 | Color.gray 84 | .edgesIgnoringSafeArea(.all) 85 | ShirtView(itemAdded: .constant(false)) 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Cart/SupportShapes/Tick.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Tick.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 06/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Tick: Shape { 12 | let scaleFactor: CGFloat 13 | 14 | func path(in rect: CGRect) -> Path { 15 | let cX = rect.midX + 4 16 | let cY = rect.midY - 3 17 | 18 | var path = Path() 19 | path.move(to: CGPoint(x: rect.midX, y: rect.minY)) 20 | path.move(to: CGPoint(x: cX - (42 * scaleFactor), y: cY - (4 * scaleFactor))) 21 | path.addLine(to: CGPoint(x: cX - (scaleFactor * 18), y: cY + (scaleFactor * 28))) 22 | path.addLine(to: CGPoint(x: cX + (scaleFactor * 40), y: cY - (scaleFactor * 36))) 23 | return path 24 | } 25 | } 26 | 27 | struct Tick_Previews: PreviewProvider { 28 | static var previews: some View { 29 | Tick(scaleFactor: 1) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Cart/SupportShapes/Triangle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Triangle.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 06/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Triangle: Shape { 12 | func path(in rect: CGRect) -> Path { 13 | var path = Path() 14 | 15 | path.move(to: CGPoint(x: rect.midX, y: rect.minY)) 16 | path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY * 0.85)) 17 | path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY * 0.85)) 18 | path.addLine(to: CGPoint(x: rect.midX, y: rect.minY)) 19 | return path 20 | } 21 | } 22 | 23 | struct Triangle_Previews: PreviewProvider { 24 | static var previews: some View { 25 | Triangle() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/ChatBar/AttachmentButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AttachmentButton.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 08/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct AttachmentButton: View { 12 | @Binding var needsRotation: Bool 13 | @State var buttonPressAnimation: Bool = false 14 | 15 | 16 | var iconName: String 17 | var iconSize: CGFloat = 20 18 | var action: () -> Void 19 | 20 | var body: some View { 21 | Button(action: action) { 22 | Image(systemName: self.iconName) 23 | .font(.system(size: iconSize, weight: .medium, design: .rounded)) 24 | .foregroundColor(Color.white) 25 | .padding() 26 | .frame(width: 52, height: 52) 27 | .background(Color.buttonBackground.opacity(0.5)) 28 | .cornerRadius(32) 29 | .rotationEffect(self.needsRotation ? .degrees(137) : .degrees(0)) 30 | .animation(Animation.easeIn(duration: 0.25).speed(1.5)) 31 | .overlay( 32 | Circle() 33 | .opacity(self.buttonPressAnimation ? 0.1: 0) 34 | .scaleEffect(self.buttonPressAnimation ? 0.95 : 0.5) 35 | .animation(self.buttonPressAnimation ? .easeIn(duration: 0.25) : .easeIn(duration: 0)) 36 | ) 37 | } 38 | // TODO:- Find a way to the tap gesture to the Button closure 39 | // .onTapGesture { 40 | // self.buttonPressAnimation.toggle() 41 | // Timer.scheduledTimer(withTimeInterval: 0.3, repeats: false) { (Timer) in 42 | // self.buttonPressAnimation.toggle() 43 | // } 44 | // } 45 | } 46 | } 47 | 48 | struct AttachmentButton_Previews: PreviewProvider { 49 | static var previews: some View { 50 | AttachmentButton(needsRotation: .constant(true), iconName: "plus", action: {}) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/ChatBar/ChatBarView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ChatBarView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 08/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ChatBarView: View { 12 | 13 | // MARK:- variables 14 | @State var addAttachment: Bool = false 15 | @State var rotateBar: Bool = false 16 | @Binding var message: String 17 | 18 | var chatBarHeight: CGFloat = 86 19 | 20 | // MARK:- views 21 | var body: some View { 22 | ZStack { 23 | Color.black 24 | .edgesIgnoringSafeArea(.all) 25 | ZStack { 26 | Color.chatBackground 27 | HStack { 28 | AttachmentButton(needsRotation: $rotateBar, iconName: "plus", iconSize: 24, action: { 29 | self.rotateBar.toggle() 30 | self.addAttachment.toggle() 31 | Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { (Timer) in 32 | self.addAttachment.toggle() 33 | } 34 | }) 35 | Spacer() 36 | ZStack { 37 | ZStack { 38 | HStack(alignment: .center, spacing: 20) { 39 | AttachmentButton(needsRotation: .constant(false), iconName: "camera", action: {}) 40 | AttachmentButton(needsRotation: .constant(false), iconName: "video.fill", action: {}) 41 | AttachmentButton(needsRotation: .constant(false), iconName: "rectangle.stack.person.crop", action: {}) 42 | } 43 | .rotationEffect(!self.rotateBar ? .degrees(90) : .degrees(0), anchor: .zero) 44 | .offset(y: !self.rotateBar ? 72 : 0) 45 | .animation(Animation.spring()) 46 | } 47 | ZStack { 48 | TextField("Message", text: self.$message) 49 | .font(.system(size: 18, weight: .semibold, design: .rounded)) 50 | .disableAutocorrection(true) 51 | .foregroundColor(Color.white) 52 | .accentColor(Color.white) 53 | .frame(height: 50) 54 | .padding(.leading, 36) 55 | .background( 56 | Color.buttonBackground.opacity(0.5) 57 | .cornerRadius(24) 58 | .padding(.leading) 59 | ) 60 | } 61 | .rotationEffect(self.rotateBar ? .degrees(-120) : .degrees(0), anchor: .zero) 62 | .animation(Animation.spring()) 63 | } 64 | } .padding() 65 | .padding([.leading, .trailing], 8) 66 | } 67 | .frame(height: self.chatBarHeight) 68 | .cornerRadius(self.chatBarHeight / 2) 69 | .padding() 70 | .padding([.leading, .trailing], 24) 71 | .shadow(radius: 10) 72 | .rotationEffect(self.getBarRotationDegree(), anchor: .leading) 73 | .animation( 74 | Animation.interpolatingSpring(mass: 2, stiffness: 14, damping: 10, initialVelocity: 5) 75 | .delay(0.1) 76 | ) 77 | } 78 | } 79 | 80 | func getBarRotationDegree() -> Angle { 81 | if (self.rotateBar && self.addAttachment) { 82 | return .degrees(-3) 83 | } else if (self.addAttachment) { 84 | return .degrees(3) 85 | } else { 86 | return .degrees(0) 87 | } 88 | } 89 | } 90 | 91 | struct ChatBarView_Previews: PreviewProvider { 92 | static var previews: some View { 93 | ChatBarView(message: .constant("")) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/CircleLoader/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Code/Animations/CircleLoader/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/CircleLoader/CircleLoader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircleLoader.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 05/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct CircleLoader: View { 12 | 13 | // MARK:- variables 14 | let circleTrackGradient = LinearGradient(gradient: .init(colors: [Color.circleTrackStart, Color.circleTrackEnd]), startPoint: .leading, endPoint: .bottomLeading) 15 | let circleRoundGradient = LinearGradient(gradient: .init(colors: [Color.circleRoundStart, Color.circleRoundEnd]), startPoint: .topLeading, endPoint: .trailing) 16 | 17 | let trackerRotation: Double = 2 18 | let animationDuration: Double = 0.75 19 | 20 | @State var isAnimating: Bool = false 21 | @State var circleStart: CGFloat = 0.17 22 | @State var circleEnd: CGFloat = 0.325 23 | 24 | @State var rotationDegree: Angle = Angle.degrees(0) 25 | 26 | // MARK:- views 27 | var body: some View { 28 | ZStack { 29 | Color.white 30 | .edgesIgnoringSafeArea(.all) 31 | 32 | ZStack { 33 | Circle() 34 | .stroke(style: StrokeStyle(lineWidth: 20)) 35 | .fill(circleTrackGradient) 36 | Circle() 37 | .trim(from: circleStart, to: circleEnd) 38 | .stroke(style: StrokeStyle(lineWidth: 15, lineCap: .round)) 39 | .fill(circleRoundGradient) 40 | .rotationEffect(self.rotationDegree) 41 | }.frame(width: 200, height: 200) 42 | .onAppear() { 43 | self.animateLoader() 44 | Timer.scheduledTimer(withTimeInterval: self.trackerRotation * self.animationDuration + (self.animationDuration), repeats: true) { (mainTimer) in 45 | self.animateLoader() 46 | } 47 | } 48 | } 49 | } 50 | 51 | // MARK:- functions 52 | func getRotationAngle() -> Angle { 53 | return .degrees(360 * self.trackerRotation) + .degrees(120) 54 | } 55 | 56 | func animateLoader() { 57 | withAnimation(Animation.spring(response: animationDuration * 2 )) { 58 | self.rotationDegree = .degrees(-57.5) 59 | } 60 | 61 | Timer.scheduledTimer(withTimeInterval: animationDuration, repeats: false) { _ in 62 | withAnimation(Animation.easeInOut(duration: self.trackerRotation * self.animationDuration)) { 63 | self.rotationDegree += self.getRotationAngle() 64 | } 65 | } 66 | 67 | Timer.scheduledTimer(withTimeInterval: animationDuration * 1.25, repeats: false) { _ in 68 | withAnimation(Animation.easeOut(duration: (self.trackerRotation * self.animationDuration) / 2.25 )) { 69 | self.circleEnd = 0.925 70 | } 71 | } 72 | 73 | Timer.scheduledTimer(withTimeInterval: trackerRotation * animationDuration, repeats: false) { _ in 74 | self.rotationDegree = .degrees(47.5) 75 | withAnimation(Animation.easeOut(duration: self.animationDuration)) { 76 | self.circleEnd = 0.325 77 | } 78 | } 79 | } 80 | } 81 | 82 | struct CircleLoader_Previews: PreviewProvider { 83 | static var previews: some View { 84 | CircleLoader() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/DownloadButton/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Code/Animations/DownloadButton/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/DownloadButton/DownloadButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StateView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 08/04/21. 6 | // Copyright © 2021 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct DownloadButton: View { 12 | 13 | // MARK:- variables 14 | @StateObject var downloader = Downloader() 15 | 16 | @State var downloadYOffset: CGFloat = 0 17 | @State var downloadingYOffset: CGFloat = -ButtonDimension.height 18 | @State var downloadedOffset: CGFloat = -(ButtonDimension.height * 2) 19 | 20 | @State var downloadProgress: CGFloat = 0 21 | 22 | // MARK:- views 23 | var body: some View { 24 | ZStack(alignment: Alignment(horizontal: .center, vertical: .center)) { 25 | DownloadStateView(state: .downloaded, isLight: true, progress: .constant(0)) 26 | .environmentObject(downloader) 27 | .offset(y: downloadedOffset) 28 | DownloadStateView(state: .downloading, needsProgress: true, isLight: true, progress: $downloadProgress) 29 | .environmentObject(downloader) 30 | .offset(y: downloadingYOffset) 31 | DownloadStateView(state: .notInitiated, progress: .constant(0)) 32 | .environmentObject(downloader) 33 | .offset(y: downloadYOffset) 34 | 35 | ZStack { 36 | getSupportingView() 37 | .scaleEffect(0.9) 38 | } 39 | .offset(x: -ButtonDimension.width / 3.5 + 13) 40 | 41 | }.mask( 42 | RoundedRectangle(cornerRadius: ButtonDimension.cornerRadius) 43 | .frame(width: ButtonDimension.width, height: ButtonDimension.height) 44 | ) 45 | .onTapGesture { 46 | startDownloading() 47 | } 48 | .frame(width: ButtonDimension.width, height: ButtonDimension.height) 49 | .shadow(color: Color.background.opacity(0.4), radius: 10) 50 | } 51 | 52 | // MARK:- functions 53 | func startDownloading() { 54 | self.downloader.currentState = .downloading 55 | withAnimation(Animation.easeOut(duration: ButtonDimension.animationDuration)) { 56 | self.downloadedOffset = -ButtonDimension.height + 10 57 | self.downloadYOffset = ButtonDimension.height 58 | self.downloadingYOffset = 0 59 | } 60 | 61 | Timer.scheduledTimer(withTimeInterval: ButtonDimension.animationDuration, repeats: false) { _ in 62 | incrementProgress() 63 | } 64 | } 65 | 66 | func incrementProgress() { 67 | Timer.scheduledTimer(withTimeInterval: 0.15, repeats: true) { progressTimer in 68 | if (downloadProgress > 1) { 69 | downloadProgress = 1 70 | progressTimer.invalidate() 71 | 72 | itemDownloaded() 73 | } 74 | /// hardcoding progress for now 75 | downloadProgress += 0.045 76 | } 77 | } 78 | 79 | func itemDownloaded() { 80 | self.downloader.currentState = .downloaded 81 | withAnimation(Animation.easeOut(duration: ButtonDimension.animationDuration)) { 82 | self.downloadingYOffset = ButtonDimension.height 83 | self.downloadedOffset = 0 84 | } 85 | 86 | Timer.scheduledTimer(withTimeInterval: 2.5, repeats: false) { _ in 87 | reset() 88 | } 89 | } 90 | 91 | func reset() { 92 | self.downloadYOffset = -ButtonDimension.height 93 | self.downloadProgress = 0 94 | self.downloader.currentState = .notInitiated 95 | withAnimation(Animation.easeOut(duration: ButtonDimension.animationDuration)) { 96 | self.downloadYOffset = 0 97 | } 98 | 99 | Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in 100 | self.downloadingYOffset = -ButtonDimension.height 101 | self.downloadedOffset = -(ButtonDimension.height * 2) 102 | } 103 | } 104 | 105 | @ViewBuilder func getSupportingView() -> some View { 106 | if (downloader.currentState == .notInitiated) { 107 | DownloadingIndicatorView(needsAnimation: false) 108 | .foregroundColor(.background) 109 | } else if (downloader.currentState == .downloading) { 110 | DownloadingIndicatorView() 111 | .offset(x: -16) 112 | } else { 113 | CircleTickShape() 114 | .trim(from: 0, to: self.downloadProgress == 1 ? 0 : 1) 115 | .stroke(style: StrokeStyle(lineWidth: 5.5, lineCap: .round, lineJoin: .round)) 116 | .foregroundColor(.white) 117 | .scaleEffect(0.6) 118 | .opacity(self.downloader.currentState == .downloaded ? 1 : 0) 119 | .offset(x: 8) 120 | .animation(Animation.easeInOut(duration: ButtonDimension.animationDuration * 2).delay(self.downloader.currentState == .downloaded ? ButtonDimension.animationDuration / 4 : 0)) 121 | .frame(width: 44, height: 44) 122 | } 123 | } 124 | } 125 | 126 | struct StateView_Previews: PreviewProvider { 127 | static var previews: some View { 128 | ZStack { 129 | Color.background 130 | .edgesIgnoringSafeArea(.all) 131 | DownloadButton(downloader: Downloader()) 132 | } 133 | .colorScheme(.dark) 134 | } 135 | } 136 | 137 | 138 | // 25 - 23 139 | // 140 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/DownloadButton/DownloadStateView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownloadStateView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 09/04/21. 6 | // Copyright © 2021 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct DownloadStateView: View { 12 | 13 | // MARK: - variables 14 | var state: DownloadState = .downloaded 15 | var needsProgress: Bool = true 16 | var isLight: Bool = false 17 | 18 | @EnvironmentObject var downloader: Downloader 19 | @Binding var progress: CGFloat 20 | 21 | 22 | // MARK: - views 23 | var body: some View { 24 | ZStack { 25 | RoundedRectangle(cornerRadius: 0) 26 | .foregroundColor(state.getBackground()) 27 | Text(state.getStateName()) 28 | .foregroundColor(isLight ? .white : .background) 29 | .font(.system(size: 26, weight: .bold)) 30 | .shadow(color: Color.white.opacity(0.3), radius: 5, y: 2) 31 | .opacity(downloader.currentState != state ? 0 : 1) 32 | .offset(x: downloader.currentState.offsetForText() + 26) 33 | .animation(Animation.easeOut(duration: ButtonDimension.animationDuration / 2.25)) 34 | .frame(alignment: .leading) 35 | 36 | if (needsProgress) { 37 | Capsule(style: .circular) 38 | .trim(from: 0, to: progress / 2) 39 | .stroke(lineWidth: 8) 40 | .rotationEffect(.degrees(180)) 41 | .foregroundColor(Color(hex: "25D366")) 42 | .frame(width: ButtonDimension.width, height: 12) 43 | .offset(y: ButtonDimension.height / 2 + 4.5) 44 | .mask( 45 | RoundedRectangle(cornerRadius: ButtonDimension.cornerRadius) 46 | .frame(width: 320, height: 84) 47 | ) 48 | .opacity(downloader.currentState != state ? 0 : 1) 49 | .animation(.default) 50 | } 51 | } 52 | .frame(width: ButtonDimension.width, height: ButtonDimension.height) 53 | } 54 | } 55 | 56 | struct DownloadingStatesView_Previews: PreviewProvider { 57 | static var previews: some View { 58 | DownloadStateView(progress: .constant(0)) 59 | .environmentObject(Downloader()) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/DownloadButton/Model/Downloader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Downloader.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 08/04/21. 6 | // Copyright © 2021 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | enum DownloadState: CaseIterable { 12 | case notInitiated 13 | case downloading 14 | case downloaded 15 | 16 | func getStateName() -> String { 17 | switch self { 18 | case .notInitiated: 19 | return "Download" 20 | case .downloading: 21 | return "Downloading" 22 | case .downloaded: 23 | return "Finished" 24 | } 25 | } 26 | 27 | func getBackground() -> Color { 28 | switch self { 29 | case .notInitiated: 30 | return .label 31 | case .downloading: 32 | return Color(hex: "128C7E") 33 | case .downloaded: 34 | return Color.chatBackground 35 | } 36 | } 37 | 38 | func offsetForText() -> CGFloat { 39 | switch self { 40 | case.notInitiated: 41 | return 0 42 | case .downloading: 43 | return 8 44 | case .downloaded: 45 | return 0 46 | } 47 | } 48 | } 49 | 50 | struct ButtonDimension { 51 | static let width: CGFloat = 320 52 | static let height: CGFloat = 76 53 | static let animationDuration: TimeInterval = 0.35 54 | static let cornerRadius: CGFloat = 12 55 | } 56 | 57 | 58 | class Downloader: ObservableObject { 59 | @Published var currentState: DownloadState = DownloadState.notInitiated 60 | 61 | // MARK:- inits 62 | init(state: DownloadState = .notInitiated) { 63 | self.currentState = state 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/DownloadButton/Support/CircleTickShape.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircleTickShape.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 08/04/21. 6 | // Copyright © 2021 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct CircleTickShape: Shape { 12 | 13 | // MARK: - Variables 14 | var circleSize: CGFloat = 60 15 | var scaleFactor: CGFloat = 0.3 16 | 17 | // MARK: - Functions 18 | func path(in rect: CGRect) -> Path { 19 | let cX = rect.midX 20 | let cY = rect.midY 21 | 22 | var path = Path() 23 | path.move(to: CGPoint(x: cX, y: cY)) 24 | 25 | /// circle 26 | path.addEllipse(in: CGRect(x: cX - (circleSize / 2), y: cY - (circleSize / 2), width: circleSize, height: circleSize)) 27 | 28 | /// tick 29 | path.move(to: CGPoint(x: cX - (38 * scaleFactor), y: (cY + 2) - (scaleFactor))) 30 | path.addLine(to: CGPoint(x: cX - (scaleFactor * 18), y: cY + (scaleFactor * 28))) 31 | path.addLine(to: CGPoint(x: cX + (scaleFactor * 40), y: cY - (scaleFactor * 26))) 32 | 33 | return path 34 | } 35 | } 36 | 37 | struct CircleTickShape_Previews: PreviewProvider { 38 | static var previews: some View { 39 | CircleTickShape(circleSize: 50) 40 | .stroke(style: StrokeStyle(lineWidth: 4, lineCap: .round, lineJoin: .round)) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/DownloadButton/Support/DownloadStateView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownloadStateView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 09/04/21. 6 | // Copyright © 2021 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct DownloadStateView: View { 12 | 13 | // MARK:- variables 14 | var state: DownloadState = .downloaded 15 | var needsProgress: Bool = true 16 | var isLight: Bool = false 17 | 18 | @EnvironmentObject var downloader: Downloader 19 | @Binding var progress: CGFloat 20 | 21 | // MARK:- views 22 | var body: some View { 23 | ZStack { 24 | RoundedRectangle(cornerRadius: 0) 25 | .foregroundColor(state.getBackground()) 26 | Text(state.getStateName()) 27 | .foregroundColor(isLight ? .white : .background) 28 | .font(.system(size: 26, weight: .bold)) 29 | .shadow(color: Color.white.opacity(0.3), radius: 5, y: 2) 30 | .opacity(downloader.currentState != state ? 0 : 1) 31 | .offset(x: downloader.currentState.offsetForText() + 26) 32 | .animation(Animation.easeOut(duration: ButtonDimension.animationDuration / 2.25)) 33 | .frame(alignment: .leading) 34 | 35 | if (needsProgress) { 36 | Capsule(style: .circular) 37 | .trim(from: 0, to: progress / 2) 38 | .stroke(lineWidth: 8) 39 | .rotationEffect(.degrees(180)) 40 | .foregroundColor(Color(hex: "25D366")) 41 | .frame(width: ButtonDimension.width, height: 12) 42 | .offset(y: ButtonDimension.height / 2 + 4.5) 43 | .mask( 44 | RoundedRectangle(cornerRadius: ButtonDimension.cornerRadius) 45 | .frame(width: 320, height: 84) 46 | ) 47 | .opacity(downloader.currentState != state ? 0 : 1) 48 | .animation(.default) 49 | } 50 | } 51 | .frame(width: ButtonDimension.width, height: ButtonDimension.height) 52 | } 53 | } 54 | 55 | struct DownloadingStatesView_Previews: PreviewProvider { 56 | static var previews: some View { 57 | DownloadStateView(progress: .constant(0)) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/DownloadButton/Support/DownloadingIndicatorView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownloadingIcon.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 09/04/21. 6 | // Copyright © 2021 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct DownloadingIndicatorView: View { 12 | 13 | // MARK:- variables 14 | @State var downloadSymbolYOffset: CGFloat = 0 15 | let animationDuration: TimeInterval = 0.5 16 | let size: CGFloat = 38 17 | 18 | var needsAnimation: Bool = true 19 | 20 | // MARK:- views 21 | var body: some View { 22 | ZStack { 23 | Circle() 24 | .stroke(style: StrokeStyle(lineWidth: 4)) 25 | .frame(width: size, height: size) 26 | .shadow(color: Color.label.opacity(0.25), radius: 4, y: 2) 27 | Image(systemName: "arrow.down") 28 | .font(.system(size: 20, weight: .heavy)) 29 | .offset(y: downloadSymbolYOffset) 30 | .mask( 31 | Circle() 32 | .frame(width: size, height: size) 33 | ) 34 | } 35 | .onAppear() { 36 | if (needsAnimation) { 37 | withAnimation(Animation.easeIn(duration: animationDuration)) { 38 | downloadSymbolYOffset = size 39 | } 40 | Timer.scheduledTimer(withTimeInterval: animationDuration, repeats: true) { _ in 41 | animate() 42 | } 43 | } 44 | } 45 | } 46 | 47 | // MARK: - functions 48 | func animate() { 49 | downloadSymbolYOffset = -size 50 | withAnimation(Animation.easeIn(duration: animationDuration)) { 51 | downloadSymbolYOffset = size 52 | } 53 | } 54 | } 55 | 56 | struct DownloadingIcon_Previews: PreviewProvider { 57 | static var previews: some View { 58 | DownloadingIndicatorView() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/GithubLoader/GithubLoader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GithubLoader.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 14/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct GithubLoader: View { 12 | 13 | // MARK: - variables 14 | @State var resetStrokes: Bool = true 15 | @State var strokeStart: CGFloat = 0 16 | @State var strokeEnd: CGFloat = 0 17 | 18 | 19 | // MARK: - views 20 | var body: some View { 21 | ZStack { 22 | Color.black 23 | .edgesIgnoringSafeArea(.all) 24 | OctocatShape() 25 | .stroke(style: StrokeStyle(lineWidth: 2.5, lineCap: .round, lineJoin: .round, miterLimit: 5)) 26 | .foregroundColor(Color.white) 27 | .opacity(0.35) 28 | OctocatShape() 29 | .trim(from: strokeStart, to: strokeEnd) 30 | .stroke(style: StrokeStyle(lineWidth: 5, lineCap: .round, lineJoin: .round, miterLimit: 10)) 31 | .foregroundColor(Color.white) 32 | .onAppear() { 33 | Timer.scheduledTimer(withTimeInterval: 0.35, repeats: true) { timer in 34 | if (self.strokeEnd >= 1) { 35 | if (self.resetStrokes) { 36 | Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in 37 | self.strokeEnd = 0 38 | self.strokeStart = 0 39 | self.resetStrokes.toggle() 40 | } 41 | self.resetStrokes = false 42 | } 43 | } 44 | withAnimation(Animation.easeOut(duration: 0.5)) { 45 | self.strokeEnd += 0.1 46 | self.strokeStart = self.strokeEnd - 0.3 47 | } 48 | } 49 | } 50 | VStack{ 51 | Spacer() 52 | HStack { 53 | Spacer() 54 | Text("@Shubham_iosdev") 55 | .foregroundColor(.white) 56 | .font(.system(size: 28, weight: .medium, design: .monospaced)) 57 | .opacity(0.3) 58 | }.padding(.trailing, 16) 59 | } 60 | } 61 | } 62 | } 63 | 64 | struct InfinityLoader_Previews: PreviewProvider { 65 | static var previews: some View { 66 | GithubLoader() 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/GithubLoader/Support Shapes/Octocat.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OctocatShape.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 14/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Octocat: Shape { 12 | 13 | // MARK:- variables 14 | 15 | // MARK:- functions 16 | func path(in rect: CGRect) -> Path { 17 | 18 | ///phew, had to do a lot of hit and trials for this xD 19 | var path = Path() 20 | path.move(to: CGPoint(x: 243.77, y: 483.38)) 21 | 22 | // right side 23 | path.addLine(to: CGPoint(x: 243.77, y: 441.77)) 24 | path.addLine(to: CGPoint(x: 243.79, y: 441.46)) 25 | 26 | path.addCurve(to: CGPoint(x: 233.25, y: 413.32), control1: CGPoint(x: 244.53, y: 431), control2: CGPoint(x: 240.68, y: 420.73)) 27 | path.addCurve(to: CGPoint(x: 303, y: 338.47), control1: CGPoint(x: 267.46, y: 409.95), control2: CGPoint(x: 303, y: 397.16)) 28 | path.addLine(to: CGPoint(x: 303, y: 338.48)) 29 | path.addCurve(to: CGPoint(x: 286.56, y: 297.86), control1: CGPoint(x: 303, y: 323.32), control2: CGPoint(x: 297.11, y: 308.76)) 30 | path.addLine(to: CGPoint(x: 287, y: 297.74)) 31 | path.addCurve(to: CGPoint(x: 285.57, y: 256.94), control1: CGPoint(x: 291.84, y: 284.47), control2: CGPoint(x: 291.33, y: 269.84)) 32 | path.addCurve(to: CGPoint(x: 243.77, y: 273.54), control1: CGPoint(x: 285.88, y: 257.63), control2: CGPoint(x: 273.17, y: 253.87)) 33 | 34 | // center 35 | path.addLine(to: CGPoint(x: 243.37, y: 273.43)) 36 | path.addCurve(to: CGPoint(x: 168.78, y: 273.43), control1: CGPoint(x: 218.94, y: 266.9), control2: CGPoint(x: 193.21, y: 266.9)) 37 | 38 | // leftSide 39 | path.addCurve(to: CGPoint(x: 126.28, y: 257.63), control1: CGPoint(x: 138.98, y: 253.87), control2: CGPoint(x: 126.28, y: 257.63)) 40 | path.addLine(to: CGPoint(x: 126.2, y: 257.81)) 41 | path.addCurve(to: CGPoint(x: 125.49, y: 298.63), control1: CGPoint(x: 120.67, y: 270.81), control2: CGPoint(x: 120.42, y: 285.45)) 42 | path.addLine(to: CGPoint(x: 125.6, y: 297.86)) 43 | path.addCurve(to: CGPoint(x: 109.15, y: 338.48), control1: CGPoint(x: 115.05, y: 308.76), control2: CGPoint(x: 109.15, y: 323.33)) 44 | 45 | path.addCurve(to: CGPoint(x: 178.51, y: 414.04), control1: CGPoint(x: 109.15, y: 397.06), control2: CGPoint(x: 144.69, y: 409.85)) 46 | path.addLine(to: CGPoint(x: 178.48, y: 414.07)) 47 | path.addCurve(to: CGPoint(x: 168.38, y: 441.76), control1: CGPoint(x: 171.34, y: 421.45), control2: CGPoint(x: 167.67, y: 431.52)) 48 | path.addLine(to: CGPoint(x: 168.38, y: 483.38)) 49 | 50 | // tail 51 | path.move(to: CGPoint(x: 168.38, y: 451.13)) 52 | path.addCurve(to: CGPoint(x: 93, y: 418.88), control1: CGPoint(x: 114.54, y: 467.25), control2: CGPoint(x: 114.54, y: 424.25)) 53 | return path 54 | } 55 | } 56 | 57 | struct Octocat_Previews: PreviewProvider { 58 | static var previews: some View { 59 | ZStack{ 60 | Color.black 61 | .edgesIgnoringSafeArea(.all) 62 | OctocatShape() 63 | .stroke(style: StrokeStyle(lineWidth: 4, lineCap: .round, lineJoin: .round, miterLimit: 8)) 64 | .foregroundColor(Color.white) 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/InfinityLoader/InfinityView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InfinityView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 03/12/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct InfinityView: View { 12 | 13 | // MARK:- variables 14 | let animationDuration: TimeInterval = 0.2 15 | let strokeWidth: CGFloat = 20 16 | let animationCap: CGFloat = 1.205 17 | 18 | 19 | @State var strokeStart: CGFloat = 0 20 | @State var strokeEnd: CGFloat = 0 21 | @State var additionalLength: CGFloat = 0 22 | 23 | // MARK:- views 24 | var body: some View { 25 | ZStack { 26 | Color.black 27 | .edgesIgnoringSafeArea(.all) 28 | InfinityShape() 29 | .stroke(style: StrokeStyle(lineWidth: strokeWidth, lineCap: .round, lineJoin: .round)) 30 | .foregroundColor(.white) 31 | .shadow(color: Color.white,radius: 4) 32 | .overlay( 33 | InfinityShape() 34 | .trim(from: strokeStart, to: strokeEnd) 35 | .stroke(style: StrokeStyle(lineWidth: strokeWidth - 0.5, lineCap: .round, lineJoin: .round)) 36 | .foregroundColor(.materialBlack) 37 | .shadow(color: Color.white, radius: 5) 38 | ) 39 | }.onAppear() { 40 | Timer.scheduledTimer(withTimeInterval: animationDuration, repeats: true) { _ in 41 | withAnimation(Animation.linear(duration: animationDuration)) { 42 | strokeEnd += 0.05 43 | strokeStart = strokeEnd - (0.05 + additionalLength) 44 | } 45 | 46 | // reset values 47 | if (strokeEnd >= animationCap) { 48 | strokeEnd = 0 49 | additionalLength = 0 50 | strokeStart = 0 51 | } 52 | } 53 | 54 | Timer.scheduledTimer(withTimeInterval: animationDuration * 3, repeats: true) { _ in 55 | additionalLength += 0.015 56 | } 57 | } 58 | } 59 | } 60 | 61 | struct InfinityView_Previews: PreviewProvider { 62 | static var previews: some View { 63 | InfinityView() 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/InfinityLoader/Support Shapes/InfinityShape.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InfinityShape.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 03/12/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct InfinityShape: Shape { 12 | 13 | // MARK:- functions 14 | func path(in rect: CGRect) -> Path { 15 | var path = Path() 16 | path.move(to: CGPoint(x: rect.midX - 100, y: rect.midY + 72)) 17 | 18 | path.addCurve(to: CGPoint(x: rect.midX - 100, y: rect.midY - 72), control1: CGPoint(x: rect.midX - 200, y: rect.midY + 72), control2: CGPoint(x: rect.midX - 200, y: rect.midY - 72)) 19 | path.addCurve(to: CGPoint(x: rect.midX + 100, y: rect.midY + 72), control1: CGPoint(x: rect.midX , y: rect.midY - 72), control2: CGPoint(x: rect.midX, y: rect.midY + 72)) 20 | path.addCurve(to: CGPoint(x: rect.midX + 100, y: rect.midY - 72), control1: CGPoint(x: rect.midX + 200, y: rect.midY + 72), control2: CGPoint(x: rect.midX + 200, y: rect.midY - 72)) 21 | 22 | path.addCurve(to: CGPoint(x: rect.midX - 100, y: rect.midY + 72), control1: CGPoint(x: rect.midX, y: rect.midY - 72), control2: CGPoint(x: rect.midX , y: rect.midY + 72)) 23 | return path 24 | } 25 | } 26 | 27 | struct InfinityShape_Previews: PreviewProvider { 28 | static var previews: some View { 29 | InfinityShape() 30 | .stroke(style: StrokeStyle(lineWidth: 20, lineCap: .round)) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/LightSwitch/LightSwitchView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LightSwitchView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 16/12/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct LightSwitchView: View { 12 | 13 | // MARK:- variables 14 | let appWidth = UIScreen.main.bounds.width 15 | let appHeight = UIScreen.main.bounds.height 16 | let animationDuration: TimeInterval = 0.35 17 | 18 | @State var xScale: CGFloat = 2 19 | @State var yScale: CGFloat = 0.4 20 | @State var yOffset: CGFloat = UIScreen.main.bounds.height * 0.8 21 | 22 | 23 | @State var isOff: Bool = true 24 | 25 | // MARK:- views 26 | var body: some View { 27 | ZStack { 28 | Color.black 29 | Circle() 30 | .fill(Color.yellow) 31 | .scaleEffect(CGSize(width: xScale, height: yScale)) 32 | .offset(y: yOffset) 33 | VStack(alignment: .leading) { 34 | HStack { 35 | Image(systemName: "arrow.left") 36 | .foregroundColor(isOff ? .white : .black) 37 | .font(.system(size: 24, weight: .semibold, design: .monospaced)) 38 | Spacer() 39 | 40 | .offset(x: -12) 41 | Spacer() 42 | }.padding([.top, .bottom], 24) 43 | Spacer() 44 | }.offset(y: 32) 45 | .padding([.leading, .trailing], 24) 46 | ZStack { 47 | Capsule(style: .continuous) 48 | .foregroundColor(.gray) 49 | .frame(width: 52, height: appHeight * 0.25 + 6) 50 | .opacity(0.275) 51 | .offset(x: appWidth / 2 - 48, y: 16) 52 | ZStack { 53 | Capsule() 54 | .frame(width: 3, height: self.isOff ? appHeight * 0.41 : appHeight * 0.625) 55 | .foregroundColor(.white) 56 | Circle() 57 | .fill(Color.white) 58 | .frame(width: 42, height: 42) 59 | .offset(y: self.isOff ? appHeight * 0.225: appHeight * 0.25 + 42) 60 | .onTapGesture { 61 | toggleAllLights() 62 | } 63 | }.offset(x: appWidth / 2 - 48, y: -appHeight / 2) 64 | .frame(height: 0, alignment: .top) 65 | } 66 | .animation(Animation.spring(dampingFraction: 0.65).speed(1.25)) 67 | }.edgesIgnoringSafeArea(.all) 68 | } 69 | 70 | // MARK:- functions 71 | func toggleAllLights() { 72 | if (isOff) { 73 | withAnimation(Animation.easeIn(duration: animationDuration)) { 74 | xScale = 4 75 | yScale = 4 76 | yOffset = 0 77 | } 78 | } else { 79 | withAnimation(Animation.easeOut(duration: animationDuration * 0.75)) { 80 | yScale = 0.4 81 | xScale = 2 82 | yOffset = UIScreen.main.bounds.height * 0.8 83 | } 84 | } 85 | isOff.toggle() 86 | } 87 | } 88 | 89 | struct LightSwitchView_Previews: PreviewProvider { 90 | static var previews: some View { 91 | LightSwitchView() 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Like/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Code/Animations/Like/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Like/LikeButtonView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LikeButton.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 26/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct LikeView: View { 12 | 13 | // MARK:- variables 14 | let animationDuration: Double = 0.25 15 | 16 | @State var isAnimating: Bool = false 17 | @State var shrinkIcon: Bool = false 18 | @State var floatLike: Bool = false 19 | @State var showFlare: Bool = false 20 | 21 | // MARK:- views 22 | var body: some View { 23 | ZStack { 24 | Color.likeBackground 25 | .edgesIgnoringSafeArea(.all) 26 | ZStack { 27 | if (floatLike) { 28 | CapusuleGroupView(isAnimating: $floatLike) 29 | .offset(y: -130) 30 | .scaleEffect(self.showFlare ? 1.25 : 0.8) 31 | .opacity(self.floatLike ? 1 : 0) 32 | .animation(Animation.spring().delay(animationDuration / 2)) 33 | } 34 | Circle() 35 | .foregroundColor(self.isAnimating ? Color.likeColor : Color.likeOverlay) 36 | .animation(Animation.easeOut(duration: animationDuration * 2).delay(animationDuration)) 37 | HeartImageView() 38 | .foregroundColor(.white) 39 | .offset(y: 12) 40 | .scaleEffect(self.isAnimating ? 1.25 : 1) 41 | .overlay( 42 | Color.likeColor 43 | .mask( 44 | HeartImageView() 45 | ) 46 | .offset(y: 12) 47 | .scaleEffect(self.isAnimating ? 1.35 : 0) 48 | .animation(Animation.easeIn(duration: animationDuration)) 49 | .opacity(self.isAnimating ? 0 : 1) 50 | .animation(Animation.easeIn(duration: animationDuration).delay(animationDuration)) 51 | ) 52 | }.frame(width: 250, height: 250) 53 | .scaleEffect(self.shrinkIcon ? 0.35 : 1) 54 | .animation(Animation.spring(response: animationDuration, dampingFraction: 1, blendDuration: 1)) 55 | if (floatLike) { 56 | FloatingLike(isAnimating: $floatLike) 57 | .offset(y: -40) 58 | } 59 | }.onTapGesture { 60 | if (!floatLike) { 61 | self.floatLike.toggle() 62 | self.isAnimating.toggle() 63 | self.shrinkIcon.toggle() 64 | Timer.scheduledTimer(withTimeInterval: animationDuration, repeats: false) { _ in 65 | self.shrinkIcon.toggle() 66 | self.showFlare.toggle() 67 | } 68 | } else { 69 | self.isAnimating = false 70 | self.shrinkIcon = false 71 | self.showFlare = false 72 | self.floatLike = false 73 | } 74 | } 75 | } 76 | } 77 | 78 | struct LikeButton_Previews: PreviewProvider { 79 | static var previews: some View { 80 | LikeView() 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Like/LikeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LikeView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 26/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct LikeView: View { 12 | 13 | // MARK:- variables 14 | let animationDuration: Double = 0.25 15 | 16 | @State var isAnimating: Bool = false 17 | @State var shrinkIcon: Bool = false 18 | @State var floatLike: Bool = false 19 | @State var showFlare: Bool = false 20 | 21 | // MARK:- views 22 | var body: some View { 23 | ZStack { 24 | Color.likeBackground 25 | .edgesIgnoringSafeArea(.all) 26 | ZStack { 27 | if (floatLike) { 28 | CapusuleGroupView(isAnimating: $floatLike) 29 | .offset(y: -130) 30 | .scaleEffect(self.showFlare ? 1.25 : 0.8) 31 | .opacity(self.floatLike ? 1 : 0) 32 | .animation(Animation.spring().delay(animationDuration / 2)) 33 | } 34 | Circle() 35 | .foregroundColor(self.isAnimating ? Color.likeColor : Color.likeOverlay) 36 | .animation(Animation.easeOut(duration: animationDuration * 2).delay(animationDuration)) 37 | HeartImageView() 38 | .foregroundColor(.white) 39 | .offset(y: 12) 40 | .scaleEffect(self.isAnimating ? 1.25 : 1) 41 | .overlay( 42 | Color.likeColor 43 | .mask( 44 | HeartImageView() 45 | ) 46 | .offset(y: 12) 47 | .scaleEffect(self.isAnimating ? 1.35 : 0) 48 | .animation(Animation.easeIn(duration: animationDuration)) 49 | .opacity(self.isAnimating ? 0 : 1) 50 | .animation(Animation.easeIn(duration: animationDuration).delay(animationDuration)) 51 | ) 52 | }.frame(width: 250, height: 250) 53 | .scaleEffect(self.shrinkIcon ? 0.35 : 1) 54 | .animation(Animation.spring(response: animationDuration, dampingFraction: 1, blendDuration: 1)) 55 | if (floatLike) { 56 | FloatingLike(isAnimating: $floatLike) 57 | .offset(y: -40) 58 | } 59 | }.onTapGesture { 60 | if (!floatLike) { 61 | self.floatLike.toggle() 62 | self.isAnimating.toggle() 63 | self.shrinkIcon.toggle() 64 | Timer.scheduledTimer(withTimeInterval: animationDuration, repeats: false) { _ in 65 | self.shrinkIcon.toggle() 66 | self.showFlare.toggle() 67 | } 68 | } else { 69 | self.isAnimating = false 70 | self.shrinkIcon = false 71 | self.showFlare = false 72 | self.floatLike = false 73 | } 74 | } 75 | } 76 | } 77 | 78 | struct LikeButton_Previews: PreviewProvider { 79 | static var previews: some View { 80 | LikeView() 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Like/Support Shapes/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Code/Animations/Like/Support Shapes/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Like/Support Shapes/CapusuleGroupView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UpperCapsuleView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 26/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct CapusuleGroupView: View { 12 | 13 | // MARK:- variables 14 | @Binding var isAnimating: Bool 15 | 16 | // MARK:- views 17 | var body: some View { 18 | ZStack { 19 | ShrinkingCapsule(rotationAngle: .zero, offset: CGSize(width: 0, height: -15), isAnimating: $isAnimating) 20 | ShrinkingCapsule(rotationAngle: .degrees(-33), offset: CGSize(width: -80, height: 7.5), isAnimating: $isAnimating) 21 | ShrinkingCapsule(rotationAngle: .degrees(33), offset: CGSize(width: 80, height: 7.5), isAnimating: $isAnimating) 22 | ShrinkingCapsule(rotationAngle: .degrees(-65), offset: CGSize(width: -135, height: 70), isAnimating: $isAnimating) 23 | ShrinkingCapsule(rotationAngle: .degrees(65), offset: CGSize(width: 135, height: 70), isAnimating: $isAnimating) 24 | LowerCapsuleView(isAnimating: $isAnimating) 25 | } 26 | .onTapGesture { 27 | self.isAnimating.toggle() 28 | } 29 | } 30 | } 31 | 32 | struct UpperCapsuleView_Previews: PreviewProvider { 33 | static var previews: some View { 34 | CapusuleGroupView(isAnimating: .constant(false)) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Like/Support Shapes/FloatingLike.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FloatingLike.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 26/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct FloatingLike: View { 12 | 13 | let animationDuration: TimeInterval = 0.45 14 | let animation = Animation.spring(response: 0.75).speed(0.75) 15 | 16 | @State var scale: CGFloat = 1.25 17 | @State var offset: CGSize = CGSize(width: 0, height: 0) 18 | @State var rotationAngle: Angle = Angle.degrees(-4) 19 | @State var opacity: Double = 1 20 | 21 | @Binding var isAnimating: Bool 22 | 23 | var body: some View { 24 | ZStack{ 25 | Capsule(style: .circular) 26 | .fill(Color.likeColor) 27 | HStack { 28 | Spacer() 29 | Image(systemName: "plus") 30 | .foregroundColor(Color.white) 31 | .font(.system(size: 52, weight: .bold, design: .monospaced)) 32 | Text("1") 33 | .foregroundColor(.white) 34 | .font(.system(size: 72, weight: .bold, design: .rounded)) 35 | Spacer() 36 | } 37 | }.frame(width: 165, height: 130, alignment: .center) 38 | .rotationEffect(rotationAngle) 39 | .scaleEffect(scale) 40 | .offset(offset) 41 | .opacity(opacity) 42 | .onAppear() { 43 | self.scale = 0.1 44 | Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { checkingTimer in 45 | if (isAnimating) { 46 | checkingTimer.invalidate() 47 | floatCapsule() 48 | } 49 | } 50 | } 51 | } 52 | 53 | // MARK:- functions 54 | func floatCapsule() { 55 | withAnimation(animation) { 56 | self.scale = 0.75 57 | self.offset = CGSize(width: 10, height: -100) 58 | self.rotationAngle = .degrees(-10) 59 | } 60 | Timer.scheduledTimer(withTimeInterval: animationDuration / 2, repeats: false) { _ in 61 | withAnimation(animation) { 62 | self.offset = CGSize(width: -10, height: -200) 63 | } 64 | withAnimation(Animation.spring(response: animationDuration * 1.2).speed(0.75)) { 65 | self.rotationAngle = .degrees(10) 66 | } 67 | } 68 | Timer.scheduledTimer(withTimeInterval: animationDuration , repeats: false) { _ in 69 | withAnimation(animation) { 70 | self.offset = CGSize(width: 0, height: -300) 71 | self.rotationAngle = .degrees(0) 72 | } 73 | } 74 | 75 | Timer.scheduledTimer(withTimeInterval: animationDuration * 1.5, repeats: false) { _ in 76 | withAnimation(animation) { 77 | self.opacity = 0 78 | } 79 | } 80 | } 81 | } 82 | 83 | struct FloatingLike_Previews: PreviewProvider { 84 | static var previews: some View { 85 | FloatingLike(isAnimating: .constant(true)) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Like/Support Shapes/HeartImageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeartImageView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 26/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct HeartImageView: View { 12 | var body: some View { 13 | Image(systemName: "suit.heart.fill") 14 | .font(.system(size: 160, weight: .medium, design: .monospaced)) 15 | } 16 | } 17 | 18 | struct HeartImageView_Previews: PreviewProvider { 19 | static var previews: some View { 20 | HeartImageView() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Like/Support Shapes/LowerCapsuleView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LowerCapsuleView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 26/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct LowerCapsuleView: View { 12 | 13 | // MARK:- variables 14 | @Binding var isAnimating: Bool 15 | 16 | // MARK:- views 17 | var body: some View { 18 | ZStack { 19 | ShrinkingCapsule(rotationAngle: .degrees(16), offset: CGSize(width: -42.5, height: 10), isAnimating: $isAnimating) 20 | ShrinkingCapsule(rotationAngle: .degrees( -16), offset: CGSize(width: 42.5, height: 10), isAnimating: $isAnimating) 21 | ShrinkingCapsule(rotationAngle: .degrees(48), offset: CGSize(width: -107, height: -30), isAnimating: $isAnimating) 22 | ShrinkingCapsule(rotationAngle: .degrees(-48), offset: CGSize(width: 107, height: -30), isAnimating: $isAnimating) 23 | ShrinkingCapsule(rotationAngle: .degrees(82), offset: CGSize(width: -142, height: -95), isAnimating: $isAnimating) 24 | ShrinkingCapsule(rotationAngle: .degrees(-82), offset: CGSize(width: 142, height: -95), isAnimating: $isAnimating) 25 | } 26 | .offset(y: 260) 27 | } 28 | } 29 | 30 | struct LowerCapsuleView_Previews: PreviewProvider { 31 | static var previews: some View { 32 | LowerCapsuleView(isAnimating: .constant(false)) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Like/Support Shapes/ShrinkingCapsule.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShrinkingCapsule.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 26/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ShrinkingCapsule: View { 12 | 13 | // MARK:- variables 14 | let animationDuration: Double = 0.4 15 | let rotationAngle: Angle 16 | let offset: CGSize 17 | 18 | @Binding var isAnimating: Bool 19 | @State var hideCapsule: Bool = false 20 | 21 | var body: some View { 22 | ZStack { 23 | Capsule(style: .continuous) 24 | .fill(Color.likeColor) 25 | .frame(width: 15, height: self.isAnimating ? 30 : 65, alignment: .bottomLeading) 26 | .rotationEffect(rotationAngle) 27 | }.offset(offset) 28 | .opacity(self.hideCapsule ? 0 : 0.8) 29 | .animation(Animation.easeIn(duration: animationDuration)) 30 | .onAppear() { 31 | Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in 32 | if (self.isAnimating) { 33 | Timer.scheduledTimer(withTimeInterval: animationDuration, repeats: false) { _ in 34 | self.hideCapsule.toggle() 35 | } 36 | timer.invalidate() 37 | } 38 | } 39 | } 40 | } 41 | } 42 | 43 | struct ShrinkingCapsule_Previews: PreviewProvider { 44 | static var previews: some View { 45 | ShrinkingCapsule(rotationAngle: .degrees(35), offset: CGSize(width: 10, height: 10), isAnimating: .constant(false)) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Loader/LoaderState.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoaderState.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 18/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | enum LoaderState: CaseIterable { 12 | case right 13 | case down 14 | case left 15 | case up 16 | 17 | var alignment: Alignment { 18 | switch self { 19 | case .right, .down: 20 | return .topLeading 21 | case .left: 22 | return .topTrailing 23 | case .up: 24 | return .bottomLeading 25 | } 26 | } 27 | 28 | var capsuleDimension: CGFloat { 29 | return 40 30 | } 31 | var increasingOffset: CGFloat { 32 | return 72 33 | } 34 | 35 | var increment_before: (CGFloat, CGFloat, CGFloat, CGFloat) { 36 | switch self { 37 | case .right: 38 | return (0, 0, capsuleDimension + increasingOffset, capsuleDimension) 39 | case .down: 40 | return (increasingOffset, 0, capsuleDimension, capsuleDimension + increasingOffset) 41 | case .left: 42 | return (increasingOffset, increasingOffset, capsuleDimension + increasingOffset, capsuleDimension) 43 | case .up: 44 | return (0, capsuleDimension + increasingOffset, capsuleDimension, capsuleDimension + increasingOffset) 45 | } 46 | } 47 | 48 | var increment_after: (CGFloat, CGFloat, CGFloat, CGFloat) { 49 | switch self { 50 | case .right: 51 | return (increasingOffset, 0, capsuleDimension, capsuleDimension) 52 | case .down: 53 | return (increasingOffset, increasingOffset, capsuleDimension, capsuleDimension) 54 | case .left: 55 | return (0, increasingOffset, capsuleDimension, capsuleDimension) 56 | default: 57 | return (0, capsuleDimension, capsuleDimension, capsuleDimension) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Loader/LoaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoaderView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 18/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | 12 | struct LoaderView: View { 13 | 14 | // MARK:- variables 15 | @State var animateLoaders: Bool = false 16 | 17 | // MARK:- views 18 | var body: some View { 19 | ZStack { 20 | Color.black 21 | .edgesIgnoringSafeArea(.all) 22 | ZStack { 23 | Loader(loaderState: .down, timerDuration: 0.35, startAnimating: $animateLoaders) 24 | Loader(loaderState: .right, timerDuration: 1.05, startAnimating: $animateLoaders) 25 | Loader(loaderState: .up, timerDuration: 1.75, startAnimating: $animateLoaders) 26 | }.offset(x: -40, y: -40) 27 | }.onAppear() { 28 | self.animateLoaders.toggle() 29 | } 30 | } 31 | } 32 | 33 | struct LoaderView_Previews: PreviewProvider { 34 | static var previews: some View { 35 | LoaderView() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Loader/Support Shapes/Loader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Loader.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 18/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Loader: View { 12 | 13 | // MARK:- variables 14 | @State var capsuleWidth: CGFloat = 40 15 | @State var capsuleHeight: CGFloat = 40 16 | @State var xOffset: CGFloat = 0 17 | @State var yOffset: CGFloat = 0 18 | @State var loaderState: LoaderState 19 | @State var currentIndex = 0 20 | @State var animationStarted: Bool = true 21 | 22 | var timerDuration: TimeInterval 23 | @Binding var startAnimating: Bool 24 | 25 | // MARK:- views 26 | var body: some View { 27 | ZStack(alignment: Alignment(horizontal: .center, vertical: .bottom), content: { 28 | Capsule() 29 | .stroke(style: StrokeStyle(lineWidth: 14, lineCap: .round)) 30 | .foregroundColor(Color.white) 31 | .frame(width: capsuleWidth, height: capsuleHeight, alignment: .center) 32 | .animation(.easeOut(duration: 0.35)) 33 | .offset(x: self.xOffset, y: self.yOffset) 34 | 35 | }).frame(width: 40, height: 0, alignment: loaderState.alignment) 36 | .onAppear() { 37 | self.setIndex() 38 | Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (initialTimer) in 39 | if (self.startAnimating) { 40 | Timer.scheduledTimer(withTimeInterval: self.timerDuration, repeats: false) { (separatorTimer) in 41 | self.animateCapsule() 42 | Timer.scheduledTimer(withTimeInterval: 2.1, repeats: true) { (loaderTimer) in 43 | if (!self.startAnimating) { 44 | loaderTimer.invalidate() 45 | } 46 | self.loaderState = self.getNextCase() 47 | self.animateCapsule() 48 | } 49 | } 50 | // invalidate the initialTimer that starts the animation once the binding constant is true 51 | initialTimer.invalidate() 52 | } 53 | } 54 | } 55 | } 56 | 57 | // MARK:- functions 58 | 59 | // provides the next case defined in the enum based on the currentIndex 60 | func getNextCase() -> LoaderState { 61 | let allCases = LoaderState.allCases 62 | if (self.currentIndex == allCases.count - 1) { 63 | self.currentIndex = -1 64 | } 65 | self.currentIndex += 1 66 | let index = self.currentIndex 67 | return allCases[index] 68 | } 69 | 70 | // sets the initialIndex & offset values based on the loader state provided to the view 71 | func setIndex() { 72 | for (ix, loaderCase) in LoaderState.allCases.enumerated() { 73 | if (loaderCase == self.loaderState) { 74 | self.currentIndex = ix 75 | self.xOffset = LoaderState.allCases[self.currentIndex].increment_before.0 76 | self.yOffset = LoaderState.allCases[self.currentIndex].increment_before.1 77 | } 78 | } 79 | } 80 | 81 | // animates the capsule to a direction 82 | func animateCapsule() { 83 | self.xOffset = self.loaderState.increment_before.0 84 | self.yOffset = self.loaderState.increment_before.1 85 | self.capsuleWidth = self.loaderState.increment_before.2 86 | self.capsuleHeight = self.loaderState.increment_before.3 87 | 88 | Timer.scheduledTimer(withTimeInterval: 0.35, repeats: false) { (Timer) in 89 | self.xOffset = self.loaderState.increment_after.0 90 | self.yOffset = self.loaderState.increment_after.1 91 | self.capsuleWidth = self.loaderState.increment_after.2 92 | self.capsuleHeight = self.loaderState.increment_after.3 93 | } 94 | } 95 | } 96 | 97 | struct Loader_Previews: PreviewProvider { 98 | static var previews: some View { 99 | ZStack { 100 | Color.black 101 | .edgesIgnoringSafeArea(.all) 102 | Loader(loaderState: .down, timerDuration: 0.35, startAnimating: .constant(true)) 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Loader2/LoaderIIView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoaderIIView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 20/12/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct LoaderIIView: View { 12 | 13 | // MARK:- views 14 | var body: some View { 15 | ZStack { 16 | VStack(spacing: 24) { 17 | MovingCircleView(state: .right, moveOffset: 15, animationDuration: 1) 18 | MovingCircleView(state: .left, moveOffset: 15, animationDuration: 1.1) 19 | MovingCircleView(state: .right, moveOffset: 15, animationDuration: 1.05) 20 | MovingCircleView(state: .left, moveOffset: 15, animationDuration: 1.15) 21 | MovingCircleView(state: .right, moveOffset: 15, animationDuration: 1.1) 22 | MovingCircleView(state: .left, moveOffset: 15, animationDuration: 1.05) 23 | MovingCircleView(state: .right, moveOffset: 15, animationDuration: 1) 24 | } 25 | } 26 | } 27 | } 28 | 29 | struct LoaderIIView_Previews: PreviewProvider { 30 | static var previews: some View { 31 | ZStack { 32 | Color.black 33 | .edgesIgnoringSafeArea(.all) 34 | LoaderIIView() 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Loader2/Support Shapes/MovingCircleView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MovingCircleView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 20/12/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | enum CircleState { 12 | case left 13 | case right 14 | case undefined 15 | } 16 | 17 | struct MovingCircleView: View { 18 | 19 | // MARK:- variables 20 | var state: CircleState = .undefined 21 | 22 | var moveOffset: CGFloat = 0 23 | var animationDuration: TimeInterval = 0.3 24 | 25 | @State var xOffset: CGFloat = 0 26 | 27 | // MARK:- views 28 | var body: some View { 29 | Circle() 30 | .fill(Color.white) 31 | .frame(width: 18, height: 18) 32 | .offset(x: xOffset) 33 | .shadow(color: Color.white, radius: 5) 34 | .onAppear() { 35 | if (state == .left) { 36 | Timer.scheduledTimer(withTimeInterval: animationDuration, repeats: true) { _ in 37 | initiateWithLeft() 38 | } 39 | } else { 40 | Timer.scheduledTimer(withTimeInterval: animationDuration, repeats: true) { _ in 41 | initiateWithRight() 42 | } 43 | } 44 | } 45 | } 46 | 47 | // MARK:- functions 48 | func initiateWithLeft() { 49 | withAnimation(Animation.easeInOut(duration: animationDuration / 2)) { 50 | self.xOffset = -moveOffset 51 | } 52 | 53 | Timer.scheduledTimer(withTimeInterval: animationDuration / 2, repeats: false) { _ in 54 | withAnimation(Animation.easeInOut(duration: 0.5)) { 55 | self.xOffset = moveOffset 56 | } 57 | } 58 | } 59 | 60 | func initiateWithRight() { 61 | withAnimation(Animation.easeInOut(duration: animationDuration / 2)) { 62 | self.xOffset = moveOffset 63 | } 64 | 65 | Timer.scheduledTimer(withTimeInterval: animationDuration / 2, repeats: false) { _ in 66 | withAnimation(Animation.easeInOut(duration: animationDuration / 2)) { 67 | self.xOffset = -moveOffset 68 | } 69 | } 70 | } 71 | } 72 | 73 | struct MovingCircleView_Previews: PreviewProvider { 74 | static var previews: some View { 75 | ZStack { 76 | Color.black 77 | .edgesIgnoringSafeArea(.all) 78 | MovingCircleView(moveOffset: 40, animationDuration: 1) 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/LoginView/Support Shapes/Bolt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Bolt.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 24/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Bolt: Shape { 12 | 13 | func path(in rect: CGRect) -> Path { 14 | var path = Path() 15 | 16 | path.move(to: CGPoint(x: 211.67, y: 327.33)) 17 | path.addLine(to: CGPoint(x: 175, y: 371.33)) 18 | path.addLine(to: CGPoint(x: 208, y: 371.33)) 19 | 20 | path.addLine(to: CGPoint(x: 204.33, y: 400.67)) 21 | path.addLine(to: CGPoint(x: 241, y: 356.67)) 22 | 23 | path.addLine(to: CGPoint(x: 208, y: 356.67)) 24 | path.addLine(to: CGPoint(x: 211.67, y: 327.33)) 25 | return path 26 | } 27 | } 28 | 29 | struct Bolt_Previews: PreviewProvider { 30 | static var previews: some View { 31 | Bolt() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/LoginView/Support Shapes/Plus.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Plus.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 16/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Plus: Shape { 12 | 13 | func path(in rect: CGRect) -> Path { 14 | 15 | let cX: CGFloat = rect.midX 16 | let cY: CGFloat = rect.midY 17 | 18 | var path = Path() 19 | 20 | path.move(to: CGPoint(x: cX, y: cY + -16)) 21 | path.addLine(to: CGPoint(x: cX, y: cY + 16)) 22 | path.move(to: CGPoint(x: cX + -16, y: cY)) 23 | path.addLine(to: CGPoint(x: cX + 16, y: cY)) 24 | return path 25 | } 26 | 27 | 28 | } 29 | 30 | struct Plus_Previews: PreviewProvider { 31 | static var previews: some View { 32 | Plus() 33 | .stroke(style: StrokeStyle(lineWidth: 6, lineCap: .round)) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/LoginView/Support Shapes/RoundedTriangle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RoundedRectangle.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 24/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct RoundedTriangle: Shape { 12 | func path(in rect: CGRect) -> Path { 13 | var path = Path() 14 | 15 | path.move(to: CGPoint(x: rect.minX, y: rect.maxY)) 16 | path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) 17 | path.addCurve(to: CGPoint(x: rect.midX, y: rect.minY), control1: CGPoint(x: rect.midX + 124, y: rect.minY), control2: CGPoint(x: rect.midX, y: rect.minY)) 18 | path.addCurve(to: CGPoint(x: rect.minX, y: rect.maxY), control1: CGPoint(x: rect.midX, y: rect.minY), control2: CGPoint(x: rect.midX - 124, y: rect.minY)) 19 | 20 | 21 | return path 22 | } 23 | } 24 | 25 | struct RounedTriangle_Previews: PreviewProvider { 26 | static var previews: some View { 27 | RoundedTriangle() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/LoginView/Support Shapes/ShrinkingPlus.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShrinkingPlus.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 24/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ShrinkingPlus: View { 12 | 13 | // MARK:- variables 14 | let position: PlusPosition 15 | let animationDuration: TimeInterval = 0.4 16 | 17 | @State var rotationDegree: Angle = Angle.degrees(0) 18 | @State var scale: CGFloat = 0 19 | 20 | // MARK:- views 21 | var body: some View { 22 | Plus() 23 | .stroke(style: StrokeStyle(lineWidth: 6, lineCap: .round)) 24 | .foregroundColor(position.color) 25 | .rotationEffect(rotationDegree) 26 | .scaleEffect(scale) 27 | .opacity(position.opacity) 28 | .onAppear() { 29 | self.scale = position.scale 30 | self.rotationDegree = position.degree 31 | animatePlus() 32 | Timer.scheduledTimer(withTimeInterval: position.delay * 20, repeats: true) { _ in 33 | animatePlus() 34 | } 35 | } 36 | } 37 | 38 | // MARK:- functions 39 | func animatePlus() { 40 | Timer.scheduledTimer(withTimeInterval: position.delay, repeats: false) { _ in 41 | withAnimation(Animation.easeOut(duration: animationDuration)) { 42 | rotationDegree = (position.degree) 43 | } 44 | withAnimation(Animation.easeOut(duration: animationDuration).delay(animationDuration / 4)) { 45 | scale = 0 46 | } 47 | 48 | Timer.scheduledTimer(withTimeInterval: position.delay * 3, repeats: false) { _ in 49 | withAnimation(Animation.easeOut(duration: animationDuration)) { 50 | rotationDegree = .degrees(0) 51 | } 52 | withAnimation(Animation.easeOut(duration: animationDuration).delay(animationDuration / 4)) { 53 | scale = position.scale 54 | } 55 | } 56 | } 57 | } 58 | } 59 | 60 | struct ShrinkingPlus_Previews: PreviewProvider { 61 | static var previews: some View { 62 | ZStack { 63 | Color.black 64 | .edgesIgnoringSafeArea(.all) 65 | ShrinkingPlus(position: PlusPosition(id: 0, color: Color.white, offsetX: -92, offsetY: -100, delay: 0.2, scale: 0.8, opacity: 1, degree: Angle(degrees: 43))) 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/LoginView/Support Shapes/SwiftUIView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUIView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 24/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct SwiftUIView: View { 12 | var body: some View { 13 | ZStack { 14 | Color.black 15 | .edgesIgnoringSafeArea(.all) 16 | 17 | 18 | } 19 | } 20 | } 21 | 22 | struct SwiftUIView_Previews: PreviewProvider { 23 | static var previews: some View { 24 | SwiftUIView() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Octocat-Wink/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Code/Animations/Octocat-Wink/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Octocat-Wink/Support Shapes/OctoHead.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OctoHead.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 12/10/21. 6 | // Copyright © 2021 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct OctoHead: Shape { 12 | 13 | // MARK:- functions 14 | func path(in rect: CGRect) -> Path { 15 | let cX: CGFloat = rect.midX 16 | let cY: CGFloat = rect.midY 17 | 18 | var path = Path() 19 | 20 | path.move(to: CGPoint(x: cX + -41.87, y: cY + -63.23)) 21 | path.addCurve(to: CGPoint(x: cX + 43.23, y: cY + -63.46), control1: CGPoint(x: cX + -7.92, y: cY + -60.68), control2: CGPoint(x: cX + 7.6, y: cY + -60.73)) 22 | path.addCurve(to: CGPoint(x: cX + 87.78, y: cY + -63.5), control1: CGPoint(x: cX + 57.7, y: cY + -64.55), control2: CGPoint(x: cX + 81.18, y: cY + -64.59)) 23 | path.addCurve(to: CGPoint(x: cX + 122, y: cY + -46.71), control1: CGPoint(x: cX + 103.39, y: cY + -61), control2: CGPoint(x: cX + 112.85, y: cY + -56.31)) 24 | path.addLine(to: CGPoint(x: cX + 122.28, y: cY + -46.42)) 25 | path.addCurve(to: CGPoint(x: cX + 139.09, y: cY + -14.8), control1: CGPoint(x: cX + 130.74, y: cY + -37.66), control2: CGPoint(x: cX + 136.56, y: cY + -26.71)) 26 | path.addCurve(to: CGPoint(x: cX + 139.75, y: cY + 13.04), control1: CGPoint(x: cX + 140.43, y: cY + -8.71), control2: CGPoint(x: cX + 140.7, y: cY + 4.67)) 27 | path.addCurve(to: CGPoint(x: cX + 119.68, y: cY + 58.59), control1: CGPoint(x: cX + 137.38, y: cY + 33.15), control2: CGPoint(x: cX + 131.33, y: cY + 46.94)) 28 | path.addCurve(to: CGPoint(x: cX + 46.64, y: cY + 85.85), control1: CGPoint(x: cX + 104.53, y: cY + 73.75), control2: CGPoint(x: cX + 81.32, y: cY + 82.44)) 29 | path.addCurve(to: CGPoint(x: cX + -0, y: cY + 87.63), control1: CGPoint(x: cX + 32.08, y: cY + 87.31), control2: CGPoint(x: cX + 23.53, y: cY + 87.63)) 30 | path.addCurve(to: CGPoint(x: cX + -47.87, y: cY + 85.85), control1: CGPoint(x: cX + -23.71, y: cY + 87.63), control2: CGPoint(x: cX + -33.54, y: cY + 87.26)) 31 | path.addCurve(to: CGPoint(x: cX + -141.76, y: cY + 12.5), control1: CGPoint(x: cX + -108.09, y: cY + 79.8), control2: CGPoint(x: cX + -136.94, y: cY + 57.27)) 32 | path.addCurve(to: CGPoint(x: cX + -140.94, y: cY + -15.4), control1: CGPoint(x: cX + -142.58, y: cY + 5.04), control2: CGPoint(x: cX + -142.12, y: cY + -10.34)) 33 | path.addLine(to: CGPoint(x: cX + -140.89, y: cY + -15.61)) 34 | path.addCurve(to: CGPoint(x: cX + -131.37, y: cY + -37.52), control1: CGPoint(x: cX + -139.09, y: cY + -23.44), control2: CGPoint(x: cX + -135.86, y: cY + -30.86)) 35 | path.addCurve(to: CGPoint(x: cX + -113.96, y: cY + -55.13), control1: CGPoint(x: cX + -127.56, y: cY + -43.34), control2: CGPoint(x: cX + -118.87, y: cY + -52.13)) 36 | path.addCurve(to: CGPoint(x: cX + -87.24, y: cY + -63.82), control1: CGPoint(x: cX + -106.72, y: cY + -59.59), control2: CGPoint(x: cX + -97.85, y: cY + -62.5)) 37 | path.addCurve(to: CGPoint(x: cX + -41.87, y: cY + -63.23), control1: CGPoint(x: cX + -80.1, y: cY + -64.73), control2: CGPoint(x: cX + -58.35, y: cY + -64.46)) 38 | path.addLine(to: CGPoint(x: cX + -41.87, y: cY + -63.23)) 39 | 40 | path.closeSubpath() 41 | return path 42 | } 43 | } 44 | 45 | struct OctoHead_Previews: PreviewProvider { 46 | static var previews: some View { 47 | OctoHead() 48 | .stroke(lineWidth: 12) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Octocat-Wink/Support Shapes/OctocatLoader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OctocatLoader.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 12/10/21. 6 | // Copyright © 2021 Shubham Singh. All rights reserved. 7 | // 8 | import SwiftUI 9 | 10 | struct OctocatShape: Shape { 11 | 12 | // MARK:- variables 13 | 14 | // MARK:- functions 15 | func path(in rect: CGRect) -> Path { 16 | 17 | let cX: CGFloat = rect.midX 18 | let cY: CGFloat = rect.midY 19 | 20 | var path = Path() 21 | 22 | path.move(to: CGPoint(x: cX + 24.07, y: cY + 77.5)) 23 | 24 | /// right 25 | path.addLine(to: CGPoint(x: cX + 24.07, y: cY + 52.94)) 26 | path.addLine(to: CGPoint(x: cX + 24.06, y: cY + 53.12)) 27 | path.addCurve(to: CGPoint(x: cX + 18.14, y: cY + 36.4), control1: CGPoint(x: cX + 24.6, y: cY + 46.95), control2: CGPoint(x: cX + 22.44, y: cY + 40.85)) 28 | path.addCurve(to: CGPoint(x: cX + 58.99, y: cY + -8.06), control1: CGPoint(x: cX + 38.04, y: cY + 34.15), control2: CGPoint(x: cX + 58.99, y: cY + 26.6)) 29 | path.addLine(to: CGPoint(x: cX + 58.99, y: cY + -8.06)) 30 | path.addCurve(to: CGPoint(x: cX + 49.3, y: cY + -32.04), control1: CGPoint(x: cX + 58.99, y: cY + -17), control2: CGPoint(x: cX + 55.52, y: cY + -25.6)) 31 | path.addLine(to: CGPoint(x: cX + 49.56, y: cY + -32.1)) 32 | path.addCurve(to: CGPoint(x: cX + 48.72, y: cY + -56.2), control1: CGPoint(x: cX + 52.41, y: cY + -39.94), control2: CGPoint(x: cX + 52.11, y: cY + -48.58)) 33 | path.addCurve(to: CGPoint(x: cX + 24.08, y: cY + -46.4), control1: CGPoint(x: cX + 48.9, y: cY + -55.79), control2: CGPoint(x: cX + 41.41, y: cY + -58.02)) 34 | 35 | 36 | path.addLine(to: CGPoint(x: cX + 23.84, y: cY + -46.46)) 37 | 38 | /// top 39 | path.addCurve(to: CGPoint(x: cX + -20.12, y: cY + -46.46), control1: CGPoint(x: cX + 9.44, y: cY + -50.32), control2: CGPoint(x: cX + -5.72, y: cY + -50.32)) 40 | 41 | 42 | // left 43 | path.addCurve(to: CGPoint(x: cX + -45.17, y: cY + -55.79), control1: CGPoint(x: cX + -37.69, y: cY + -58.01), control2: CGPoint(x: cX + -45.11, y: cY + -55.79)) 44 | path.addLine(to: CGPoint(x: cX + -45.22, y: cY + -55.69)) 45 | path.addCurve(to: CGPoint(x: cX + -45.64, y: cY + -31.58), control1: CGPoint(x: cX + -48.48, y: cY + -48.01), control2: CGPoint(x: cX + -48.63, y: cY + -39.37)) 46 | path.addLine(to: CGPoint(x: cX + -45.58, y: cY + -32.04)) 47 | path.addCurve(to: CGPoint(x: cX + -55.27, y: cY + -8.05), control1: CGPoint(x: cX + -51.79, y: cY + -25.6), control2: CGPoint(x: cX + -55.27, y: cY + -17)) 48 | path.addCurve(to: CGPoint(x: cX + -14.39, y: cY + 36.56), control1: CGPoint(x: cX + -55.27, y: cY + 26.53), control2: CGPoint(x: cX + -34.32, y: cY + 34.09)) 49 | path.addLine(to: CGPoint(x: cX + -14.4, y: cY + 36.58)) 50 | path.addCurve(to: CGPoint(x: cX + -20.36, y: cY + 52.93), control1: CGPoint(x: cX + -18.62, y: cY + 40.94), control2: CGPoint(x: cX + -20.78, y: cY + 46.88)) 51 | path.addLine(to: CGPoint(x: cX + -20.36, y: cY + 77.5)) 52 | 53 | 54 | // tail 55 | path.move(to: CGPoint(x: cX + -20.36, y: cY + 58.46)) 56 | path.addCurve (to: CGPoint(x: cX + -64.79, y: cY + 39.42), control1: CGPoint(x: cX + -52.09, y: cY + 67.98), control2: CGPoint(x: cX + -52.09, y: cY + 42.59)) 57 | 58 | 59 | return path 60 | } 61 | } 62 | 63 | struct OctocatShape_Previews: PreviewProvider { 64 | static var previews: some View { 65 | ZStack{ 66 | Color.black 67 | .edgesIgnoringSafeArea(.all) 68 | OctocatShape() 69 | // .trim(from: 0, to: 0.2) 70 | .stroke(style: StrokeStyle(lineWidth: 4, lineCap: .round, lineJoin: .round, miterLimit: 8)) 71 | .foregroundColor(Color.white) 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/PillLoader/PillLoader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PillLoader.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 11/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct PillLoader: View { 12 | 13 | // MARK:- variables 14 | let trackerRotation: Double = 1.5 15 | let animationDuration: Double = 3 16 | let backgroundColor: LinearGradient = LinearGradient(gradient: Gradient(colors: [Color.blue.opacity(0.4), Color.purple.opacity(0.3)]), startPoint: .topLeading, endPoint: .bottom) 17 | 18 | @State var isAnimating: Bool = false 19 | @State var hideCapsule: Bool = false 20 | @State var fillCapsule: Bool = false 21 | 22 | @State private var time: CGFloat = 0.5 23 | 24 | // MARK:- views 25 | var body: some View { 26 | ZStack { 27 | backgroundColor 28 | .edgesIgnoringSafeArea(.all) 29 | ZStack { 30 | PillsDropView(isAnimating: $hideCapsule) 31 | .opacity(self.hideCapsule ? 1 : 0) 32 | // Outer container 33 | Capsule(style: .circular) 34 | .stroke(style: StrokeStyle(lineWidth: 10)) 35 | .foregroundColor(Color.white) 36 | .shadow(color: Color.white.opacity(0.1), radius: 1) 37 | 38 | FillShapes(xOffset: -45, yOffset: -100, capsuleSpacing: 40) 39 | 40 | // Line 41 | Color.white 42 | .frame(height: 6, alignment: .center) 43 | 44 | // Initial Half Capsule 45 | Capsule(style: .circular) 46 | .trim(from: 0, to: 0.5) 47 | .foregroundColor(Color.pillColor) 48 | .padding(5.5) 49 | .padding(.top, 6) 50 | .opacity(self.hideCapsule ? 0 : 1) 51 | FillShapes(xOffset: 45, yOffset: 100, capsuleSpacing: -40) 52 | 53 | // Filling Capsule 54 | ZStack { 55 | WaveFill(curve: time * 0.25, curveHeight: 10, curveLength: 1.5) 56 | .fill(Color.pillColor.opacity(0.985)) 57 | .offset(y: self.fillCapsule ? 0 : 180) 58 | WaveFill(curve: time * 5, curveHeight: 12, curveLength: 1.5) 59 | .fill(Color.pillColor.opacity(0.9)) 60 | .offset(y: self.fillCapsule ? 0 : 180) 61 | FillShapes(xOffset: 45, yOffset: 100, capsuleSpacing: -40) 62 | } 63 | .rotationEffect(.degrees(180)) 64 | .opacity(self.hideCapsule ? 1 : 0) 65 | .mask( 66 | Capsule(style: .circular) 67 | .trim(from: 0.5, to: 1) 68 | .foregroundColor(Color.red) 69 | .padding(5.5) 70 | .padding(.bottom, 8) 71 | 72 | ) 73 | } 74 | .frame(width: 140, height: 360) 75 | .rotationEffect(self.isAnimating ? getRotationAngle() : .degrees(0)) 76 | }.onAppear() { 77 | self.animateLoader() 78 | Timer.scheduledTimer(withTimeInterval: (self.animationDuration * self.trackerRotation) * 3.75, repeats: true) { _ in 79 | self.animateLoader() 80 | } 81 | } 82 | } 83 | 84 | // MARK:- functions 85 | func getRotationAngle() -> Angle { 86 | return .degrees(360 * self.trackerRotation) 87 | } 88 | 89 | func animateLoader() { 90 | withAnimation(Animation.interactiveSpring(response: self.animationDuration * self.trackerRotation, dampingFraction: 1, blendDuration: 1)) { 91 | self.isAnimating.toggle() 92 | } 93 | Timer.scheduledTimer(withTimeInterval: (self.animationDuration * self.trackerRotation) - 0.25, repeats: false) { _ in 94 | withAnimation(Animation.easeOut(duration: self.animationDuration / 2)) { 95 | self.hideCapsule.toggle() 96 | } 97 | withAnimation(Animation.easeIn(duration: self.animationDuration * 1.85).delay(0.05)) { 98 | self.fillCapsule.toggle() 99 | } 100 | Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { curveTimer in 101 | if (self.hideCapsule) { 102 | self.time += 0.01 103 | } else { 104 | curveTimer.invalidate() 105 | } 106 | } 107 | } 108 | Timer.scheduledTimer(withTimeInterval: (self.animationDuration * self.trackerRotation) * 2.5, repeats: false) { (_) in 109 | self.hideCapsule.toggle() 110 | self.isAnimating.toggle() 111 | self.fillCapsule.toggle() 112 | self.time = 0.5 113 | } 114 | } 115 | } 116 | 117 | struct PillLoader_Previews: PreviewProvider { 118 | static var previews: some View { 119 | PillLoader() 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/PillLoader/Support Shapes/FillShapes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FillShapes.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 11/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct FillShapes: View { 12 | 13 | // MARK:- variables 14 | @State var xOffset: CGFloat 15 | @State var yOffset: CGFloat 16 | 17 | @State var capsuleSpacing: CGFloat 18 | 19 | // MARK:- views 20 | var body: some View { 21 | ZStack { 22 | Circle() 23 | .frame(width: 20, height: 20) 24 | .foregroundColor(Color.white.opacity(0.55)) 25 | .shadow(color: .white, radius: 10, x: 1, y: 1) 26 | .offset(x: xOffset, y: yOffset) 27 | 28 | Capsule(style: .continuous) 29 | .frame(width: 20, height: 40) 30 | .foregroundColor(Color.white.opacity(0.55)) 31 | .shadow(color: .white, radius: 10, x: 1, y: 1) 32 | .offset(x: xOffset, y: yOffset + capsuleSpacing) 33 | 34 | } 35 | } 36 | } 37 | 38 | struct HalfCapsuleFill_Previews: PreviewProvider { 39 | static var previews: some View { 40 | ZStack{ 41 | Color.blue 42 | .edgesIgnoringSafeArea(.all) 43 | FillShapes(xOffset: -45, yOffset: -10, capsuleSpacing: 40) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/PillLoader/Support Shapes/Pill 2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Circle.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 11/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Pill: View { 12 | 13 | // MARK:- variables 14 | let width: CGFloat = 40 15 | let height: CGFloat = 40 16 | 17 | let initialOffset: CGSize 18 | let animationOffset: CGSize 19 | 20 | let animationDuration: TimeInterval = 0.1 21 | let animationDelay: TimeInterval 22 | 23 | @Binding var isAnimating: Bool 24 | 25 | // MARK:- views 26 | var body: some View { 27 | Circle() 28 | .foregroundColor(Color.pillColor) 29 | .frame(width: width, height: height) 30 | .offset(self.isAnimating ? animationOffset : initialOffset) 31 | .animation(Animation.interpolatingSpring(stiffness: 0.5, damping: 1) .delay(animationDelay)) 32 | } 33 | } 34 | 35 | struct Circle_Previews: PreviewProvider { 36 | static var previews: some View { 37 | Pill(initialOffset: CGSize(width: 0, height: 0), animationOffset: CGSize(width: 40, height: 40), animationDelay: 0.1, isAnimating: .constant(true)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/PillLoader/Support Shapes/Pill.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Circle.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 11/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Pill: View { 12 | 13 | // MARK:- variables 14 | let width: CGFloat = 40 15 | let height: CGFloat = 40 16 | 17 | let initialOffset: CGSize 18 | let animationOffset: CGSize 19 | 20 | let animationDuration: TimeInterval = 0.075 21 | let animationDelay: TimeInterval 22 | 23 | @Binding var isAnimating: Bool 24 | 25 | // MARK:- views 26 | var body: some View { 27 | Circle() 28 | .foregroundColor(Color.pillColor) 29 | .frame(width: width, height: height) 30 | .offset(self.isAnimating ? animationOffset : initialOffset) 31 | .animation(Animation.spring() 32 | .speed(1.35) 33 | .delay(self.animationDelay)) 34 | } 35 | } 36 | 37 | struct Circle_Previews: PreviewProvider { 38 | static var previews: some View { 39 | Pill(initialOffset: CGSize(width: 0, height: 0), animationOffset: CGSize(width: 40, height: 40), animationDelay: 0.1, isAnimating: .constant(true)) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/PillLoader/Support Shapes/PillGroupView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PillDrop.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 11/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct PillGroupView: View { 12 | 13 | // MARK:- variables 14 | @Binding var isAnimating: Bool 15 | 16 | let initialOffSet: CGSize 17 | let animationOffset: Double 18 | 19 | // MARK:- views 20 | var body: some View { 21 | ZStack { 22 | Pill(initialOffset: CGSize(width: initialOffSet.width + 45, height: initialOffSet.height + 125), animationOffset: CGSize(width: initialOffSet.width + -20, height: -150), animationDelay: animationOffset, isAnimating: $isAnimating) 23 | Pill(initialOffset: CGSize(width: initialOffSet.width + -45, height: initialOffSet.height + 118), animationOffset: CGSize(width: initialOffSet.width + -20, height: -145), animationDelay: animationOffset + 0.05, isAnimating: $isAnimating) 24 | Pill(initialOffset: CGSize(width: initialOffSet.width + 10, height: initialOffSet.height + 124), animationOffset: CGSize(width: initialOffSet.width + -20, height: -150), animationDelay: animationOffset + 0.1, isAnimating: $isAnimating) 25 | Pill(initialOffset: CGSize(width: initialOffSet.width + -10, height: initialOffSet.height + 125), animationOffset: CGSize(width: initialOffSet.width , height:-145), animationDelay: animationOffset + 0.15, isAnimating: $isAnimating) 26 | 27 | Pill(initialOffset: CGSize(width: initialOffSet.width + -30, height: initialOffSet.height + 145), animationOffset: CGSize(width: initialOffSet.width + +10, height: -157.5), animationDelay: animationOffset + 0.2, isAnimating: $isAnimating) 28 | Pill(initialOffset: CGSize(width: initialOffSet.width + -40, height: initialOffSet.height + 135), animationOffset: CGSize(width: initialOffSet.width + -20, height: -145), animationDelay: animationOffset + 0.25, isAnimating: $isAnimating) 29 | 30 | Pill(initialOffset: CGSize(width: initialOffSet.width + 40, height: initialOffSet.height + 140), animationOffset: CGSize(width: initialOffSet.width + -10, height: -120), animationDelay: animationOffset + 0.3, isAnimating: $isAnimating) 31 | Pill(initialOffset: CGSize(width: initialOffSet.width + 25, height: initialOffSet.height + 155), animationOffset: CGSize(width: initialOffSet.width + -30, height: -125), animationDelay: animationOffset + 0.35, isAnimating: $isAnimating) 32 | Pill(initialOffset: CGSize(width: initialOffSet.width, height: initialOffSet.height + 160), animationOffset: CGSize(width: initialOffSet.width + 20, height: -155), animationDelay: animationOffset + 0.4, isAnimating: $isAnimating) 33 | Pill(initialOffset: CGSize(width: initialOffSet.width + -20, height: initialOffSet.height + 155), animationOffset: CGSize(width: initialOffSet.width , height: -125), animationDelay: animationOffset + 0.45, isAnimating: $isAnimating) 34 | } 35 | } 36 | } 37 | 38 | struct PillDrop_Previews: PreviewProvider { 39 | static var previews: some View { 40 | ZStack { 41 | Color.black 42 | .edgesIgnoringSafeArea(.all) 43 | ZStack { 44 | PillGroupView(isAnimating: .constant(false), initialOffSet: CGSize(width: 0, height: 0), animationOffset: 0.1) 45 | Capsule(style: .circular) 46 | .stroke(style: StrokeStyle(lineWidth: 10)) 47 | .foregroundColor(.white) 48 | Color.white 49 | .frame(height: 6, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/) 50 | } 51 | .frame(width: 140, height: 360) 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/PillLoader/Support Shapes/PillsDropView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PillDropView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 11/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct PillsDropView: View { 12 | 13 | // MARK:- variables 14 | @Binding var isAnimating: Bool 15 | 16 | // MARK:- views 17 | var body: some View { 18 | ZStack { 19 | PillGroupView(isAnimating: $isAnimating, initialOffSet: CGSize(width: 0, height: 0), animationOffset: 0.05) 20 | PillGroupView(isAnimating: $isAnimating, initialOffSet: CGSize(width: 10, height: -45), animationOffset: 0.05) 21 | PillGroupView(isAnimating: $isAnimating, initialOffSet: CGSize(width: -10, height: -99.5), animationOffset: 0.025) 22 | } 23 | } 24 | } 25 | 26 | struct PillDropView_Previews: PreviewProvider { 27 | static var previews: some View { 28 | PillsDropView(isAnimating: .constant(false)) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/PillLoader/Support Shapes/WaveFill.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WaveFill.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 11/09/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct WaveFill: Shape { 12 | 13 | // MARK:- variables 14 | var curve: CGFloat 15 | let curveHeight: CGFloat 16 | let curveLength: CGFloat 17 | 18 | // MARK:- functions 19 | func path(in rect: CGRect) -> Path { 20 | var path = Path() 21 | path.move(to: CGPoint(x: rect.width, y: rect.height * 2)) 22 | path.addLine(to: CGPoint(x: 0, y: rect.height * 2)) 23 | 24 | for i in stride(from: 0, to: CGFloat(rect.width), by: 1) { 25 | path.addLine(to: CGPoint(x: i, y: sin(((i / rect.height) + curve) * curveLength * .pi) * curveHeight + rect.midY)) 26 | } 27 | path.addLine(to: CGPoint(x: rect.width, y: rect.height * 2)) 28 | return path 29 | } 30 | } 31 | 32 | 33 | 34 | struct WaveFill_Previews: PreviewProvider { 35 | static var previews: some View { 36 | WaveFill(curve: 1, curveHeight: 4, curveLength: 3) 37 | .fill(Color.orange.opacity(0.5)) 38 | .opacity(0.5) 39 | .frame(width: 200, height: 100) 40 | .offset(y: 140) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/SpinningLoader/SpinningView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SpinningView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 05/03/21. 6 | // Copyright © 2021 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct SpinningView: View { 12 | 13 | // MARK:- variables 14 | @State var circleEnd: CGFloat = 0.001 15 | @State var smallerCircleEnd: CGFloat = 1 16 | 17 | @State var rotationDegree: Angle = Angle.degrees(-90) 18 | @State var smallerRotationDegree: Angle = Angle.degrees(-30) 19 | 20 | let trackerRotation: Double = 1 21 | let animationDuration: Double = 1.35 22 | 23 | // MARK:- views 24 | var body: some View { 25 | ZStack { 26 | Color.black 27 | .edgesIgnoringSafeArea(.all) 28 | ZStack { 29 | Circle() 30 | .trim(from: 0, to: circleEnd) 31 | .stroke(style: StrokeStyle(lineWidth: 18, lineCap: .round)) 32 | .fill(Color.white) 33 | .rotationEffect(self.rotationDegree) 34 | .frame(width: 130, height: 130) 35 | Circle() 36 | .trim(from: 0, to: smallerCircleEnd) 37 | .stroke(style: StrokeStyle(lineWidth: 18, lineCap: .round)) 38 | .fill(Color.white.opacity(0.9)) 39 | .rotationEffect(self.smallerRotationDegree) 40 | .frame(width: 48, height: 48 ) 41 | }.offset(y: -48) 42 | Text("@shubham_iosdev") 43 | .foregroundColor(.white) 44 | .font(.system(size: 20, weight: .medium, design: .monospaced)) 45 | .opacity(0.7) 46 | .offset(x: 96, y: 380) 47 | .onAppear() { 48 | animate() 49 | Timer.scheduledTimer(withTimeInterval: animationDuration * 1.98, repeats: true) { _ in 50 | reset() 51 | animate() 52 | } 53 | } 54 | } 55 | } 56 | 57 | // MARK:- functions 58 | func animate() { 59 | withAnimation(Animation.easeOut(duration: animationDuration)) { 60 | self.circleEnd = 1 61 | } 62 | withAnimation(Animation.easeOut(duration: animationDuration * 1.1)) { 63 | self.rotationDegree = RotationDegrees.initialCicle.getRotationDegrees() 64 | } 65 | 66 | /// smaller circle 67 | withAnimation(Animation.easeOut(duration: animationDuration * 0.85)) { 68 | self.smallerCircleEnd = 0.001 69 | self.smallerRotationDegree = RotationDegrees.initialSmallCircle.getRotationDegrees() 70 | } 71 | 72 | 73 | Timer.scheduledTimer(withTimeInterval: animationDuration * 0.7, repeats: false) { _ in 74 | withAnimation(Animation.easeIn(duration: animationDuration * 0.4)) { 75 | self.smallerRotationDegree = RotationDegrees.middleSmallCircle.getRotationDegrees() 76 | self.rotationDegree = RotationDegrees.middleCircle.getRotationDegrees() 77 | } 78 | } 79 | 80 | Timer.scheduledTimer(withTimeInterval: animationDuration, repeats: false) { _ in 81 | withAnimation(Animation.easeOut(duration: animationDuration)) { 82 | self.rotationDegree = RotationDegrees.last.getRotationDegrees() 83 | self.circleEnd = 0.001 84 | } 85 | 86 | /// smaller circle 87 | withAnimation(Animation.linear(duration: animationDuration * 0.8)) { 88 | self.smallerCircleEnd = 1 89 | self.smallerRotationDegree = RotationDegrees.last.getRotationDegrees() 90 | } 91 | } 92 | } 93 | 94 | func reset() { 95 | self.rotationDegree = .degrees(-90) 96 | self.smallerRotationDegree = Angle.degrees(-30) 97 | } 98 | } 99 | 100 | struct SpinningView_Previews: PreviewProvider { 101 | static var previews: some View { 102 | ZStack { 103 | SpinningView() 104 | } 105 | } 106 | } 107 | 108 | 109 | enum RotationDegrees { 110 | case initialCicle 111 | case initialSmallCircle 112 | 113 | case middleCircle 114 | case middleSmallCircle 115 | 116 | case last 117 | 118 | func getRotationDegrees() -> Angle { 119 | switch self { 120 | case .initialCicle: 121 | return .degrees(365) 122 | case .initialSmallCircle: 123 | return .degrees(679) 124 | 125 | case .middleCircle: 126 | return .degrees(375) 127 | case .middleSmallCircle: 128 | return .degrees(825) 129 | 130 | case .last: 131 | return .degrees(990) 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/SubmitView/SubmitView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubmitView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 07/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct SubmitView: View { 12 | 13 | // MARK:- variables 14 | let animationDuration: TimeInterval = 0.45 15 | let trackerRotation: Double = 2.585 16 | 17 | @State var isAnimating: Bool = false 18 | @State var taskDone: Bool = false 19 | 20 | @State var submitScale: CGFloat = 1 21 | 22 | // MARK:- views 23 | var body: some View { 24 | ZStack { 25 | Color.black 26 | .edgesIgnoringSafeArea(.all) 27 | ZStack { 28 | RoundedRectangle(cornerRadius: self.isAnimating ? 46 : 20, style: .circular) 29 | .fill(Color.submitColor) 30 | .frame(width: self.isAnimating ? 92 : 300, height: 92) 31 | .scaleEffect(submitScale, anchor: .center) 32 | .onTapGesture { 33 | if (!self.isAnimating) { 34 | HapticManager().makeSelectionFeedback() 35 | toggleIsAnimating() 36 | animateButton() 37 | resetSubmit() 38 | Timer.scheduledTimer(withTimeInterval: trackerRotation * 0.95, repeats: false) { _ in 39 | self.taskDone.toggle() 40 | } 41 | } 42 | } 43 | if (self.isAnimating) { 44 | RotatingCircle(trackerRotation: trackerRotation, timerInterval: trackerRotation * 0.91) 45 | } 46 | Tick(scaleFactor: 0.4) 47 | .trim(from: 0, to: self.taskDone ? 1 : 0) 48 | .stroke(style: StrokeStyle(lineWidth: 5, lineCap: .round)) 49 | .foregroundColor(Color.white) 50 | .frame(width: 16) 51 | .offset(x: -4, y: 4) 52 | .animation(.easeOut(duration: 0.35)) 53 | Text("Submit") 54 | .font(.system(size: 32, weight: .bold, design: .monospaced)) 55 | .foregroundColor(Color.white) 56 | .opacity(self.isAnimating ? 0 : 1) 57 | .animation(Animation.easeOut(duration: animationDuration)) 58 | .scaleEffect(self.isAnimating ? 0.7 : 1) 59 | .animation(Animation.easeOut(duration: animationDuration)) 60 | } 61 | } 62 | } 63 | 64 | // MARK:- functions 65 | func animateButton() { 66 | expandButton() 67 | Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in 68 | expandButton() 69 | } 70 | Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in 71 | expandButton() 72 | } } 73 | 74 | func expandButton() { 75 | withAnimation(Animation.linear(duration: 0.5)) { 76 | self.submitScale = 1.35 77 | } 78 | withAnimation(Animation.linear(duration: 0.5).delay(0.5)) { 79 | self.submitScale = 1 80 | } 81 | } 82 | 83 | func resetSubmit() { 84 | Timer.scheduledTimer(withTimeInterval: trackerRotation * 0.95 + animationDuration * 3.5, repeats: false) { _ in 85 | toggleIsAnimating() 86 | self.taskDone.toggle() 87 | } 88 | } 89 | 90 | func toggleIsAnimating() { 91 | withAnimation(Animation.spring(response: animationDuration * 1.25, dampingFraction: 0.9, blendDuration: 1)){ 92 | self.isAnimating.toggle() 93 | } 94 | } 95 | } 96 | 97 | struct SubmitView_Previews: PreviewProvider { 98 | static var previews: some View { 99 | SubmitView() 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/SubmitView/Support Shapes/RotatingCircle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RotatingCircle.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 07/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct RotatingCircle: View { 12 | 13 | // MARK:- variables 14 | @State var isAnimating: Bool = false 15 | @State var rotationAngle: Angle = .degrees(0) 16 | @State var circleScale: CGFloat = 0.5 17 | @State var xOffset: CGFloat = 30 18 | @State var yOffSet: CGFloat = 0 19 | @State var opacity: Double = 1 20 | 21 | let trackerRotation: Double 22 | let timerInterval: TimeInterval 23 | 24 | // MARK:- views 25 | var body: some View { 26 | Circle() 27 | .fill(Color.white) 28 | .frame(width: 40) 29 | .offset(x: xOffset, y: yOffSet) 30 | .rotationEffect(rotationAngle) 31 | .scaleEffect(circleScale) 32 | .opacity(opacity) 33 | .onAppear() { 34 | // Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in 35 | withAnimation(Animation.easeOut(duration: 0.2)) { 36 | self.circleScale = 1 37 | self.xOffset = 130 38 | } 39 | withAnimation(Animation.linear(duration: timerInterval)) { 40 | self.rotationAngle = getRotationAngle() 41 | } 42 | Timer.scheduledTimer(withTimeInterval: timerInterval, repeats: false) { _ in 43 | withAnimation(Animation.easeOut(duration: 0.2)) { 44 | self.circleScale = 0.25 45 | self.xOffset = 60 46 | self.yOffSet = -40 47 | } 48 | } 49 | Timer.scheduledTimer(withTimeInterval: timerInterval + 0.05, repeats: false) { _ in 50 | withAnimation(Animation.default) { 51 | self.opacity = 0 52 | } 53 | } 54 | } 55 | // } 56 | } 57 | 58 | // MARK:- functions 59 | func getRotationAngle() -> Angle { 60 | return .degrees(360 * self.trackerRotation) 61 | } 62 | } 63 | 64 | struct RotatingCircle_Previews: PreviewProvider { 65 | static var previews: some View { 66 | ZStack { 67 | Color.black 68 | .edgesIgnoringSafeArea(.all) 69 | RotatingCircle(trackerRotation: 2.4, timerInterval: 2.4 * 0.91) 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/TriangleLoader/Support/TriangleShape.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TriangleShape.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 14/09/21. 6 | // Copyright © 2021 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct TriangleShape: Shape { 12 | func path(in rect: CGRect) -> Path { 13 | var path = Path() 14 | 15 | path.move(to: CGPoint(x: rect.midX, y: rect.minY)) 16 | path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY * 0.85)) 17 | path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY * 0.85)) 18 | path.addLine(to: CGPoint(x: rect.midX, y: rect.minY)) 19 | path.move(to: CGPoint(x: rect.midX, y: rect.minY)) 20 | path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY * 0.85)) 21 | path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY * 0.85)) 22 | path.addLine(to: CGPoint(x: rect.midX, y: rect.minY)) 23 | return path 24 | } 25 | } 26 | 27 | struct TriangleShape_Previews: PreviewProvider { 28 | static var previews: some View { 29 | TriangleShape() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/TriangleLoader/TriangleLoader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TriangleLoader.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 13/09/21. 6 | // Copyright © 2021 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | enum TriangleState { 12 | case begin 13 | case phaseOne 14 | case phaseTwo 15 | case stop 16 | 17 | func getStrokes() -> (CGFloat, CGFloat) { 18 | switch self { 19 | case .begin: 20 | return (0.335, 0.665) 21 | case .phaseOne: 22 | return (0.5, 0.825) 23 | case .phaseTwo: 24 | return (0.675, 1) 25 | case .stop: 26 | return (0.175, 0.5) 27 | } 28 | } 29 | 30 | func getCircleOffset() -> (CGFloat, CGFloat) { 31 | switch self { 32 | /// you'll have to change the offset values here if you want to increase/decrease the size of the circle 33 | case .begin: 34 | return (0, 35) 35 | case .phaseOne: 36 | return (30, -5) 37 | case .phaseTwo: 38 | return (-30, -5) 39 | case .stop: 40 | return (-30, 0) 41 | } 42 | } 43 | } 44 | 45 | struct TriangleLoader: View { 46 | 47 | // MARK:- variables 48 | @State var strokeStart: CGFloat = 0 49 | @State var strokeEnd: CGFloat = 0 50 | 51 | @State var circleOffset: CGSize = CGSize(width: 0, height: 0) 52 | 53 | let animationDuration: TimeInterval = 0.7 54 | var circleColor: Color = Color.blue 55 | 56 | // MARK:- views 57 | var body: some View { 58 | ZStack { 59 | Color.background 60 | .edgesIgnoringSafeArea(.all) 61 | ZStack { 62 | TriangleShape() 63 | .trim(from: strokeStart, to: strokeEnd) 64 | .stroke(style: StrokeStyle(lineWidth: 10, lineCap: .round, lineJoin: .round, miterLimit: 8)) 65 | Circle() 66 | .offset(circleOffset) 67 | .foregroundColor(circleColor) 68 | .frame(width: 15, height: 15) 69 | } 70 | .frame(width: 100, height: 100) 71 | .offset(y: -75) 72 | }.onAppear() { 73 | setStroke(state: .begin) 74 | setCircleOffset(state: .begin) 75 | animate() 76 | Timer.scheduledTimer(withTimeInterval: animationDuration * 4.5, repeats: true) { _ in 77 | animate() 78 | } 79 | } 80 | } 81 | 82 | // MARK:- functions 83 | func animate() { 84 | Timer.scheduledTimer(withTimeInterval: animationDuration / 2, repeats: false) { _ in 85 | withAnimation(.easeInOut(duration: animationDuration)) { 86 | setStroke(state: .phaseOne) 87 | } 88 | 89 | withAnimation(.spring(response: animationDuration * 2, dampingFraction: 0.85)) { 90 | setCircleOffset(state: .phaseOne) 91 | } 92 | } 93 | 94 | Timer.scheduledTimer(withTimeInterval: animationDuration * 2 , repeats: false) { _ in 95 | withAnimation(.easeInOut(duration: animationDuration)) { 96 | setStroke(state: .phaseTwo) 97 | } 98 | 99 | withAnimation(.spring(response: animationDuration * 2, dampingFraction: 0.85)) { 100 | setCircleOffset(state: .phaseTwo) 101 | } 102 | } 103 | 104 | Timer.scheduledTimer(withTimeInterval: animationDuration * 3.5, repeats: false) { _ in 105 | setStroke(state: .stop) 106 | 107 | withAnimation(.easeInOut(duration: animationDuration)) { 108 | setStroke(state: .begin) 109 | } 110 | 111 | withAnimation(.spring(response: animationDuration * 2, dampingFraction: 0.85)) { 112 | setCircleOffset(state: .begin) 113 | } 114 | } 115 | } 116 | 117 | func setStroke(state: TriangleState) { 118 | (self.strokeStart, self.strokeEnd) = state.getStrokes() 119 | } 120 | 121 | func setCircleOffset(state: TriangleState) { 122 | let offset = state.getCircleOffset() 123 | self.circleOffset = CGSize(width: offset.0, height: offset.1) 124 | } 125 | } 126 | 127 | struct TriangleLoader_Previews: PreviewProvider { 128 | static var previews: some View { 129 | TriangleLoader() 130 | .colorScheme(.dark) 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Wifi/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/Code/Animations/Wifi/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Wifi/ArcView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ArcView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 11/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ArcView: View { 12 | var radius: CGFloat 13 | @Binding var fillColor: Color 14 | @Binding var shadowColor: Color 15 | 16 | var body: some View { 17 | ArcShape(radius: radius) 18 | .fill(fillColor) 19 | .shadow(color: shadowColor, radius: 5) 20 | .frame(height: radius) 21 | .animation(Animation.spring().speed(0.75)) 22 | .onTapGesture { 23 | self.fillColor = Color.wifiConnected 24 | } 25 | } 26 | } 27 | 28 | struct ArcView_Previews: PreviewProvider { 29 | static var previews: some View { 30 | ZStack { 31 | Color.black 32 | ArcView(radius: 42, fillColor: .constant(Color.wifiConnected), shadowColor: .constant(Color.red)) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Wifi/CircleEmitter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Test.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 12/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct CircleEmitter: View { 12 | @Binding var isAnimating: Bool 13 | 14 | var body: some View { 15 | ForEach(0 ..< 50) { ix in 16 | Circle() 17 | .fill(Color.white.opacity(0.75)) 18 | .frame(width: 6, height: 6) 19 | .offset(x: CGFloat.random(in: -250 ..< 250), y: CGFloat.random(in: -200 ..< 250)) 20 | .scaleEffect(self.isAnimating ? 1 : 0) 21 | .animation(self.isAnimating ? Animation.easeInOut(duration: 0.125).delay(0.01 * Double(ix)): .none) 22 | } 23 | } 24 | } 25 | 26 | struct CircleEmitter_Previews: PreviewProvider { 27 | static var previews: some View { 28 | ZStack { 29 | Color.black 30 | .edgesIgnoringSafeArea(.all) 31 | CircleEmitter(isAnimating: .constant(true)) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Wifi/Support Shapes/Arc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Arc.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 11/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ArcShape : Shape { 12 | var radius: CGFloat 13 | 14 | func path(in rect: CGRect) -> Path { 15 | var p = Path() 16 | p.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: self.radius, startAngle: .degrees(220), endAngle: .degrees(320), clockwise: false) 17 | return p.strokedPath(.init(lineWidth: 6, lineCap: .round)) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/Wifi/Support Shapes/Circles.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Circles.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 12/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Circles : Shape { 12 | 13 | func path(in rect: CGRect) -> Path { 14 | 15 | var path = Path() 16 | path.move(to: rect.origin) 17 | for _ in 0 ..< 18 { 18 | let barHeight = CGFloat.random(in: 2.5 ..< 7) 19 | let barRect = CGRect(x: CGFloat.random(in: rect.minX ..< rect.midX), 20 | y: CGFloat.random(in: rect.minY ..< rect.midY), 21 | width: barHeight, 22 | height: barHeight) 23 | path.addRoundedRect(in: barRect, cornerSize: CGSize(width: barHeight / 2, height: barHeight / 2)) 24 | } 25 | for _ in 0 ..< 18 { 26 | let barHeight = CGFloat.random(in: 2.5 ..< 7) 27 | let barRect = CGRect(x: CGFloat.random(in: rect.midX ..< rect.maxX), 28 | y: CGFloat.random(in: rect.minY ..< rect.midY), 29 | width: barHeight, 30 | height: barHeight) 31 | path.addRoundedRect(in: barRect, cornerSize: CGSize(width: barHeight / 2, height: barHeight / 2)) 32 | } 33 | return path 34 | } 35 | } 36 | struct Circles_Previews: PreviewProvider { 37 | static var previews: some View { 38 | ZStack { 39 | Color.black 40 | .edgesIgnoringSafeArea(.all) 41 | Circles() 42 | .fill(Color.red) 43 | .frame(height: 300) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/YinYang-Toggle/ViewModels/YinYangViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YinYangViewModel.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 02/09/24. 6 | // Copyright © 2024 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | @Observable 12 | class YinYangViewModel { 13 | 14 | // MARK: - Variables 15 | var forTest = false 16 | var themeToggled: Bool = false 17 | 18 | 19 | // MARK: - Inits 20 | init(forTest: Bool = false) { 21 | self.forTest = forTest 22 | } 23 | 24 | 25 | // MARK: - Functions 26 | } 27 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/YinYang-Toggle/Views/Support Shapes/YinYangShape.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YinYangShape.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 02/09/24. 6 | // Copyright © 2024 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct YinYangShape: Shape { 12 | 13 | // MARK: - Functions 14 | func path(in rect: CGRect) -> Path { 15 | let cX: CGFloat = rect.midX 16 | let cY: CGFloat = rect.midY 17 | 18 | let fillColor = UIColor(red: 0.000, green: 0.000, blue: 0.000, alpha: 1.000) 19 | let fillColor2 = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1.000) 20 | //// YinYang 21 | //// g1878 22 | //// path1366 Drawing 23 | let path1366Path = UIBezierPath(ovalIn: CGRect(x: cX + -46.75, y: cY + -46.3, width: 99, height: 99)) 24 | fillColor2.setFill() 25 | path1366Path.fill() 26 | 27 | //// path1351 Drawing 28 | let bezierPath = UIBezierPath() 29 | bezierPath.move(to: CGPoint(x: cX + -0.91, y: cY + 53.13)) 30 | bezierPath.addCurve (to: CGPoint(x: cX + -46.05, y: cY + 14.33), controlPoint1: CGPoint(x: cX + -22.35, y: cY + 52.01), controlPoint2: CGPoint(x: cX + -41.66, y: cY + 35.31)) 31 | bezierPath.addCurve (to: CGPoint(x: cX + -30.04, y: cY + -34.18), controlPoint1: CGPoint(x: cX + -50.1, y: cY + -3.17), controlPoint2: CGPoint(x: cX + -43.76, y: cY + -22.55)) 32 | bezierPath.addCurve (to: CGPoint(x: cX + 5.67, y: cY + -46.14), controlPoint1: CGPoint(x: cX + -20.3, y: cY + -42.65), controlPoint2: CGPoint(x: cX + -7.22, y: cY + -47.11)) 33 | bezierPath.addCurve (to: CGPoint(x: cX + 50.27, y: cY + -10.55), controlPoint1: CGPoint(x: cX + 26.08, y: cY + -45.31), controlPoint2: CGPoint(x: cX + 44.77, y: cY + -30.18)) 34 | bezierPath.addCurve (to: CGPoint(x: cX + 51.61, y: cY + 11.83), controlPoint1: CGPoint(x: cX + 52.52, y: cY + -3.34), controlPoint2: CGPoint(x: cX + 52.52, y: cY + 4.4)) 35 | bezierPath.addCurve (to: CGPoint(x: cX + 14.98, y: cY + 51.66), controlPoint1: CGPoint(x: cX + 48.51, y: cY + 30.75), controlPoint2: CGPoint(x: cX + 33.63, y: cY + 47.08)) 36 | bezierPath.addCurve (to: CGPoint(x: cX + -0.91, y: cY + 53.13), controlPoint1: CGPoint(x: cX + 9.82, y: cY + 52.92), controlPoint2: CGPoint(x: cX + 4.39, y: cY + 53.58)) 37 | bezierPath.close() 38 | 39 | bezierPath.move(to: CGPoint(x: cX + -8.55, y: cY + 50.08)) 40 | bezierPath.addCurve (to: CGPoint(x: cX + -21.98, y: cY + 25.2), controlPoint1: CGPoint(x: cX + -17.64, y: cY + 45.61), controlPoint2: CGPoint(x: cX + -23.27, y: cY + 35.27)) 41 | bezierPath.addCurve (to: CGPoint(x: cX + 1.71, y: cY + 3.32), controlPoint1: CGPoint(x: cX + -20.94, y: cY + 13.34), controlPoint2: CGPoint(x: cX + -10.15, y: cY + 3.53)) 42 | bezierPath.addCurve (to: CGPoint(x: cX + 25.04, y: cY + -11.87), controlPoint1: CGPoint(x: cX + 11.64, y: cY + 3.62), controlPoint2: CGPoint(x: cX + 21.43, y: cY + -2.55)) 43 | bezierPath.addCurve (to: CGPoint(x: cX + 16.45, y: cY + -41.08), controlPoint1: CGPoint(x: cX + 29.36, y: cY + -22.07), controlPoint2: CGPoint(x: cX + 25.63, y: cY + -34.86)) 44 | bezierPath.addCurve (to: CGPoint(x: cX + -9.71, y: cY + -43.53), controlPoint1: CGPoint(x: cX + 8.92, y: cY + -46.63), controlPoint2: CGPoint(x: cX + -1.14, y: cY + -45.45)) 45 | bezierPath.addCurve (to: CGPoint(x: cX + -45.91, y: cY + 0.21), controlPoint1: CGPoint(x: cX + -29.5, y: cY + -38.67), controlPoint2: CGPoint(x: cX + -44.8, y: cY + -20.13)) 46 | bezierPath.addCurve (to: CGPoint(x: cX + -21.08, y: cY + 45.88), controlPoint1: CGPoint(x: cX + -47.35, y: cY + 18.57), controlPoint2: CGPoint(x: cX + -37.25, y: cY + 37.1)) 47 | bezierPath.addCurve (to: CGPoint(x: cX + -7.5, y: cY + 50.68), controlPoint1: CGPoint(x: cX + -17.03, y: cY + 48.07), controlPoint2: CGPoint(x: cX + -11.29, y: cY + 50.63)) 48 | bezierPath.addLine(to: CGPoint(x: cX + -7.92, y: cY + 50.42)) 49 | bezierPath.addLine(to: CGPoint(x: cX + -8.55, y: cY + 50.08)) 50 | bezierPath.addLine(to: CGPoint(x: cX + -8.55, y: cY + 50.08)) 51 | bezierPath.close() 52 | 53 | fillColor.setFill() 54 | bezierPath.fill() 55 | 56 | 57 | return Path(bezierPath.cgPath) 58 | } 59 | } 60 | 61 | #Preview { 62 | ZStack { 63 | Color.purple 64 | .opacity(0.1) 65 | YinYangShape() 66 | .background { 67 | Circle() 68 | .foregroundStyle(.white) 69 | .frame(width: 96, height: 96) 70 | .offset(y: 2) 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/YinYang-Toggle/Views/Support Views/YinYangToggleView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YinYangToggleView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 02/09/24. 6 | // Copyright © 2024 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct YinToggleView: View { 12 | 13 | // MARK: - Variables 14 | @Environment(YinYangViewModel.self) var yinYangViewModel 15 | @State var viewAppeared = false 16 | 17 | 18 | let animationDuration: TimeInterval = 0.75 19 | let xOffset: CGFloat = 28.5 20 | 21 | // MARK: - Views 22 | var body: some View { 23 | GeometryReader { proxy in 24 | Capsule(style: .continuous) 25 | .trim(from: 0, to: viewAppeared ? 1 : 0) 26 | .stroke(lineWidth: 3) 27 | .foregroundColor(.gray) 28 | .animation(.smooth(duration: animationDuration).delay(animationDuration * 1.25), value: viewAppeared) 29 | .overlay(alignment: .leading) { 30 | YinYangView(scale: 0.565, yYingOffset: 10, yYangOffset: 15) 31 | .offset(y: -2) 32 | .rotationEffect(yinYangViewModel.themeToggled ? .degrees(180) : .zero) 33 | .offset(x: yinYangViewModel.themeToggled ? proxy.size.width / 2 - xOffset : -proxy.size.width / 2 + xOffset) 34 | } 35 | .background { 36 | Capsule(style: .continuous) 37 | .opacity(viewAppeared ? yinYangViewModel.themeToggled ? 0.95 : 0.8 : 0) 38 | .foregroundStyle(!yinYangViewModel.themeToggled ? .black : .white) 39 | .animation(.smooth(duration: animationDuration * 1.25).delay(animationDuration * 1.5), value: viewAppeared) 40 | } 41 | .onTapGesture { 42 | withAnimation(.snappy(duration: animationDuration)) { 43 | yinYangViewModel.themeToggled.toggle() 44 | } 45 | } 46 | .onAppear() { 47 | viewAppeared.toggle() 48 | } 49 | } 50 | } 51 | } 52 | 53 | #Preview { 54 | YinToggleView() 55 | .frame(width: 140, height: 62) 56 | .environment(YinYangViewModel()) 57 | } 58 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/YinYang-Toggle/Views/Support Views/YinYangView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YinYangView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 02/09/24. 6 | // Copyright © 2024 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct YinYangView: View { 12 | 13 | // MARK: - Variables 14 | @State var viewAppeared = false 15 | 16 | var scale: CGFloat = 1 17 | var size: CGFloat = 100 18 | 19 | var yYingOffset: CGFloat = -15 20 | var yYangOffset: CGFloat = 20 21 | 22 | let animationDuration: TimeInterval = 0.5 23 | 24 | // MARK: - Views 25 | var body: some View { 26 | ZStack { 27 | YinYangShape() // initial drawing overlay 28 | .trim(from: 0, to: viewAppeared ? 1 : 0) 29 | .stroke(lineWidth: 2) 30 | .scaleEffect(scale) 31 | .animation(.easeInOut(duration: animationDuration), value: viewAppeared) 32 | .opacity(viewAppeared ? 0 : 1) 33 | .animation(.smooth(duration: animationDuration / 2).delay(animationDuration), value: viewAppeared) 34 | 35 | YinYangShape() 36 | .scaleEffect(scale) 37 | .overlay { 38 | Circle() 39 | .stroke(lineWidth: 3) 40 | .frame(width: size * scale, height: size * scale) 41 | .offset(x: 2, y: 2) 42 | } 43 | .background { // white background for the Yang Part 44 | Circle() 45 | .foregroundStyle(.white) 46 | .frame(width: size * scale, height: size * scale) 47 | .offset(y: 2) 48 | } 49 | .opacity(viewAppeared ? 1 : 0) 50 | .animation(.smooth.delay(animationDuration), value: viewAppeared) 51 | .overlay { // 52 | ZStack { 53 | Circle() 54 | .trim(from: 0, to: viewAppeared ? 1 : 0) 55 | .stroke(lineWidth: 2) 56 | .animation(.snappy.delay(animationDuration * 1.2), value: viewAppeared) 57 | Circle() 58 | .opacity(viewAppeared ? 1 : 0) 59 | .animation(.smooth.delay(animationDuration * 1.5), value: viewAppeared) 60 | } 61 | .frame(width: 11.5 * scale) 62 | .offset(y: -yYingOffset) // Change the offset if needed when you change the main Scale 63 | } 64 | .overlay { 65 | ZStack { 66 | Circle() 67 | .trim(from: 0, to: viewAppeared ? 1 : 0) 68 | .stroke(lineWidth: 2) 69 | .animation(.snappy.delay(animationDuration * 1.5), value: viewAppeared) 70 | Circle() 71 | .opacity(viewAppeared ? 1 : 0) 72 | .animation(.smooth.delay(animationDuration * 1.5), value: viewAppeared) 73 | } 74 | .foregroundColor(Color.white) 75 | .frame(width: 12 * scale) 76 | .offset(y: yYangOffset) // Change the offset if needed when you change the main Scale 77 | } 78 | } 79 | .onAppear() { 80 | viewAppeared.toggle() 81 | } 82 | } 83 | } 84 | 85 | #Preview { 86 | YinYangView(scale: 0.7, size: 100) 87 | } 88 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Animations/YinYang-Toggle/Views/YinYangAnimationView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YinYangAnimationView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham on 02/09/24. 6 | // Copyright © 2024 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct YinYangAnimationView: View { 12 | // MARK: - Variables 13 | @Environment(\.colorScheme) var colorScheme 14 | @State var yinYangViewModel: YinYangViewModel = .init() 15 | 16 | @State var viewAppeared = false 17 | 18 | let animationDuration: TimeInterval = 0.475 19 | let scale: CGFloat = 2.5 20 | 21 | 22 | // MARK: - Views 23 | var body: some View { 24 | GeometryReader { proxy in 25 | ZStack(alignment: Alignment(horizontal: .center, vertical: .center)) { 26 | GenerateViewBackground() 27 | GenerateShapeView() 28 | GenerateYinToggleView() 29 | } 30 | .overlay(alignment: .topLeading) { 31 | VStack { 32 | HStack { 33 | Text("Theme Switcher") 34 | .font(.system(size: 28, weight: .medium, design: .monospaced)) 35 | .tracking(-0.2) 36 | .padding(.top, 14) 37 | .foregroundStyle(yinYangViewModel.themeToggled ? Color.background : Color.label) 38 | 39 | Spacer() 40 | } 41 | .offset(y: viewAppeared ? 0 : 34) 42 | .opacity(viewAppeared ? 1 : 0) 43 | .animation(.smooth.delay(animationDuration * 3), value: viewAppeared) 44 | } 45 | .padding(.horizontal, 24) 46 | .padding(.vertical, 12) 47 | } 48 | .overlay(alignment: .topLeading) { 49 | Text("@Shubham_iosdev") 50 | .font(.system(size: 18, weight: .medium, design: .serif)) 51 | .tracking(-0.2) 52 | .offset(y: viewAppeared ? 0 : 34) 53 | .opacity(viewAppeared ? 0.7 : 0) 54 | .padding(.top, 14) 55 | .animation(.smooth.delay(animationDuration * 3), value: viewAppeared) 56 | .foregroundStyle(yinYangViewModel.themeToggled ? Color.background : Color.label) 57 | .padding(.leading, 24) 58 | .padding(.top, 54) 59 | 60 | } 61 | } 62 | .environment(yinYangViewModel) 63 | .onAppear() { 64 | viewAppeared.toggle() 65 | } 66 | } 67 | 68 | // MARK: - Functions 69 | @ViewBuilder 70 | func GenerateViewBackground() -> some View { 71 | Color.white 72 | .ignoresSafeArea() 73 | .scaleEffect(!yinYangViewModel.themeToggled ? scale : 0) 74 | .opacity(yinYangViewModel.themeToggled ? 0 : 1) 75 | .animation(.smooth, value: yinYangViewModel.themeToggled) 76 | 77 | Circle() 78 | .ignoresSafeArea() 79 | .scaleEffect(yinYangViewModel.themeToggled ? scale : 0) 80 | .offset(y: -44) 81 | .opacity(yinYangViewModel.themeToggled ? 1 : 0) 82 | .animation(yinYangViewModel.themeToggled ? .smooth(duration: animationDuration) : .snappy(duration: animationDuration), value: yinYangViewModel.themeToggled) 83 | } 84 | 85 | @ViewBuilder 86 | func GenerateShapeView() -> some View { 87 | ZStack { 88 | Rectangle() 89 | .foregroundColor(.label) 90 | .opacity(yinYangViewModel.themeToggled ? 0.25 : 0.02) 91 | .frame(height: 3) 92 | .scaleEffect(3) 93 | .rotationEffect(.degrees(-25)) 94 | .offset(y: -UIScreen.main.bounds.height * 0.5 + 48) 95 | 96 | Rectangle() 97 | .foregroundColor(.label) 98 | .opacity(yinYangViewModel.themeToggled ? 0.225 : 0.025) 99 | .foregroundStyle(yinYangViewModel.themeToggled ? Color.background : Color.label) 100 | .frame(height: 3) 101 | .scaleEffect(3) 102 | .rotationEffect(.degrees(-25)) 103 | .offset(y: -UIScreen.main.bounds.height * 0.5 + 84) 104 | } 105 | .opacity(viewAppeared ? 1 : 0) 106 | .animation(.smooth.delay(animationDuration * 3.25), value: viewAppeared) 107 | } 108 | 109 | @ViewBuilder 110 | func GenerateYinToggleView() -> some View { 111 | YinToggleView() 112 | .frame(width: 140, height: 62) 113 | .offset(y: -44) 114 | 115 | } 116 | } 117 | 118 | #Preview { 119 | YinYangAnimationView() 120 | } 121 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Modules/Home/IntroView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IntroView.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 13/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct IntroView: View { 12 | var body: some View { 13 | Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) 14 | } 15 | } 16 | 17 | struct IntroView_Previews: PreviewProvider { 18 | static var previews: some View { 19 | IntroView() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Services/HapticManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HapticManager.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 13/10/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | struct HapticManager { 12 | 13 | enum NotificationFeedbackType { 14 | case success, info, failure 15 | } 16 | 17 | enum ImpactFeedbackType { 18 | case light, medium, heavy 19 | } 20 | 21 | // MARK:- functions 22 | func makeNotifiationFeedback(mode: NotificationFeedbackType) { 23 | let generator = UINotificationFeedbackGenerator() 24 | 25 | if (mode == .success) { 26 | generator.notificationOccurred(.success) 27 | } else if (mode == .failure) { 28 | generator.notificationOccurred(.error) 29 | } else { 30 | generator.notificationOccurred(.warning) 31 | } 32 | } 33 | 34 | func makeSelectionFeedback() { 35 | let generator = UISelectionFeedbackGenerator() 36 | generator.selectionChanged() 37 | } 38 | 39 | func makeImpactFeedback(mode: ImpactFeedbackType) { 40 | var generator: UIImpactFeedbackGenerator 41 | if (mode == .light) { 42 | generator = UIImpactFeedbackGenerator(style: .light) 43 | } else if (mode == .medium) { 44 | generator = UIImpactFeedbackGenerator(style: .medium) 45 | } else { 46 | generator = UIImpactFeedbackGenerator(style: .heavy) 47 | } 48 | generator.prepare() 49 | generator.impactOccurred() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SwiftUI-Animations/Code/Utils/Colors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Colors.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 08/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | extension Color { 12 | 13 | static let background: Color = Color(UIColor.systemBackground) 14 | static let label: Color = Color(UIColor.label) 15 | 16 | static let chatBackground: Color = Color(r: 41, g: 121, b: 255.0) 17 | static let buttonBackground: Color = Color(r: 144.0, g: 202.0, b: 249.0) 18 | 19 | static let wifiBackground: Color = Color(r: 5, g: 23, b: 46) 20 | static let wifiShadow: Color = Color(r: 13, g: 50, b: 125) 21 | 22 | static let wifiConnected: Color = Color(r: 170, g: 255, b: 197) 23 | 24 | static let expandingBackground: Color = Color(r: 3, g: 247, b: 235) 25 | static let expandingAccent: Color = Color(r: 186, g: 38, b: 75) 26 | 27 | static let circleTrackStart: Color = Color(r: 237, g: 242, b: 255) 28 | static let circleTrackEnd: Color = Color(r: 235, g: 248, b: 255) 29 | 30 | static let circleRoundStart: Color = Color(r: 71, g: 198, b: 255) 31 | static let circleRoundEnd: Color = Color(r: 90, g: 131, b: 255) 32 | 33 | static let pillColor: Color = Color(r: 242, g: 53, b: 174) 34 | 35 | static let likeBackground: Color = Color(r: 49, g: 28, b: 78) 36 | static let likeOverlay: Color = Color(r: 64, g: 49, b: 82) 37 | 38 | static let likeColor: Color = Color(r: 254, g: 140, b: 100) 39 | 40 | static let submitColor: Color = Color(r: 110, g: 80, b: 249) 41 | 42 | static let materialBlack: Color = Color(r: 18, g: 18, b: 18) 43 | static let offWhite: Color = Color(r: 225, g: 225, b: 235) 44 | 45 | init(r: Double, g: Double, b: Double) { 46 | self.init(red: r / 255.0, green: g / 255.0, blue: b / 255.0) 47 | } 48 | } 49 | 50 | extension Color { 51 | 52 | init(hex: String) { 53 | self.init(UIColor(hex: hex)) 54 | } 55 | } 56 | 57 | extension UIColor { 58 | /// For converting Hex-based colors 59 | convenience init(hex: String) { 60 | var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines) 61 | hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "") 62 | var rgb: UInt64 = 0 63 | 64 | var r: CGFloat = 0.0 65 | var g: CGFloat = 0.0 66 | var b: CGFloat = 0.0 67 | var a: CGFloat = 1.0 68 | 69 | let length = hexSanitized.count 70 | Scanner(string: hexSanitized).scanHexInt64(&rgb) 71 | 72 | if length == 6 { 73 | r = CGFloat((rgb & 0xFF0000) >> 16) / 255.0 74 | g = CGFloat((rgb & 0x00FF00) >> 8) / 255.0 75 | b = CGFloat(rgb & 0x0000FF) / 255.0 76 | 77 | } else if length == 8 { 78 | r = CGFloat((rgb & 0xFF000000) >> 24) / 255.0 79 | g = CGFloat((rgb & 0x00FF0000) >> 16) / 255.0 80 | b = CGFloat((rgb & 0x0000FF00) >> 8) / 255.0 81 | a = CGFloat(rgb & 0x000000FF) / 255.0 82 | } 83 | self.init(red: r, green: g, blue: b, alpha: a) 84 | } 85 | } 86 | 87 | 88 | // Foundation 89 | extension Double { 90 | 91 | func clean(places: Int) -> String { 92 | return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.\(places)f", self) 93 | } 94 | } 95 | 96 | -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/.DS_Store -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/3-d-Loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/3-d-Loader.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/addView.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/addView.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/book-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/book-loader.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/cards.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/cards.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/cart.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/cart.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/chat-bar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/chat-bar.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/circle-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/circle-loader.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/downloadButton.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/downloadButton.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/github-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/github-loader.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/infinity.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/infinity.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/lightswitch.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/lightswitch.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/likeVIew.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/likeVIew.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/loader.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/login.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/login.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/octocat-wink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/octocat-wink.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/pill-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/pill-loader.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/spinningloader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/spinningloader.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/submit-button.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/submit-button.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/triLoader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/triLoader.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/GIFs/wifi.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham0812/SwiftUI-Animations/a6344c483499af14b5cc89104108608ac99ad97d/SwiftUI-Animations/GIFs/wifi.gif -------------------------------------------------------------------------------- /SwiftUI-Animations/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /SwiftUI-Animations/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // SwiftUI-Animations 4 | // 5 | // Created by Shubham Singh on 05/08/20. 6 | // Copyright © 2020 Shubham Singh. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = YinYangAnimationView().preferredColorScheme(.light) 24 | 25 | // Use a UIHostingController as window root view controller. 26 | if let windowScene = scene as? UIWindowScene { 27 | let window = UIWindow(windowScene: windowScene) 28 | window.rootViewController = UIHostingController(rootView: contentView) 29 | self.window = window 30 | window.makeKeyAndVisible() 31 | } 32 | } 33 | 34 | func sceneDidDisconnect(_ scene: UIScene) { 35 | // Called as the scene is being released by the system. 36 | // This occurs shortly after the scene enters the background, or when its session is discarded. 37 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 38 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 39 | } 40 | 41 | func sceneDidBecomeActive(_ scene: UIScene) { 42 | // Called when the scene has moved from an inactive state to an active state. 43 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 44 | } 45 | 46 | func sceneWillResignActive(_ scene: UIScene) { 47 | // Called when the scene will move from an active state to an inactive state. 48 | // This may occur due to temporary interruptions (ex. an incoming phone call). 49 | } 50 | 51 | func sceneWillEnterForeground(_ scene: UIScene) { 52 | // Called as the scene transitions from the background to the foreground. 53 | // Use this method to undo the changes made on entering the background. 54 | } 55 | 56 | func sceneDidEnterBackground(_ scene: UIScene) { 57 | // Called as the scene transitions from the foreground to the background. 58 | // Use this method to save data, release shared resources, and store enough scene-specific state information 59 | // to restore the scene back to its current state. 60 | } 61 | 62 | 63 | } 64 | 65 | --------------------------------------------------------------------------------