├── .gitignore ├── AnimationExamples.xcodeproj └── project.pbxproj ├── AnimationExamples ├── AnimationExamplesApp.swift ├── Animations │ ├── BlinkCircle │ │ ├── BlinkCircleVM.swift │ │ └── BlinkCircleView.swift │ ├── CircleRotation │ │ ├── CircleRotationVM.swift │ │ └── CirclesRotationView.swift │ ├── ConfettiCenter │ │ ├── ConfettiCenterVM.swift │ │ └── ConfettiCenterView.swift │ ├── FireworkCenter │ │ ├── FireworkCenterVM.swift │ │ └── FireworkCenterView.swift │ ├── PaperPlane │ │ ├── PaperPlaneVM.swift │ │ └── PaperPlaneView.swift │ └── SnowFlake │ │ ├── SnowFlakeVM.swift │ │ └── SnowFlakeView.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── paper_plane.imageset │ │ ├── Contents.json │ │ ├── ic_nft_send@2x.png │ │ └── ic_nft_send@3x.png │ └── snow_flake.imageset │ │ ├── Contents.json │ │ ├── snow_flake@2x.png │ │ └── snow_flake@3x.png ├── Helper │ ├── Extension.swift │ └── RandomGenerator.swift ├── HomePage.swift ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json └── Shapes │ ├── RoundedCross.swift │ ├── SlimRectangle.swift │ └── Triangle.swift ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | 4 | xcuserdata/ 5 | 6 | *.xcodeproj/* 7 | !*.xcodeproj/project.pbxproj 8 | !*.xcodeproj/xcshareddata/ 9 | !*.xcworkspace/contents.xcworkspacedata 10 | /*.gcno 11 | 12 | ## Build generated 13 | build/ 14 | DerivedData/ 15 | 16 | ## Various settings 17 | *.pbxuser 18 | !default.pbxuser 19 | *.mode1v3 20 | !default.mode1v3 21 | *.mode2v3 22 | !default.mode2v3 23 | *.perspectivev3 24 | !default.perspectivev3 25 | xcuserdata/ 26 | 27 | Resources/Font 28 | -------------------------------------------------------------------------------- /AnimationExamples.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0B3C46D529BF38E000B4B38A /* AnimationExamplesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3C46D429BF38E000B4B38A /* AnimationExamplesApp.swift */; }; 11 | 0B3C46D729BF38E000B4B38A /* HomePage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3C46D629BF38E000B4B38A /* HomePage.swift */; }; 12 | 0B3C46D929BF38E100B4B38A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0B3C46D829BF38E100B4B38A /* Assets.xcassets */; }; 13 | 0B3C46DC29BF38E100B4B38A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0B3C46DB29BF38E100B4B38A /* Preview Assets.xcassets */; }; 14 | 0B3C46E329BF3A1F00B4B38A /* SnowFlakeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3C46E229BF3A1F00B4B38A /* SnowFlakeView.swift */; }; 15 | 0B3C46E629BF3AEC00B4B38A /* SnowFlakeVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3C46E529BF3AEC00B4B38A /* SnowFlakeVM.swift */; }; 16 | 0B3C46EA29BF427900B4B38A /* RandomGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3C46E929BF427900B4B38A /* RandomGenerator.swift */; }; 17 | 0B3C46EC29BF481000B4B38A /* PaperPlaneView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3C46EB29BF481000B4B38A /* PaperPlaneView.swift */; }; 18 | 0B3C46EE29BF481700B4B38A /* PaperPlaneVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3C46ED29BF481700B4B38A /* PaperPlaneVM.swift */; }; 19 | 0B515C0829C1813A0094D991 /* CirclesRotationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B515C0729C1813A0094D991 /* CirclesRotationView.swift */; }; 20 | 0BB8837929D0670F00ED56FB /* FireworkCenterVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB8837729D0670F00ED56FB /* FireworkCenterVM.swift */; }; 21 | 0BB8837A29D0670F00ED56FB /* FireworkCenterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB8837829D0670F00ED56FB /* FireworkCenterView.swift */; }; 22 | 0BBD2A9329C08659003FBA45 /* BlinkCircleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BBD2A9229C08659003FBA45 /* BlinkCircleView.swift */; }; 23 | 0BBD2A9529C08661003FBA45 /* BlinkCircleVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BBD2A9429C08661003FBA45 /* BlinkCircleVM.swift */; }; 24 | 0BC38A3E29C3DFBE00BD08DB /* ConfettiCenterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC38A3D29C3DFBE00BD08DB /* ConfettiCenterView.swift */; }; 25 | 0BC38A4029C3E00A00BD08DB /* ConfettiCenterVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC38A3F29C3E00A00BD08DB /* ConfettiCenterVM.swift */; }; 26 | 0BC38A4329C3E0F700BD08DB /* Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC38A4229C3E0F700BD08DB /* Extension.swift */; }; 27 | 0BC38A4829C3E15100BD08DB /* RoundedCross.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC38A4529C3E15000BD08DB /* RoundedCross.swift */; }; 28 | 0BC38A4929C3E15100BD08DB /* Triangle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC38A4629C3E15100BD08DB /* Triangle.swift */; }; 29 | 0BC38A4A29C3E15100BD08DB /* SlimRectangle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC38A4729C3E15100BD08DB /* SlimRectangle.swift */; }; 30 | 0BC38A5229C86CD800BD08DB /* CircleRotationVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC38A5129C86CD800BD08DB /* CircleRotationVM.swift */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 0B3C46D129BF38E000B4B38A /* AnimationExamples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AnimationExamples.app; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 0B3C46D429BF38E000B4B38A /* AnimationExamplesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimationExamplesApp.swift; sourceTree = ""; }; 36 | 0B3C46D629BF38E000B4B38A /* HomePage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomePage.swift; sourceTree = ""; }; 37 | 0B3C46D829BF38E100B4B38A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 38 | 0B3C46DB29BF38E100B4B38A /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 39 | 0B3C46E229BF3A1F00B4B38A /* SnowFlakeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnowFlakeView.swift; sourceTree = ""; }; 40 | 0B3C46E529BF3AEC00B4B38A /* SnowFlakeVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnowFlakeVM.swift; sourceTree = ""; }; 41 | 0B3C46E929BF427900B4B38A /* RandomGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RandomGenerator.swift; sourceTree = ""; }; 42 | 0B3C46EB29BF481000B4B38A /* PaperPlaneView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaperPlaneView.swift; sourceTree = ""; }; 43 | 0B3C46ED29BF481700B4B38A /* PaperPlaneVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaperPlaneVM.swift; sourceTree = ""; }; 44 | 0B515C0729C1813A0094D991 /* CirclesRotationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CirclesRotationView.swift; sourceTree = ""; }; 45 | 0BB8837729D0670F00ED56FB /* FireworkCenterVM.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FireworkCenterVM.swift; sourceTree = ""; }; 46 | 0BB8837829D0670F00ED56FB /* FireworkCenterView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FireworkCenterView.swift; sourceTree = ""; }; 47 | 0BBD2A9229C08659003FBA45 /* BlinkCircleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlinkCircleView.swift; sourceTree = ""; }; 48 | 0BBD2A9429C08661003FBA45 /* BlinkCircleVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlinkCircleVM.swift; sourceTree = ""; }; 49 | 0BC38A3D29C3DFBE00BD08DB /* ConfettiCenterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfettiCenterView.swift; sourceTree = ""; }; 50 | 0BC38A3F29C3E00A00BD08DB /* ConfettiCenterVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfettiCenterVM.swift; sourceTree = ""; }; 51 | 0BC38A4229C3E0F700BD08DB /* Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extension.swift; sourceTree = ""; }; 52 | 0BC38A4529C3E15000BD08DB /* RoundedCross.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoundedCross.swift; sourceTree = ""; }; 53 | 0BC38A4629C3E15100BD08DB /* Triangle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Triangle.swift; sourceTree = ""; }; 54 | 0BC38A4729C3E15100BD08DB /* SlimRectangle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlimRectangle.swift; sourceTree = ""; }; 55 | 0BC38A5129C86CD800BD08DB /* CircleRotationVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleRotationVM.swift; sourceTree = ""; }; 56 | /* End PBXFileReference section */ 57 | 58 | /* Begin PBXFrameworksBuildPhase section */ 59 | 0B3C46CE29BF38E000B4B38A /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 0B3C46C829BF38E000B4B38A = { 70 | isa = PBXGroup; 71 | children = ( 72 | 0B3C46D329BF38E000B4B38A /* AnimationExamples */, 73 | 0B3C46D229BF38E000B4B38A /* Products */, 74 | ); 75 | sourceTree = ""; 76 | }; 77 | 0B3C46D229BF38E000B4B38A /* Products */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 0B3C46D129BF38E000B4B38A /* AnimationExamples.app */, 81 | ); 82 | name = Products; 83 | sourceTree = ""; 84 | }; 85 | 0B3C46D329BF38E000B4B38A /* AnimationExamples */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 0B3C46D629BF38E000B4B38A /* HomePage.swift */, 89 | 0B3C46D429BF38E000B4B38A /* AnimationExamplesApp.swift */, 90 | 0BC38A5029C86BEB00BD08DB /* Animations */, 91 | 0B3C46E829BF426900B4B38A /* Helper */, 92 | 0BC38A4429C3E13000BD08DB /* Shapes */, 93 | 0B3C46D829BF38E100B4B38A /* Assets.xcassets */, 94 | 0B3C46DA29BF38E100B4B38A /* Preview Content */, 95 | ); 96 | path = AnimationExamples; 97 | sourceTree = ""; 98 | }; 99 | 0B3C46DA29BF38E100B4B38A /* Preview Content */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 0B3C46DB29BF38E100B4B38A /* Preview Assets.xcassets */, 103 | ); 104 | path = "Preview Content"; 105 | sourceTree = ""; 106 | }; 107 | 0B3C46E829BF426900B4B38A /* Helper */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 0B3C46E929BF427900B4B38A /* RandomGenerator.swift */, 111 | 0BC38A4229C3E0F700BD08DB /* Extension.swift */, 112 | ); 113 | path = Helper; 114 | sourceTree = ""; 115 | }; 116 | 0BB8837629D066DF00ED56FB /* FireworkCenter */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 0BB8837829D0670F00ED56FB /* FireworkCenterView.swift */, 120 | 0BB8837729D0670F00ED56FB /* FireworkCenterVM.swift */, 121 | ); 122 | path = FireworkCenter; 123 | sourceTree = ""; 124 | }; 125 | 0BC38A4429C3E13000BD08DB /* Shapes */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 0BC38A4529C3E15000BD08DB /* RoundedCross.swift */, 129 | 0BC38A4729C3E15100BD08DB /* SlimRectangle.swift */, 130 | 0BC38A4629C3E15100BD08DB /* Triangle.swift */, 131 | ); 132 | path = Shapes; 133 | sourceTree = ""; 134 | }; 135 | 0BC38A4B29C86B6000BD08DB /* ConfettiCenter */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 0BC38A3D29C3DFBE00BD08DB /* ConfettiCenterView.swift */, 139 | 0BC38A3F29C3E00A00BD08DB /* ConfettiCenterVM.swift */, 140 | ); 141 | path = ConfettiCenter; 142 | sourceTree = ""; 143 | }; 144 | 0BC38A4C29C86B6700BD08DB /* SnowFlake */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | 0B3C46E229BF3A1F00B4B38A /* SnowFlakeView.swift */, 148 | 0B3C46E529BF3AEC00B4B38A /* SnowFlakeVM.swift */, 149 | ); 150 | path = SnowFlake; 151 | sourceTree = ""; 152 | }; 153 | 0BC38A4D29C86B6E00BD08DB /* PaperPlane */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 0B3C46ED29BF481700B4B38A /* PaperPlaneVM.swift */, 157 | 0B3C46EB29BF481000B4B38A /* PaperPlaneView.swift */, 158 | ); 159 | path = PaperPlane; 160 | sourceTree = ""; 161 | }; 162 | 0BC38A4E29C86B7F00BD08DB /* BlinkCircle */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | 0BBD2A9229C08659003FBA45 /* BlinkCircleView.swift */, 166 | 0BBD2A9429C08661003FBA45 /* BlinkCircleVM.swift */, 167 | ); 168 | path = BlinkCircle; 169 | sourceTree = ""; 170 | }; 171 | 0BC38A4F29C86B8A00BD08DB /* CircleRotation */ = { 172 | isa = PBXGroup; 173 | children = ( 174 | 0B515C0729C1813A0094D991 /* CirclesRotationView.swift */, 175 | 0BC38A5129C86CD800BD08DB /* CircleRotationVM.swift */, 176 | ); 177 | path = CircleRotation; 178 | sourceTree = ""; 179 | }; 180 | 0BC38A5029C86BEB00BD08DB /* Animations */ = { 181 | isa = PBXGroup; 182 | children = ( 183 | 0BB8837629D066DF00ED56FB /* FireworkCenter */, 184 | 0BC38A4C29C86B6700BD08DB /* SnowFlake */, 185 | 0BC38A4D29C86B6E00BD08DB /* PaperPlane */, 186 | 0BC38A4E29C86B7F00BD08DB /* BlinkCircle */, 187 | 0BC38A4F29C86B8A00BD08DB /* CircleRotation */, 188 | 0BC38A4B29C86B6000BD08DB /* ConfettiCenter */, 189 | ); 190 | path = Animations; 191 | sourceTree = ""; 192 | }; 193 | /* End PBXGroup section */ 194 | 195 | /* Begin PBXNativeTarget section */ 196 | 0B3C46D029BF38E000B4B38A /* AnimationExamples */ = { 197 | isa = PBXNativeTarget; 198 | buildConfigurationList = 0B3C46DF29BF38E100B4B38A /* Build configuration list for PBXNativeTarget "AnimationExamples" */; 199 | buildPhases = ( 200 | 0B3C46CD29BF38E000B4B38A /* Sources */, 201 | 0B3C46CE29BF38E000B4B38A /* Frameworks */, 202 | 0B3C46CF29BF38E000B4B38A /* Resources */, 203 | ); 204 | buildRules = ( 205 | ); 206 | dependencies = ( 207 | ); 208 | name = AnimationExamples; 209 | productName = AnimationExamples; 210 | productReference = 0B3C46D129BF38E000B4B38A /* AnimationExamples.app */; 211 | productType = "com.apple.product-type.application"; 212 | }; 213 | /* End PBXNativeTarget section */ 214 | 215 | /* Begin PBXProject section */ 216 | 0B3C46C929BF38E000B4B38A /* Project object */ = { 217 | isa = PBXProject; 218 | attributes = { 219 | BuildIndependentTargetsInParallel = 1; 220 | LastSwiftUpdateCheck = 1410; 221 | LastUpgradeCheck = 1410; 222 | TargetAttributes = { 223 | 0B3C46D029BF38E000B4B38A = { 224 | CreatedOnToolsVersion = 14.1; 225 | }; 226 | }; 227 | }; 228 | buildConfigurationList = 0B3C46CC29BF38E000B4B38A /* Build configuration list for PBXProject "AnimationExamples" */; 229 | compatibilityVersion = "Xcode 14.0"; 230 | developmentRegion = en; 231 | hasScannedForEncodings = 0; 232 | knownRegions = ( 233 | en, 234 | Base, 235 | ); 236 | mainGroup = 0B3C46C829BF38E000B4B38A; 237 | productRefGroup = 0B3C46D229BF38E000B4B38A /* Products */; 238 | projectDirPath = ""; 239 | projectRoot = ""; 240 | targets = ( 241 | 0B3C46D029BF38E000B4B38A /* AnimationExamples */, 242 | ); 243 | }; 244 | /* End PBXProject section */ 245 | 246 | /* Begin PBXResourcesBuildPhase section */ 247 | 0B3C46CF29BF38E000B4B38A /* Resources */ = { 248 | isa = PBXResourcesBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | 0B3C46DC29BF38E100B4B38A /* Preview Assets.xcassets in Resources */, 252 | 0B3C46D929BF38E100B4B38A /* Assets.xcassets in Resources */, 253 | ); 254 | runOnlyForDeploymentPostprocessing = 0; 255 | }; 256 | /* End PBXResourcesBuildPhase section */ 257 | 258 | /* Begin PBXSourcesBuildPhase section */ 259 | 0B3C46CD29BF38E000B4B38A /* Sources */ = { 260 | isa = PBXSourcesBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | 0BC38A3E29C3DFBE00BD08DB /* ConfettiCenterView.swift in Sources */, 264 | 0BBD2A9329C08659003FBA45 /* BlinkCircleView.swift in Sources */, 265 | 0BC38A4029C3E00A00BD08DB /* ConfettiCenterVM.swift in Sources */, 266 | 0B515C0829C1813A0094D991 /* CirclesRotationView.swift in Sources */, 267 | 0B3C46EC29BF481000B4B38A /* PaperPlaneView.swift in Sources */, 268 | 0B3C46E629BF3AEC00B4B38A /* SnowFlakeVM.swift in Sources */, 269 | 0BC38A4829C3E15100BD08DB /* RoundedCross.swift in Sources */, 270 | 0B3C46D729BF38E000B4B38A /* HomePage.swift in Sources */, 271 | 0BB8837A29D0670F00ED56FB /* FireworkCenterView.swift in Sources */, 272 | 0BC38A4A29C3E15100BD08DB /* SlimRectangle.swift in Sources */, 273 | 0B3C46EE29BF481700B4B38A /* PaperPlaneVM.swift in Sources */, 274 | 0B3C46EA29BF427900B4B38A /* RandomGenerator.swift in Sources */, 275 | 0BC38A5229C86CD800BD08DB /* CircleRotationVM.swift in Sources */, 276 | 0BC38A4329C3E0F700BD08DB /* Extension.swift in Sources */, 277 | 0BBD2A9529C08661003FBA45 /* BlinkCircleVM.swift in Sources */, 278 | 0BC38A4929C3E15100BD08DB /* Triangle.swift in Sources */, 279 | 0B3C46E329BF3A1F00B4B38A /* SnowFlakeView.swift in Sources */, 280 | 0B3C46D529BF38E000B4B38A /* AnimationExamplesApp.swift in Sources */, 281 | 0BB8837929D0670F00ED56FB /* FireworkCenterVM.swift in Sources */, 282 | ); 283 | runOnlyForDeploymentPostprocessing = 0; 284 | }; 285 | /* End PBXSourcesBuildPhase section */ 286 | 287 | /* Begin XCBuildConfiguration section */ 288 | 0B3C46DD29BF38E100B4B38A /* Debug */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ALWAYS_SEARCH_USER_PATHS = NO; 292 | CLANG_ANALYZER_NONNULL = YES; 293 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 295 | CLANG_ENABLE_MODULES = YES; 296 | CLANG_ENABLE_OBJC_ARC = YES; 297 | CLANG_ENABLE_OBJC_WEAK = YES; 298 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 299 | CLANG_WARN_BOOL_CONVERSION = YES; 300 | CLANG_WARN_COMMA = YES; 301 | CLANG_WARN_CONSTANT_CONVERSION = YES; 302 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 303 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 304 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 305 | CLANG_WARN_EMPTY_BODY = YES; 306 | CLANG_WARN_ENUM_CONVERSION = YES; 307 | CLANG_WARN_INFINITE_RECURSION = YES; 308 | CLANG_WARN_INT_CONVERSION = YES; 309 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 310 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 311 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 312 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 313 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 314 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 315 | CLANG_WARN_STRICT_PROTOTYPES = YES; 316 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 317 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 318 | CLANG_WARN_UNREACHABLE_CODE = YES; 319 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 320 | COPY_PHASE_STRIP = NO; 321 | DEBUG_INFORMATION_FORMAT = dwarf; 322 | ENABLE_STRICT_OBJC_MSGSEND = YES; 323 | ENABLE_TESTABILITY = YES; 324 | GCC_C_LANGUAGE_STANDARD = gnu11; 325 | GCC_DYNAMIC_NO_PIC = NO; 326 | GCC_NO_COMMON_BLOCKS = YES; 327 | GCC_OPTIMIZATION_LEVEL = 0; 328 | GCC_PREPROCESSOR_DEFINITIONS = ( 329 | "DEBUG=1", 330 | "$(inherited)", 331 | ); 332 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 333 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 334 | GCC_WARN_UNDECLARED_SELECTOR = YES; 335 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 336 | GCC_WARN_UNUSED_FUNCTION = YES; 337 | GCC_WARN_UNUSED_VARIABLE = YES; 338 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 339 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 340 | MTL_FAST_MATH = YES; 341 | ONLY_ACTIVE_ARCH = YES; 342 | SDKROOT = iphoneos; 343 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 344 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 345 | }; 346 | name = Debug; 347 | }; 348 | 0B3C46DE29BF38E100B4B38A /* Release */ = { 349 | isa = XCBuildConfiguration; 350 | buildSettings = { 351 | ALWAYS_SEARCH_USER_PATHS = NO; 352 | CLANG_ANALYZER_NONNULL = YES; 353 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 354 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 355 | CLANG_ENABLE_MODULES = YES; 356 | CLANG_ENABLE_OBJC_ARC = YES; 357 | CLANG_ENABLE_OBJC_WEAK = YES; 358 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 359 | CLANG_WARN_BOOL_CONVERSION = YES; 360 | CLANG_WARN_COMMA = YES; 361 | CLANG_WARN_CONSTANT_CONVERSION = YES; 362 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 363 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 364 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 365 | CLANG_WARN_EMPTY_BODY = YES; 366 | CLANG_WARN_ENUM_CONVERSION = YES; 367 | CLANG_WARN_INFINITE_RECURSION = YES; 368 | CLANG_WARN_INT_CONVERSION = YES; 369 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 370 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 371 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 372 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 373 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 374 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 375 | CLANG_WARN_STRICT_PROTOTYPES = YES; 376 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 377 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 378 | CLANG_WARN_UNREACHABLE_CODE = YES; 379 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 380 | COPY_PHASE_STRIP = NO; 381 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 382 | ENABLE_NS_ASSERTIONS = NO; 383 | ENABLE_STRICT_OBJC_MSGSEND = YES; 384 | GCC_C_LANGUAGE_STANDARD = gnu11; 385 | GCC_NO_COMMON_BLOCKS = YES; 386 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 387 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 388 | GCC_WARN_UNDECLARED_SELECTOR = YES; 389 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 390 | GCC_WARN_UNUSED_FUNCTION = YES; 391 | GCC_WARN_UNUSED_VARIABLE = YES; 392 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 393 | MTL_ENABLE_DEBUG_INFO = NO; 394 | MTL_FAST_MATH = YES; 395 | SDKROOT = iphoneos; 396 | SWIFT_COMPILATION_MODE = wholemodule; 397 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 398 | VALIDATE_PRODUCT = YES; 399 | }; 400 | name = Release; 401 | }; 402 | 0B3C46E029BF38E100B4B38A /* Debug */ = { 403 | isa = XCBuildConfiguration; 404 | buildSettings = { 405 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 406 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 407 | CODE_SIGN_STYLE = Automatic; 408 | CURRENT_PROJECT_VERSION = 1; 409 | DEVELOPMENT_ASSET_PATHS = "\"AnimationExamples/Preview Content\""; 410 | DEVELOPMENT_TEAM = 696UKQNL3G; 411 | ENABLE_PREVIEWS = YES; 412 | GENERATE_INFOPLIST_FILE = YES; 413 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 414 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 415 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 416 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 417 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 418 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 419 | LD_RUNPATH_SEARCH_PATHS = ( 420 | "$(inherited)", 421 | "@executable_path/Frameworks", 422 | ); 423 | MARKETING_VERSION = 1.0; 424 | PRODUCT_BUNDLE_IDENTIFIER = com.esatgozcu.AnimationExamples; 425 | PRODUCT_NAME = "$(TARGET_NAME)"; 426 | SWIFT_EMIT_LOC_STRINGS = YES; 427 | SWIFT_VERSION = 5.0; 428 | TARGETED_DEVICE_FAMILY = "1,2"; 429 | }; 430 | name = Debug; 431 | }; 432 | 0B3C46E129BF38E100B4B38A /* Release */ = { 433 | isa = XCBuildConfiguration; 434 | buildSettings = { 435 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 436 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 437 | CODE_SIGN_STYLE = Automatic; 438 | CURRENT_PROJECT_VERSION = 1; 439 | DEVELOPMENT_ASSET_PATHS = "\"AnimationExamples/Preview Content\""; 440 | DEVELOPMENT_TEAM = 696UKQNL3G; 441 | ENABLE_PREVIEWS = YES; 442 | GENERATE_INFOPLIST_FILE = YES; 443 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 444 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 445 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 446 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 447 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 448 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 449 | LD_RUNPATH_SEARCH_PATHS = ( 450 | "$(inherited)", 451 | "@executable_path/Frameworks", 452 | ); 453 | MARKETING_VERSION = 1.0; 454 | PRODUCT_BUNDLE_IDENTIFIER = com.esatgozcu.AnimationExamples; 455 | PRODUCT_NAME = "$(TARGET_NAME)"; 456 | SWIFT_EMIT_LOC_STRINGS = YES; 457 | SWIFT_VERSION = 5.0; 458 | TARGETED_DEVICE_FAMILY = "1,2"; 459 | }; 460 | name = Release; 461 | }; 462 | /* End XCBuildConfiguration section */ 463 | 464 | /* Begin XCConfigurationList section */ 465 | 0B3C46CC29BF38E000B4B38A /* Build configuration list for PBXProject "AnimationExamples" */ = { 466 | isa = XCConfigurationList; 467 | buildConfigurations = ( 468 | 0B3C46DD29BF38E100B4B38A /* Debug */, 469 | 0B3C46DE29BF38E100B4B38A /* Release */, 470 | ); 471 | defaultConfigurationIsVisible = 0; 472 | defaultConfigurationName = Release; 473 | }; 474 | 0B3C46DF29BF38E100B4B38A /* Build configuration list for PBXNativeTarget "AnimationExamples" */ = { 475 | isa = XCConfigurationList; 476 | buildConfigurations = ( 477 | 0B3C46E029BF38E100B4B38A /* Debug */, 478 | 0B3C46E129BF38E100B4B38A /* Release */, 479 | ); 480 | defaultConfigurationIsVisible = 0; 481 | defaultConfigurationName = Release; 482 | }; 483 | /* End XCConfigurationList section */ 484 | }; 485 | rootObject = 0B3C46C929BF38E000B4B38A /* Project object */; 486 | } 487 | -------------------------------------------------------------------------------- /AnimationExamples/AnimationExamplesApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnimationExamplesApp.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/13. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct AnimationExamplesApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | HomePage() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AnimationExamples/Animations/BlinkCircle/BlinkCircleVM.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BlinkCircleVM.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/14. 6 | // 7 | 8 | import SwiftUI 9 | 10 | class BlinkCircleVM : ObservableObject { 11 | 12 | var startSize = 0.2 13 | var endSize = 2.0 14 | var animTime : Double = 0.05 15 | @Published var currentSize = 0.2 16 | @Published var viewID = 0 17 | @Published var rowCount : Int = 2 18 | 19 | func calculateOffsetX(width: CGFloat, i: Int) -> CGFloat{ 20 | let onePiece = Double(width/Double(rowCount)) 21 | let result = onePiece*Double(i%Int(rowCount)) 22 | return CGFloat(result) 23 | } 24 | func calculateOffsetY(size: CGSize, i: Int) -> CGFloat{ 25 | let onePiece = Int(size.width/Double(rowCount)) 26 | let result = onePiece*Int(i/Int(rowCount)) 27 | let startPosition = Int((size.height/2) - (size.width/2)) 28 | return CGFloat(result + startPosition) 29 | } 30 | func getItemSize()->Int{ 31 | return rowCount*rowCount 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /AnimationExamples/Animations/BlinkCircle/BlinkCircleView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BlinkCircleView.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/14. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BlinkCircleView: View { 11 | 12 | @StateObject var vm = BlinkCircleVM() 13 | 14 | var body: some View { 15 | GeometryReader { geo in 16 | ForEach(0.. [AnyView]{ 74 | var shapes = [AnyView]() 75 | for confetti in confettiTypes{ 76 | for color in colors{ 77 | switch confetti { 78 | case .shape(_): 79 | shapes.append(AnyView(confetti.view.foregroundColor(color).frame(width: confettiSize, height: confettiSize, alignment: .center))) 80 | default: 81 | shapes.append(AnyView(confetti.view.foregroundColor(color).font(.system(size: confettiSize)))) 82 | } 83 | } 84 | } 85 | return shapes 86 | } 87 | func getAnimDuration() -> CGFloat{ 88 | return explosionAnimationDuration + dropAnimationDuration 89 | } 90 | } 91 | 92 | public enum ConfettiType: CaseIterable, Hashable { 93 | public enum Shape { 94 | case circle 95 | case triangle 96 | case square 97 | case slimRectangle 98 | case roundedCross 99 | } 100 | 101 | case shape(Shape) 102 | case text(String) 103 | case sfSymbol(symbolName: String) 104 | 105 | public var view:AnyView{ 106 | switch self { 107 | case .shape(.square): 108 | return AnyView(Rectangle()) 109 | case .shape(.triangle): 110 | return AnyView(Triangle()) 111 | case .shape(.slimRectangle): 112 | return AnyView(SlimRectangle()) 113 | case .shape(.roundedCross): 114 | return AnyView(RoundedCross()) 115 | case let .text(text): 116 | return AnyView(Text(text)) 117 | case .sfSymbol(let symbolName): 118 | return AnyView(Image(systemName: symbolName)) 119 | default: 120 | return AnyView(Circle()) 121 | } 122 | } 123 | public static var allCases: [ConfettiType] { 124 | return [.shape(.circle), .shape(.triangle), .shape(.square), .shape(.slimRectangle), .shape(.roundedCross)] 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /AnimationExamples/Animations/ConfettiCenter/ConfettiCenterView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ConfettiView.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/17. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ConfettiCenterView: View{ 11 | 12 | @State var counter = 0 13 | 14 | var body: some View{ 15 | ZStack{ 16 | Text("🎉").onTapGesture { 17 | counter += 1 18 | } 19 | /* FireworkEffect */ 20 | /*ConfettiView(counter: $counter, 21 | confettiVM: ConfettiVM(confettiNumber: 40, 22 | fireworkEffect: true, 23 | openingAngle: Angle(degrees: 0), 24 | closingAngle: Angle(degrees: 360), 25 | radius: 200.0))*/ 26 | /* Emoji - Text */ 27 | /*ConfettiView(counter: $counter, confettiVM: ConfettiVM(confettiNumber: 10, 28 | confettiTypes: [ 29 | .text("❤️"), 30 | .text("💙"), 31 | .text("A")], 32 | confettiSize: 30))*/ 33 | /* Image */ 34 | /*ConfettiView(counter: $counter, confettiVM: ConfettiVM(confettiNumber: 10, 35 | confettiTypes: [ 36 | .sfSymbol(symbolName: "star.fill"), 37 | .sfSymbol(symbolName: "arrow.triangle.2.circlepath"), 38 | .sfSymbol(symbolName: "square.and.arrow.up")], 39 | confettiSize: 30, explosionAnimDuration: 0.7))*/ 40 | /* Default */ 41 | ConfettiView(counter: $counter) 42 | } 43 | } 44 | } 45 | 46 | struct ConfettiView: View{ 47 | 48 | @Binding var counter: Int 49 | @StateObject var confettiVM = ConfettiCenterVM() 50 | @State var animate = 0 51 | @State var finishedAnimationCounter = 0 52 | @State var firstAppear = false 53 | 54 | var body: some View{ 55 | ZStack{ 56 | ForEach(finishedAnimationCounter.. AnyView { 138 | return confettiVM.getShapes().randomElement()! 139 | } 140 | func getColor() -> Color { 141 | return confettiVM.colors.randomElement()! 142 | } 143 | func getRandomExplosionTimeVariation() -> CGFloat { 144 | return CGFloat((0...999).randomElement()!) / 2100 145 | } 146 | func getAnimationDuration() -> CGFloat { 147 | return 0.2 + confettiVM.explosionAnimationDuration + getRandomExplosionTimeVariation() 148 | } 149 | func getDistance() -> CGFloat { 150 | if !confettiVM.fireworkEffect{ 151 | return pow(CGFloat.random(in: 0.01...1), 2.0/7.0) * confettiVM.radius 152 | } 153 | return confettiVM.radius 154 | } 155 | func getDelayBeforeDropAnimation() -> TimeInterval { 156 | confettiVM.explosionAnimationDuration * 0.1 157 | } 158 | func deg2rad(_ number: CGFloat) -> CGFloat { 159 | return number * CGFloat.pi / 180 160 | } 161 | } 162 | 163 | struct ConfettiItem: View { 164 | 165 | @State var shape: AnyView 166 | @State var color: Color 167 | 168 | @State var move = false 169 | @State var anchor = CGFloat(Int.random(in: 0...1)) 170 | @State var spinDirX = [-1.0, 1.0].randomElement()! 171 | @State var spinDirZ = [-1.0, 1.0].randomElement()! 172 | @State var xSpeed = Double.random(in: 0.501...2.201) 173 | @State var zSpeed = Double.random(in: 0.501...2.201) 174 | 175 | var body: some View { 176 | shape 177 | .foregroundColor(color) 178 | .rotation3DEffect(.degrees(move ? 360:0), axis: (x: spinDirX, y: 0, z: 0)) 179 | .animation(Animation.linear(duration: xSpeed).repeatForever(), value: move) 180 | .rotation3DEffect(.degrees(move ? 360:0), axis: (x: 0, y: 0, z: spinDirZ), anchor: UnitPoint(x: anchor, y: anchor)) 181 | .animation(Animation.linear(duration: zSpeed).repeatForever(), value: move) 182 | .onAppear() { 183 | move = true 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /AnimationExamples/Animations/FireworkCenter/FireworkCenterVM.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FireworkCenterVM.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/26. 6 | // 7 | 8 | import SwiftUI 9 | 10 | /// - Parameters: 11 | /// - pieceCount: amount of confetti 12 | /// - colors: list of colors that is applied to the default shapes 13 | /// - pieceSize: size that confetti and emojis are scaled to 14 | /// - radius: explosion radius 15 | /// - repetitions: number of repetitions of the explosion 16 | /// - repetitionInterval: duration between the repetitions 17 | class FireworkCenterVM: ObservableObject{ 18 | @Published var pieceCount: Int 19 | @Published var pieceType: [FireworkType] 20 | @Published var colors: [Color] 21 | @Published var pieceSize: CGFloat 22 | @Published var radius: CGFloat 23 | @Published var repetitions: Int 24 | @Published var repetitionInterval: Double 25 | @Published var explosionAnimationDuration: Double 26 | @Published var launchAnimDuration: Double 27 | 28 | init(pieceCount: Int = 20, 29 | pieceType: [FireworkType] = [.shape(.circle)], 30 | colors: [Color] = [ 31 | Color.init(hex: "f88f22"), 32 | Color.init(hex: "9c1d08"), 33 | Color.init(hex: "ce7117"), 34 | Color.init(hex: "f24d24"), 35 | Color.init(hex: "113bc6"), 36 | Color.init(hex: "c54a85"), 37 | Color.init(hex: "92af96"), 38 | Color.init(hex: "d23508") 39 | ], 40 | pieceSize: CGFloat = 10.0, 41 | radius: CGFloat = 100, 42 | repetitions: Int = 0, 43 | repetitionInterval: Double = 1.0, 44 | explosionAnimDuration: Double = 1.2, 45 | launchAnimDuration: Double = 3.0 46 | ) { 47 | self.pieceCount = pieceCount 48 | self.pieceType = pieceType 49 | self.colors = colors 50 | self.pieceSize = pieceSize 51 | self.radius = radius 52 | self.repetitions = repetitions 53 | self.repetitionInterval = repetitionInterval 54 | self.explosionAnimationDuration = explosionAnimDuration 55 | self.launchAnimDuration = launchAnimDuration 56 | } 57 | func getShapes() -> [AnyView]{ 58 | var shapes = [AnyView]() 59 | for firework in pieceType{ 60 | switch firework { 61 | case .shape(_): 62 | shapes.append(AnyView(firework.view.frame(width: pieceSize, height: pieceSize, alignment: .center))) 63 | default: 64 | shapes.append(AnyView(firework.view.font(.system(size: pieceSize)))) 65 | } 66 | } 67 | return shapes 68 | } 69 | } 70 | 71 | public enum FireworkType: CaseIterable, Hashable { 72 | public enum Shape { 73 | case circle 74 | case triangle 75 | case square 76 | case slimRectangle 77 | case roundedCross 78 | } 79 | 80 | case shape(Shape) 81 | case text(String) 82 | case sfSymbol(symbolName: String) 83 | 84 | public var view:AnyView{ 85 | switch self { 86 | case .shape(.square): 87 | return AnyView(Rectangle()) 88 | case .shape(.circle): 89 | return AnyView(Circle()) 90 | case .shape(.triangle): 91 | return AnyView(Triangle()) 92 | case .shape(.slimRectangle): 93 | return AnyView(SlimRectangle()) 94 | case .shape(.roundedCross): 95 | return AnyView(RoundedCross()) 96 | case let .text(text): 97 | return AnyView(Text(text)) 98 | case .sfSymbol(let symbolName): 99 | return AnyView(Image(systemName: symbolName)) 100 | } 101 | } 102 | public static var allCases: [FireworkType] { 103 | return [.shape(.circle), .shape(.triangle), .shape(.square), .shape(.slimRectangle), .shape(.roundedCross)] 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /AnimationExamples/Animations/FireworkCenter/FireworkCenterView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FireworkCenterView.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/26. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct FireworkCenterView: View{ 11 | 12 | @State var counter = 0 13 | 14 | var body: some View{ 15 | ZStack{ 16 | Text("🎉").onTapGesture { 17 | counter += 1 18 | }.padding(.bottom, 40) 19 | 20 | FireworkView(counter: $counter) 21 | 22 | }.frame( 23 | maxWidth: .infinity, 24 | maxHeight: .infinity, 25 | alignment: .bottom 26 | ).background(Color.black) 27 | .ignoresSafeArea() 28 | } 29 | } 30 | 31 | struct FireworkView: View{ 32 | 33 | @Binding var counter: Int 34 | @StateObject var vm = FireworkCenterVM() 35 | @State var animate = 0 36 | @State var finishedAnimationCounter = 0 37 | @State var firstAppear = false 38 | 39 | var body: some View{ 40 | ZStack{ 41 | ForEach(finishedAnimationCounter.. CGFloat{ 102 | return vm.explosionAnimationDuration + vm.launchAnimDuration 103 | } 104 | func getColor() -> Color{ 105 | return vm.colors.randomElement()! 106 | } 107 | func getRandomExplosionTimeVariation() -> CGFloat { 108 | return CGFloat((0...999).randomElement()!) / 2100 109 | } 110 | func getExplosionAnimationDuration() -> CGFloat { 111 | return vm.explosionAnimationDuration + getRandomExplosionTimeVariation() 112 | } 113 | } 114 | 115 | struct FireworkFrame: View{ 116 | 117 | @StateObject var vm: FireworkCenterVM 118 | @State var location: CGPoint = CGPoint(x: 0, y: 0) 119 | @State var index: Int 120 | @State var launchHeight: CGFloat 121 | @State var percentage: CGFloat = 0.0 122 | @State var strokeWidth: CGFloat = 2.0 123 | @State var color: Color 124 | @State var withPath: Int 125 | @State var duration: CGFloat 126 | 127 | var body: some View{ 128 | ZStack{ 129 | FireworkItem(vm: vm, shape: getShape(), size: vm.pieceSize, color: color) 130 | .offset(x: location.x, y: location.y) 131 | .onAppear{ 132 | withAnimation( 133 | Animation 134 | .timingCurve(0.0, 1.0, 1.0, 1.0, duration: duration) 135 | .delay(vm.launchAnimDuration).repeatCount(1) 136 | ){ 137 | location.x = getDistance() * cos(deg2rad(getRandomAngle())) 138 | location.y = -getDistance() * sin(deg2rad(getRandomAngle())) 139 | } 140 | } 141 | 142 | if withPath == 0{ 143 | Path { path in 144 | path.move(to: .zero) 145 | path.addLine( 146 | to: CGPoint( 147 | x: getDistance() * cos(deg2rad(getRandomAngle())), 148 | y: -getDistance() * sin(deg2rad(getRandomAngle())) 149 | ) 150 | ) 151 | }.trim(from: 0.0, to: percentage) 152 | .stroke(color, lineWidth: strokeWidth) 153 | .frame(width: 1.0, height: 1.0) 154 | .onAppear{ 155 | withAnimation( 156 | Animation 157 | .timingCurve(0.0, 1.0, 1.0, 1.0, duration: duration) 158 | .delay(vm.launchAnimDuration).repeatCount(1) 159 | ){ 160 | percentage = 1.0 161 | strokeWidth = 0.0 162 | } 163 | } 164 | } 165 | } 166 | } 167 | func getRandomAngle() -> CGFloat{ 168 | return (360.0 / Double(vm.pieceCount)) * Double(index) 169 | } 170 | func getShape() -> AnyView { 171 | return vm.getShapes().randomElement()! 172 | } 173 | func getDistance() -> CGFloat { 174 | return vm.radius + (launchHeight / 10) 175 | } 176 | func deg2rad(_ number: CGFloat) -> CGFloat { 177 | return number * CGFloat.pi / 180 178 | } 179 | } 180 | 181 | struct FireworkItem: View { 182 | 183 | @StateObject var vm: FireworkCenterVM 184 | @State var shape: AnyView 185 | @State var size: CGFloat 186 | @State var color: Color 187 | @State var scale = 1.0 188 | @State var move = false 189 | 190 | var body: some View { 191 | shape 192 | .frame(width: size, height: size) 193 | .scaleEffect(scale) 194 | .foregroundColor(color) 195 | .onAppear() { 196 | withAnimation( 197 | Animation 198 | .linear(duration: vm.explosionAnimationDuration) 199 | .delay(vm.launchAnimDuration) 200 | .repeatCount(1) 201 | ) { 202 | scale = 0.0 203 | } 204 | } 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /AnimationExamples/Animations/PaperPlane/PaperPlaneVM.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PaperPlaneVM.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/13. 6 | // 7 | 8 | import SwiftUI 9 | 10 | class PaperPlaneVM : ObservableObject { 11 | 12 | var randomYList = [CGFloat]() 13 | var randomSize = [CGFloat]() 14 | var randomDurationMillis = [CGFloat]() 15 | var randomDelayMillis = [CGFloat]() 16 | var screenHeight = Int(UIScreen.main.bounds.height) 17 | var itemSize = 20 18 | 19 | init() { 20 | randomYList = RandomGenerator.uniqueRandoms(numberOfRandoms: itemSize, minNum: 100 , maxNum: screenHeight) 21 | randomSize = RandomGenerator.uniqueRandoms(numberOfRandoms: itemSize, minNum: 20 , maxNum: 100) 22 | randomDurationMillis = RandomGenerator.uniqueRandoms(numberOfRandoms: itemSize, minNum: 750 , maxNum: 1250) 23 | randomDelayMillis = RandomGenerator.uniqueRandoms(numberOfRandoms: itemSize, minNum: 0 , maxNum: 1000) 24 | } 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /AnimationExamples/Animations/PaperPlane/PaperPlaneView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PaperPlaneView.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/13. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct PaperPlaneView: View { 11 | 12 | @StateObject var viewModel = PaperPlaneVM() 13 | @State var action = false 14 | 15 | var body: some View { 16 | GeometryReader { geo in 17 | ForEach(0.. Color { 12 | Color( 13 | red: .random(in: 0...1), 14 | green: .random(in: 0...1), 15 | blue: .random(in: 0...1), 16 | opacity: randomOpacity ? .random(in: 0...1) : 1 17 | ) 18 | } 19 | } 20 | 21 | extension Color { 22 | init(hex: String) { 23 | let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) 24 | var int: UInt64 = 0 25 | Scanner(string: hex).scanHexInt64(&int) 26 | let a, r, g, b: UInt64 27 | switch hex.count { 28 | case 3: // RGB (12-bit) 29 | (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) 30 | case 6: // RGB (24-bit) 31 | (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) 32 | case 8: // ARGB (32-bit) 33 | (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) 34 | default: 35 | (a, r, g, b) = (1, 1, 1, 0) 36 | } 37 | 38 | self.init( 39 | .sRGB, 40 | red: Double(r) / 255, 41 | green: Double(g) / 255, 42 | blue: Double(b) / 255, 43 | opacity: Double(a) / 255 44 | ) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /AnimationExamples/Helper/RandomGenerator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RandomGenerator.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/13. 6 | // 7 | 8 | import Foundation 9 | 10 | class RandomGenerator { 11 | static func uniqueRandoms(numberOfRandoms: Int, minNum: Int, maxNum: Int) -> [CGFloat] { 12 | var uniqueNumbers = Set() 13 | while uniqueNumbers.count < numberOfRandoms { 14 | uniqueNumbers.insert(CGFloat(Int(arc4random_uniform(UInt32(maxNum) + 1)) + minNum)) 15 | } 16 | return uniqueNumbers.shuffled() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /AnimationExamples/HomePage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/13. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct HomePage: View { 11 | var body: some View { 12 | NavigationView { 13 | VStack(spacing: 20) { 14 | HomePageItem(title: "Snow Flake", image: "snow_flake") { 15 | SnowFlakeView() 16 | } 17 | HomePageItem(title: "Paper Plane", image: "paper_plane") { 18 | PaperPlaneView() 19 | } 20 | NavigationLink(destination: BlinkCircleView()) { 21 | Text("Blink Circles") 22 | Circle() 23 | .foregroundColor(.black) 24 | .frame(width: 20, height: 20) 25 | } 26 | NavigationLink(destination: CirclesRotationView()) { 27 | Text("Circles Rotation") 28 | Image(systemName: "rotate.3d") 29 | .resizable() 30 | .foregroundColor(.red) 31 | .frame(width: 20, height: 20) 32 | } 33 | NavigationLink(destination: ConfettiCenterView()) { 34 | Text("Confetti Animation") 35 | Text("🎉") 36 | .foregroundColor(.red) 37 | .frame(width: 20, height: 20) 38 | } 39 | NavigationLink(destination: FireworkCenterView()) { 40 | Text("Firework Animation") 41 | Text("🎆") 42 | .foregroundColor(.red) 43 | .frame(width: 20, height: 20) 44 | } 45 | } 46 | } 47 | } 48 | } 49 | 50 | struct HomePageItem: View { 51 | 52 | var title : String 53 | var image : String 54 | var content: () -> Content 55 | 56 | var body: some View { 57 | NavigationLink(destination: content) { 58 | Text(title) 59 | Image(image) 60 | .resizable() 61 | .frame(width: 20, height: 20) 62 | } 63 | } 64 | } 65 | 66 | struct ContentView_Previews: PreviewProvider { 67 | static var previews: some View { 68 | HomePage() 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /AnimationExamples/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AnimationExamples/Shapes/RoundedCross.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RoundedCross.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/17. 6 | // 7 | 8 | import SwiftUI 9 | 10 | public struct RoundedCross: Shape { 11 | public func path(in rect: CGRect) -> Path { 12 | 13 | var path = Path() 14 | path.move(to: CGPoint(x: rect.minX, y: rect.maxY/3)) 15 | path.addQuadCurve(to: CGPoint(x: rect.maxX/3, y: rect.minY), control: CGPoint(x: rect.maxX/3, y: rect.maxY/3)) 16 | path.addLine(to: CGPoint(x: 2*rect.maxX/3, y: rect.minY)) 17 | 18 | path.addQuadCurve(to: CGPoint(x: rect.maxX, y: rect.maxY/3), control: CGPoint(x: 2*rect.maxX/3, y: rect.maxY/3)) 19 | path.addLine(to: CGPoint(x: rect.maxX, y: 2*rect.maxY/3)) 20 | 21 | path.addQuadCurve(to: CGPoint(x: 2*rect.maxX/3, y: rect.maxY), control: CGPoint(x: 2*rect.maxX/3, y: 2*rect.maxY/3)) 22 | path.addLine(to: CGPoint(x: rect.maxX/3, y: rect.maxY)) 23 | 24 | path.addQuadCurve(to: CGPoint(x: 2*rect.minX/3, y: 2*rect.maxY/3), control: CGPoint(x: rect.maxX/3, y: 2*rect.maxY/3)) 25 | return path 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /AnimationExamples/Shapes/SlimRectangle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SlimRectangle.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/17. 6 | // 7 | 8 | import SwiftUI 9 | 10 | public struct SlimRectangle: Shape { 11 | public func path(in rect: CGRect) -> Path { 12 | 13 | var path = Path() 14 | path.move(to: CGPoint(x: rect.minX, y: 4*rect.maxY/5)) 15 | path.addLine(to: CGPoint(x: rect.maxX, y: 4*rect.maxY/5)) 16 | path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) 17 | path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY)) 18 | return path 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /AnimationExamples/Shapes/Triangle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Triangle.swift 3 | // AnimationExamples 4 | // 5 | // Created by Esat Gözcü on 2023/03/17. 6 | // 7 | 8 | import SwiftUI 9 | 10 | public struct Triangle: Shape { 11 | public func path(in rect: CGRect) -> Path { 12 | 13 | var path = Path() 14 | path.move(to: CGPoint(x: rect.midX, y: rect.minY)) 15 | path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY)) 16 | path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) 17 | path.addLine(to: CGPoint(x: rect.midX, y: rect.minY)) 18 | return path 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Esat GÖZCÜ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftUI Animation Examples 2 | 3 | ### Step by step understand animation logic. 4 | 5 | This repository developed for animation. There are a lot of animation with different concepts. You can select what you want and customize what you needed. 6 | 7 | Screenshot 2023-03-23 at 4 55 32 PM 8 | 9 | ## Simple Animations 10 | 11 | | **#[Snow Flake](AnimationExamples/Animations/SnowFlake)** | **#[Paper Plane](AnimationExamples/Animations/PaperPlane)** | **#[Blink Circle](AnimationExamples/Animations/BlinkCircle)** | **#[Circle Rotation](AnimationExamples/Animations/CirclesRotation)** | 12 | | --- | --- | --- | --- | 13 | | | | | | 14 | 15 |
16 | 17 | ## Confetti Animations 18 | 19 | | **#[Default](AnimationExamples/Animations/ConfettiCenter)** | **#[Firework Effect](AnimationExamples/Animations/ConfettiCenter)** | 20 | | --- | --- | 21 | | | | 22 | 23 | | **#[Image with SF Symbol](AnimationExamples/Animations/ConfettiCenter)** | **#[Emoji - Text](AnimationExamples/Animations/ConfettiCenter)** | 24 | | --- | --- | 25 | | | | 26 | 27 |
28 | 29 | ## Firework Animations 30 | 31 | | **#[Firework](AnimationExamples/Animations/FireworkCenter)** | 32 | | --- | 33 | | | 34 | 35 |
36 | 37 | ## 🔨 Support 38 | 39 | If you like the project, don't forget to `put star 🌟`. 40 | --------------------------------------------------------------------------------