├── .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 |
--------------------------------------------------------------------------------