├── PulseAnimation
├── PulseAnimation
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Preview Content
│ │ └── Preview Assets.xcassets
│ │ │ └── Contents.json
│ ├── Info.plist
│ ├── PulseAnimationApp.swift
│ ├── ContentView.swift
│ └── New Group
│ │ └── PJRPulseButton.swift
└── PulseAnimation.xcodeproj
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── paritosh.raval.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ ├── xcuserdata
│ └── paritosh.raval.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
│ └── project.pbxproj
├── README.md
└── LICENSE
/PulseAnimation/PulseAnimation/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation.xcodeproj/xcuserdata/paritosh.raval.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation.xcodeproj/project.xcworkspace/xcuserdata/paritosh.raval.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritoshraval100/PulseAnimation/HEAD/PulseAnimation/PulseAnimation.xcodeproj/project.xcworkspace/xcuserdata/paritosh.raval.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation.xcodeproj/xcuserdata/paritosh.raval.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | PulseAnimation.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation/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 |
28 | UIApplicationSupportsIndirectInputEvents
29 |
30 | UILaunchScreen
31 |
32 | UIRequiredDeviceCapabilities
33 |
34 | armv7
35 |
36 | UISupportedInterfaceOrientations
37 |
38 | UIInterfaceOrientationPortrait
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UISupportedInterfaceOrientations~ipad
43 |
44 | UIInterfaceOrientationPortrait
45 | UIInterfaceOrientationPortraitUpsideDown
46 | UIInterfaceOrientationLandscapeLeft
47 | UIInterfaceOrientationLandscapeRight
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PulseAnimation
2 | Pulse Button Animation with SwiftUI
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | I have created **PJRPulseButton** which will generate a pulse animation for the button. Provided an example as well.
14 |
15 |
16 | # How to use?
17 |
18 | It is very simple, you can use **PJRPulseButton** file in any class just like `PJRPulseButton()`. It will craeate a default button animation with plus button image.
19 |
20 |
21 | https://user-images.githubusercontent.com/5228713/112018520-a6fc5300-8b54-11eb-90ac-fd66d751a98e.mov
22 |
23 |
24 |
25 | You can customize it with different colors, image, animation duration, button size and number of outer circles.
26 |
27 | **Example**: `PJRPulseButton(color: Color.red, systemImageName: "heart.circle.fill", buttonWidth: 48, numberOfOuterCircles: 2, animationDuration: 1)`
28 |
29 |
30 |
31 | https://user-images.githubusercontent.com/5228713/112018878-f3479300-8b54-11eb-850a-9a83f66ee41e.mov
32 |
33 |
34 |
35 | License
36 | =====================
37 | Paritosh Raval
38 |
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation/PulseAnimationApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PulseAnimationApp.swift
3 | // PulseAnimation
4 | //
5 | // Created by Paritosh Raval on 22/03/21.
6 | //
7 |
8 | /*
9 | * Redistribution and use in source and binary forms, with or without
10 | * modification, are permitted provided that the following conditions are met:
11 | * * Redistributions of source code must retain the above copyright
12 | * notice, this list of conditions and the following disclaimer.
13 | * * Redistributions in binary form must reproduce the above copyright
14 | * notice, this list of conditions and the following disclaimer in the
15 | * documentation and/or other materials provided with the distribution.
16 | * * Neither the name of the nor the
17 | * names of its contributors may be used to endorse or promote products
18 | * derived from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
24 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | *
31 | */
32 |
33 | import SwiftUI
34 |
35 | @main
36 | struct PulseAnimationApp: App {
37 | var body: some Scene {
38 | WindowGroup {
39 | ContentView()
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation/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 |
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // PulseAnimation
4 | //
5 | // Created by Paritosh Raval on 22/03/21.
6 | //
7 |
8 | /*
9 | * Redistribution and use in source and binary forms, with or without
10 | * modification, are permitted provided that the following conditions are met:
11 | * * Redistributions of source code must retain the above copyright
12 | * notice, this list of conditions and the following disclaimer.
13 | * * Redistributions in binary form must reproduce the above copyright
14 | * notice, this list of conditions and the following disclaimer in the
15 | * documentation and/or other materials provided with the distribution.
16 | * * Neither the name of the nor the
17 | * names of its contributors may be used to endorse or promote products
18 | * derived from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
24 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | *
31 | */
32 |
33 | /*#********************************************************************************************************************
34 |
35 | You can try different variations like
36 | PJRPulseButton(color: Color.red, systemImageName: "heart.circle.fill", buttonWidth: 48, numberOfOuterCircles: 2, animationDuration: 1)
37 |
38 | *********************************************************************************************************************/
39 |
40 | import SwiftUI
41 |
42 | struct ContentView: View {
43 |
44 | var body: some View {
45 | EmptyView()
46 | .overlay(
47 | PJRPulseButton()
48 | .padding(.bottom, 15)
49 | .padding(.trailing, 15)
50 | , alignment: .bottomTrailing
51 | )
52 | }
53 | }
54 |
55 | struct ContentView_Previews: PreviewProvider {
56 | static var previews: some View {
57 | ContentView()
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/PulseAnimation/PulseAnimation/New Group/PJRPulseButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PJRPulseButton.swift
3 | // PulseAnimation
4 | //
5 | // Created by Paritosh Raval on 22/03/21.
6 | //
7 |
8 | /*
9 | * Redistribution and use in source and binary forms, with or without
10 | * modification, are permitted provided that the following conditions are met:
11 | * * Redistributions of source code must retain the above copyright
12 | * notice, this list of conditions and the following disclaimer.
13 | * * Redistributions in binary form must reproduce the above copyright
14 | * notice, this list of conditions and the following disclaimer in the
15 | * documentation and/or other materials provided with the distribution.
16 | * * Neither the name of the nor the
17 | * names of its contributors may be used to endorse or promote products
18 | * derived from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
24 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | *
31 | */
32 |
33 | import SwiftUI
34 |
35 | // MARK: - Strucutre for Circle
36 | struct CircleData: Hashable {
37 | let width: CGFloat
38 | let opacity: Double
39 | }
40 |
41 | struct PJRPulseButton: View {
42 |
43 | // MARK: - Properties
44 | @State private var isAnimating: Bool = false
45 | var color: Color
46 | var systemImageName: String
47 | var buttonWidth: CGFloat
48 | var numberOfOuterCircles: Int
49 | var animationDuration: Double
50 | var circleArray = [CircleData]()
51 |
52 |
53 | init(color: Color = Color.blue, systemImageName: String = "plus.circle.fill", buttonWidth: CGFloat = 48, numberOfOuterCircles: Int = 2, animationDuration: Double = 1) {
54 | self.color = color
55 | self.systemImageName = systemImageName
56 | self.buttonWidth = buttonWidth
57 | self.numberOfOuterCircles = numberOfOuterCircles
58 | self.animationDuration = animationDuration
59 |
60 | var circleWidth = self.buttonWidth
61 | var opacity = (numberOfOuterCircles > 4) ? 0.40 : 0.20
62 |
63 | for _ in 0..