├── 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 | plus plus person info Screenshot 2021-03-22 at 9 48 36 PM Screenshot 2021-03-22 at 10 03 14 PM 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..