├── .DS_Store ├── CAShapeLayerDemo ├── .DS_Store ├── CAShapeLayerDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── wyy.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── wyy.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── CAShapeLayerDemo.xcscheme │ │ └── xcschememanagement.plist ├── CAShapeLayerDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── MMSubView.h │ ├── MMSubView.m │ ├── MMWaveView.h │ ├── MMWaveView.m │ ├── SecondViewController.h │ ├── SecondViewController.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── CAShapeLayerDemoTests │ ├── CAShapeLayerDemoTests.m │ └── Info.plist └── CAShapeLayerDemoUITests │ ├── CAShapeLayerDemoUITests.m │ └── Info.plist ├── MMWaveView.podspec ├── MMWaveView ├── .DS_Store ├── MMWaveView.h └── MMWaveView.m └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YYWDark/MMWaveView/52c7bd803c81843c89f6fc2f4c8514c2f1c4ffdf/.DS_Store -------------------------------------------------------------------------------- /CAShapeLayerDemo/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YYWDark/MMWaveView/52c7bd803c81843c89f6fc2f4c8514c2f1c4ffdf/CAShapeLayerDemo/.DS_Store -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 75B357C31DDB041300F847DE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 75B357C21DDB041300F847DE /* main.m */; }; 11 | 75B357C61DDB041300F847DE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 75B357C51DDB041300F847DE /* AppDelegate.m */; }; 12 | 75B357C91DDB041300F847DE /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 75B357C81DDB041300F847DE /* ViewController.m */; }; 13 | 75B357CC1DDB041300F847DE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 75B357CA1DDB041300F847DE /* Main.storyboard */; }; 14 | 75B357CE1DDB041300F847DE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 75B357CD1DDB041300F847DE /* Assets.xcassets */; }; 15 | 75B357D11DDB041300F847DE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 75B357CF1DDB041300F847DE /* LaunchScreen.storyboard */; }; 16 | 75B357DC1DDB041300F847DE /* CAShapeLayerDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 75B357DB1DDB041300F847DE /* CAShapeLayerDemoTests.m */; }; 17 | 75B357E71DDB041300F847DE /* CAShapeLayerDemoUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 75B357E61DDB041300F847DE /* CAShapeLayerDemoUITests.m */; }; 18 | 75B357F71DDB042B00F847DE /* MMWaveView.m in Sources */ = {isa = PBXBuildFile; fileRef = 75B357F61DDB042B00F847DE /* MMWaveView.m */; }; 19 | 75B357FA1DDB044900F847DE /* SecondViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 75B357F91DDB044900F847DE /* SecondViewController.m */; }; 20 | 75B358001DDB056700F847DE /* MMSubView.m in Sources */ = {isa = PBXBuildFile; fileRef = 75B357FF1DDB056700F847DE /* MMSubView.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | 75B357D81DDB041300F847DE /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = 75B357B61DDB041300F847DE /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = 75B357BD1DDB041300F847DE; 29 | remoteInfo = CAShapeLayerDemo; 30 | }; 31 | 75B357E31DDB041300F847DE /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = 75B357B61DDB041300F847DE /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = 75B357BD1DDB041300F847DE; 36 | remoteInfo = CAShapeLayerDemo; 37 | }; 38 | /* End PBXContainerItemProxy section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 75B357BE1DDB041300F847DE /* CAShapeLayerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CAShapeLayerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 75B357C21DDB041300F847DE /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 43 | 75B357C41DDB041300F847DE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 44 | 75B357C51DDB041300F847DE /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 45 | 75B357C71DDB041300F847DE /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 46 | 75B357C81DDB041300F847DE /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 47 | 75B357CB1DDB041300F847DE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 48 | 75B357CD1DDB041300F847DE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 49 | 75B357D01DDB041300F847DE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 50 | 75B357D21DDB041300F847DE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 51 | 75B357D71DDB041300F847DE /* CAShapeLayerDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CAShapeLayerDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 75B357DB1DDB041300F847DE /* CAShapeLayerDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CAShapeLayerDemoTests.m; sourceTree = ""; }; 53 | 75B357DD1DDB041300F847DE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 54 | 75B357E21DDB041300F847DE /* CAShapeLayerDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CAShapeLayerDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 75B357E61DDB041300F847DE /* CAShapeLayerDemoUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CAShapeLayerDemoUITests.m; sourceTree = ""; }; 56 | 75B357E81DDB041300F847DE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 75B357F51DDB042B00F847DE /* MMWaveView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMWaveView.h; sourceTree = ""; }; 58 | 75B357F61DDB042B00F847DE /* MMWaveView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMWaveView.m; sourceTree = ""; }; 59 | 75B357F81DDB044900F847DE /* SecondViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecondViewController.h; sourceTree = ""; }; 60 | 75B357F91DDB044900F847DE /* SecondViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecondViewController.m; sourceTree = ""; }; 61 | 75B357FE1DDB056700F847DE /* MMSubView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMSubView.h; sourceTree = ""; }; 62 | 75B357FF1DDB056700F847DE /* MMSubView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMSubView.m; sourceTree = ""; }; 63 | /* End PBXFileReference section */ 64 | 65 | /* Begin PBXFrameworksBuildPhase section */ 66 | 75B357BB1DDB041300F847DE /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | 75B357D41DDB041300F847DE /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | ); 78 | runOnlyForDeploymentPostprocessing = 0; 79 | }; 80 | 75B357DF1DDB041300F847DE /* Frameworks */ = { 81 | isa = PBXFrameworksBuildPhase; 82 | buildActionMask = 2147483647; 83 | files = ( 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | /* End PBXFrameworksBuildPhase section */ 88 | 89 | /* Begin PBXGroup section */ 90 | 75B357B51DDB041300F847DE = { 91 | isa = PBXGroup; 92 | children = ( 93 | 75B357C01DDB041300F847DE /* CAShapeLayerDemo */, 94 | 75B357DA1DDB041300F847DE /* CAShapeLayerDemoTests */, 95 | 75B357E51DDB041300F847DE /* CAShapeLayerDemoUITests */, 96 | 75B357BF1DDB041300F847DE /* Products */, 97 | ); 98 | sourceTree = ""; 99 | }; 100 | 75B357BF1DDB041300F847DE /* Products */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 75B357BE1DDB041300F847DE /* CAShapeLayerDemo.app */, 104 | 75B357D71DDB041300F847DE /* CAShapeLayerDemoTests.xctest */, 105 | 75B357E21DDB041300F847DE /* CAShapeLayerDemoUITests.xctest */, 106 | ); 107 | name = Products; 108 | sourceTree = ""; 109 | }; 110 | 75B357C01DDB041300F847DE /* CAShapeLayerDemo */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 75B357F41DDB041E00F847DE /* View */, 114 | 75B357C41DDB041300F847DE /* AppDelegate.h */, 115 | 75B357C51DDB041300F847DE /* AppDelegate.m */, 116 | 75B357C71DDB041300F847DE /* ViewController.h */, 117 | 75B357C81DDB041300F847DE /* ViewController.m */, 118 | 75B357F81DDB044900F847DE /* SecondViewController.h */, 119 | 75B357F91DDB044900F847DE /* SecondViewController.m */, 120 | 75B357FE1DDB056700F847DE /* MMSubView.h */, 121 | 75B357FF1DDB056700F847DE /* MMSubView.m */, 122 | 75B357CA1DDB041300F847DE /* Main.storyboard */, 123 | 75B357CD1DDB041300F847DE /* Assets.xcassets */, 124 | 75B357CF1DDB041300F847DE /* LaunchScreen.storyboard */, 125 | 75B357D21DDB041300F847DE /* Info.plist */, 126 | 75B357C11DDB041300F847DE /* Supporting Files */, 127 | ); 128 | path = CAShapeLayerDemo; 129 | sourceTree = ""; 130 | }; 131 | 75B357C11DDB041300F847DE /* Supporting Files */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 75B357C21DDB041300F847DE /* main.m */, 135 | ); 136 | name = "Supporting Files"; 137 | sourceTree = ""; 138 | }; 139 | 75B357DA1DDB041300F847DE /* CAShapeLayerDemoTests */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 75B357DB1DDB041300F847DE /* CAShapeLayerDemoTests.m */, 143 | 75B357DD1DDB041300F847DE /* Info.plist */, 144 | ); 145 | path = CAShapeLayerDemoTests; 146 | sourceTree = ""; 147 | }; 148 | 75B357E51DDB041300F847DE /* CAShapeLayerDemoUITests */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 75B357E61DDB041300F847DE /* CAShapeLayerDemoUITests.m */, 152 | 75B357E81DDB041300F847DE /* Info.plist */, 153 | ); 154 | path = CAShapeLayerDemoUITests; 155 | sourceTree = ""; 156 | }; 157 | 75B357F41DDB041E00F847DE /* View */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 75B357F51DDB042B00F847DE /* MMWaveView.h */, 161 | 75B357F61DDB042B00F847DE /* MMWaveView.m */, 162 | ); 163 | name = View; 164 | sourceTree = ""; 165 | }; 166 | /* End PBXGroup section */ 167 | 168 | /* Begin PBXNativeTarget section */ 169 | 75B357BD1DDB041300F847DE /* CAShapeLayerDemo */ = { 170 | isa = PBXNativeTarget; 171 | buildConfigurationList = 75B357EB1DDB041300F847DE /* Build configuration list for PBXNativeTarget "CAShapeLayerDemo" */; 172 | buildPhases = ( 173 | 75B357BA1DDB041300F847DE /* Sources */, 174 | 75B357BB1DDB041300F847DE /* Frameworks */, 175 | 75B357BC1DDB041300F847DE /* Resources */, 176 | ); 177 | buildRules = ( 178 | ); 179 | dependencies = ( 180 | ); 181 | name = CAShapeLayerDemo; 182 | productName = CAShapeLayerDemo; 183 | productReference = 75B357BE1DDB041300F847DE /* CAShapeLayerDemo.app */; 184 | productType = "com.apple.product-type.application"; 185 | }; 186 | 75B357D61DDB041300F847DE /* CAShapeLayerDemoTests */ = { 187 | isa = PBXNativeTarget; 188 | buildConfigurationList = 75B357EE1DDB041300F847DE /* Build configuration list for PBXNativeTarget "CAShapeLayerDemoTests" */; 189 | buildPhases = ( 190 | 75B357D31DDB041300F847DE /* Sources */, 191 | 75B357D41DDB041300F847DE /* Frameworks */, 192 | 75B357D51DDB041300F847DE /* Resources */, 193 | ); 194 | buildRules = ( 195 | ); 196 | dependencies = ( 197 | 75B357D91DDB041300F847DE /* PBXTargetDependency */, 198 | ); 199 | name = CAShapeLayerDemoTests; 200 | productName = CAShapeLayerDemoTests; 201 | productReference = 75B357D71DDB041300F847DE /* CAShapeLayerDemoTests.xctest */; 202 | productType = "com.apple.product-type.bundle.unit-test"; 203 | }; 204 | 75B357E11DDB041300F847DE /* CAShapeLayerDemoUITests */ = { 205 | isa = PBXNativeTarget; 206 | buildConfigurationList = 75B357F11DDB041300F847DE /* Build configuration list for PBXNativeTarget "CAShapeLayerDemoUITests" */; 207 | buildPhases = ( 208 | 75B357DE1DDB041300F847DE /* Sources */, 209 | 75B357DF1DDB041300F847DE /* Frameworks */, 210 | 75B357E01DDB041300F847DE /* Resources */, 211 | ); 212 | buildRules = ( 213 | ); 214 | dependencies = ( 215 | 75B357E41DDB041300F847DE /* PBXTargetDependency */, 216 | ); 217 | name = CAShapeLayerDemoUITests; 218 | productName = CAShapeLayerDemoUITests; 219 | productReference = 75B357E21DDB041300F847DE /* CAShapeLayerDemoUITests.xctest */; 220 | productType = "com.apple.product-type.bundle.ui-testing"; 221 | }; 222 | /* End PBXNativeTarget section */ 223 | 224 | /* Begin PBXProject section */ 225 | 75B357B61DDB041300F847DE /* Project object */ = { 226 | isa = PBXProject; 227 | attributes = { 228 | LastUpgradeCheck = 0730; 229 | ORGANIZATIONNAME = yyx; 230 | TargetAttributes = { 231 | 75B357BD1DDB041300F847DE = { 232 | CreatedOnToolsVersion = 7.3; 233 | }; 234 | 75B357D61DDB041300F847DE = { 235 | CreatedOnToolsVersion = 7.3; 236 | TestTargetID = 75B357BD1DDB041300F847DE; 237 | }; 238 | 75B357E11DDB041300F847DE = { 239 | CreatedOnToolsVersion = 7.3; 240 | TestTargetID = 75B357BD1DDB041300F847DE; 241 | }; 242 | }; 243 | }; 244 | buildConfigurationList = 75B357B91DDB041300F847DE /* Build configuration list for PBXProject "CAShapeLayerDemo" */; 245 | compatibilityVersion = "Xcode 3.2"; 246 | developmentRegion = English; 247 | hasScannedForEncodings = 0; 248 | knownRegions = ( 249 | en, 250 | Base, 251 | ); 252 | mainGroup = 75B357B51DDB041300F847DE; 253 | productRefGroup = 75B357BF1DDB041300F847DE /* Products */; 254 | projectDirPath = ""; 255 | projectRoot = ""; 256 | targets = ( 257 | 75B357BD1DDB041300F847DE /* CAShapeLayerDemo */, 258 | 75B357D61DDB041300F847DE /* CAShapeLayerDemoTests */, 259 | 75B357E11DDB041300F847DE /* CAShapeLayerDemoUITests */, 260 | ); 261 | }; 262 | /* End PBXProject section */ 263 | 264 | /* Begin PBXResourcesBuildPhase section */ 265 | 75B357BC1DDB041300F847DE /* Resources */ = { 266 | isa = PBXResourcesBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | 75B357D11DDB041300F847DE /* LaunchScreen.storyboard in Resources */, 270 | 75B357CE1DDB041300F847DE /* Assets.xcassets in Resources */, 271 | 75B357CC1DDB041300F847DE /* Main.storyboard in Resources */, 272 | ); 273 | runOnlyForDeploymentPostprocessing = 0; 274 | }; 275 | 75B357D51DDB041300F847DE /* Resources */ = { 276 | isa = PBXResourcesBuildPhase; 277 | buildActionMask = 2147483647; 278 | files = ( 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | }; 282 | 75B357E01DDB041300F847DE /* Resources */ = { 283 | isa = PBXResourcesBuildPhase; 284 | buildActionMask = 2147483647; 285 | files = ( 286 | ); 287 | runOnlyForDeploymentPostprocessing = 0; 288 | }; 289 | /* End PBXResourcesBuildPhase section */ 290 | 291 | /* Begin PBXSourcesBuildPhase section */ 292 | 75B357BA1DDB041300F847DE /* Sources */ = { 293 | isa = PBXSourcesBuildPhase; 294 | buildActionMask = 2147483647; 295 | files = ( 296 | 75B357FA1DDB044900F847DE /* SecondViewController.m in Sources */, 297 | 75B357C91DDB041300F847DE /* ViewController.m in Sources */, 298 | 75B357C61DDB041300F847DE /* AppDelegate.m in Sources */, 299 | 75B357C31DDB041300F847DE /* main.m in Sources */, 300 | 75B357F71DDB042B00F847DE /* MMWaveView.m in Sources */, 301 | 75B358001DDB056700F847DE /* MMSubView.m in Sources */, 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | }; 305 | 75B357D31DDB041300F847DE /* Sources */ = { 306 | isa = PBXSourcesBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | 75B357DC1DDB041300F847DE /* CAShapeLayerDemoTests.m in Sources */, 310 | ); 311 | runOnlyForDeploymentPostprocessing = 0; 312 | }; 313 | 75B357DE1DDB041300F847DE /* Sources */ = { 314 | isa = PBXSourcesBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | 75B357E71DDB041300F847DE /* CAShapeLayerDemoUITests.m in Sources */, 318 | ); 319 | runOnlyForDeploymentPostprocessing = 0; 320 | }; 321 | /* End PBXSourcesBuildPhase section */ 322 | 323 | /* Begin PBXTargetDependency section */ 324 | 75B357D91DDB041300F847DE /* PBXTargetDependency */ = { 325 | isa = PBXTargetDependency; 326 | target = 75B357BD1DDB041300F847DE /* CAShapeLayerDemo */; 327 | targetProxy = 75B357D81DDB041300F847DE /* PBXContainerItemProxy */; 328 | }; 329 | 75B357E41DDB041300F847DE /* PBXTargetDependency */ = { 330 | isa = PBXTargetDependency; 331 | target = 75B357BD1DDB041300F847DE /* CAShapeLayerDemo */; 332 | targetProxy = 75B357E31DDB041300F847DE /* PBXContainerItemProxy */; 333 | }; 334 | /* End PBXTargetDependency section */ 335 | 336 | /* Begin PBXVariantGroup section */ 337 | 75B357CA1DDB041300F847DE /* Main.storyboard */ = { 338 | isa = PBXVariantGroup; 339 | children = ( 340 | 75B357CB1DDB041300F847DE /* Base */, 341 | ); 342 | name = Main.storyboard; 343 | sourceTree = ""; 344 | }; 345 | 75B357CF1DDB041300F847DE /* LaunchScreen.storyboard */ = { 346 | isa = PBXVariantGroup; 347 | children = ( 348 | 75B357D01DDB041300F847DE /* Base */, 349 | ); 350 | name = LaunchScreen.storyboard; 351 | sourceTree = ""; 352 | }; 353 | /* End PBXVariantGroup section */ 354 | 355 | /* Begin XCBuildConfiguration section */ 356 | 75B357E91DDB041300F847DE /* Debug */ = { 357 | isa = XCBuildConfiguration; 358 | buildSettings = { 359 | ALWAYS_SEARCH_USER_PATHS = NO; 360 | CLANG_ANALYZER_NONNULL = YES; 361 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 362 | CLANG_CXX_LIBRARY = "libc++"; 363 | CLANG_ENABLE_MODULES = YES; 364 | CLANG_ENABLE_OBJC_ARC = YES; 365 | CLANG_WARN_BOOL_CONVERSION = YES; 366 | CLANG_WARN_CONSTANT_CONVERSION = YES; 367 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 368 | CLANG_WARN_EMPTY_BODY = YES; 369 | CLANG_WARN_ENUM_CONVERSION = YES; 370 | CLANG_WARN_INT_CONVERSION = YES; 371 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 372 | CLANG_WARN_UNREACHABLE_CODE = YES; 373 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 374 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 375 | COPY_PHASE_STRIP = NO; 376 | DEBUG_INFORMATION_FORMAT = dwarf; 377 | ENABLE_STRICT_OBJC_MSGSEND = YES; 378 | ENABLE_TESTABILITY = YES; 379 | GCC_C_LANGUAGE_STANDARD = gnu99; 380 | GCC_DYNAMIC_NO_PIC = NO; 381 | GCC_NO_COMMON_BLOCKS = YES; 382 | GCC_OPTIMIZATION_LEVEL = 0; 383 | GCC_PREPROCESSOR_DEFINITIONS = ( 384 | "DEBUG=1", 385 | "$(inherited)", 386 | ); 387 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 388 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 389 | GCC_WARN_UNDECLARED_SELECTOR = YES; 390 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 391 | GCC_WARN_UNUSED_FUNCTION = YES; 392 | GCC_WARN_UNUSED_VARIABLE = YES; 393 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 394 | MTL_ENABLE_DEBUG_INFO = YES; 395 | ONLY_ACTIVE_ARCH = YES; 396 | SDKROOT = iphoneos; 397 | TARGETED_DEVICE_FAMILY = "1,2"; 398 | }; 399 | name = Debug; 400 | }; 401 | 75B357EA1DDB041300F847DE /* Release */ = { 402 | isa = XCBuildConfiguration; 403 | buildSettings = { 404 | ALWAYS_SEARCH_USER_PATHS = NO; 405 | CLANG_ANALYZER_NONNULL = YES; 406 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 407 | CLANG_CXX_LIBRARY = "libc++"; 408 | CLANG_ENABLE_MODULES = YES; 409 | CLANG_ENABLE_OBJC_ARC = YES; 410 | CLANG_WARN_BOOL_CONVERSION = YES; 411 | CLANG_WARN_CONSTANT_CONVERSION = YES; 412 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 413 | CLANG_WARN_EMPTY_BODY = YES; 414 | CLANG_WARN_ENUM_CONVERSION = YES; 415 | CLANG_WARN_INT_CONVERSION = YES; 416 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 417 | CLANG_WARN_UNREACHABLE_CODE = YES; 418 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 419 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 420 | COPY_PHASE_STRIP = NO; 421 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 422 | ENABLE_NS_ASSERTIONS = NO; 423 | ENABLE_STRICT_OBJC_MSGSEND = YES; 424 | GCC_C_LANGUAGE_STANDARD = gnu99; 425 | GCC_NO_COMMON_BLOCKS = YES; 426 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 427 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 428 | GCC_WARN_UNDECLARED_SELECTOR = YES; 429 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 430 | GCC_WARN_UNUSED_FUNCTION = YES; 431 | GCC_WARN_UNUSED_VARIABLE = YES; 432 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 433 | MTL_ENABLE_DEBUG_INFO = NO; 434 | SDKROOT = iphoneos; 435 | TARGETED_DEVICE_FAMILY = "1,2"; 436 | VALIDATE_PRODUCT = YES; 437 | }; 438 | name = Release; 439 | }; 440 | 75B357EC1DDB041300F847DE /* Debug */ = { 441 | isa = XCBuildConfiguration; 442 | buildSettings = { 443 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 444 | INFOPLIST_FILE = CAShapeLayerDemo/Info.plist; 445 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 446 | PRODUCT_BUNDLE_IDENTIFIER = com.xw.CAShapeLayerDemo; 447 | PRODUCT_NAME = "$(TARGET_NAME)"; 448 | }; 449 | name = Debug; 450 | }; 451 | 75B357ED1DDB041300F847DE /* Release */ = { 452 | isa = XCBuildConfiguration; 453 | buildSettings = { 454 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 455 | INFOPLIST_FILE = CAShapeLayerDemo/Info.plist; 456 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 457 | PRODUCT_BUNDLE_IDENTIFIER = com.xw.CAShapeLayerDemo; 458 | PRODUCT_NAME = "$(TARGET_NAME)"; 459 | }; 460 | name = Release; 461 | }; 462 | 75B357EF1DDB041300F847DE /* Debug */ = { 463 | isa = XCBuildConfiguration; 464 | buildSettings = { 465 | BUNDLE_LOADER = "$(TEST_HOST)"; 466 | INFOPLIST_FILE = CAShapeLayerDemoTests/Info.plist; 467 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 468 | PRODUCT_BUNDLE_IDENTIFIER = com.xw.CAShapeLayerDemoTests; 469 | PRODUCT_NAME = "$(TARGET_NAME)"; 470 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CAShapeLayerDemo.app/CAShapeLayerDemo"; 471 | }; 472 | name = Debug; 473 | }; 474 | 75B357F01DDB041300F847DE /* Release */ = { 475 | isa = XCBuildConfiguration; 476 | buildSettings = { 477 | BUNDLE_LOADER = "$(TEST_HOST)"; 478 | INFOPLIST_FILE = CAShapeLayerDemoTests/Info.plist; 479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 480 | PRODUCT_BUNDLE_IDENTIFIER = com.xw.CAShapeLayerDemoTests; 481 | PRODUCT_NAME = "$(TARGET_NAME)"; 482 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CAShapeLayerDemo.app/CAShapeLayerDemo"; 483 | }; 484 | name = Release; 485 | }; 486 | 75B357F21DDB041300F847DE /* Debug */ = { 487 | isa = XCBuildConfiguration; 488 | buildSettings = { 489 | INFOPLIST_FILE = CAShapeLayerDemoUITests/Info.plist; 490 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 491 | PRODUCT_BUNDLE_IDENTIFIER = com.xw.CAShapeLayerDemoUITests; 492 | PRODUCT_NAME = "$(TARGET_NAME)"; 493 | TEST_TARGET_NAME = CAShapeLayerDemo; 494 | }; 495 | name = Debug; 496 | }; 497 | 75B357F31DDB041300F847DE /* Release */ = { 498 | isa = XCBuildConfiguration; 499 | buildSettings = { 500 | INFOPLIST_FILE = CAShapeLayerDemoUITests/Info.plist; 501 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 502 | PRODUCT_BUNDLE_IDENTIFIER = com.xw.CAShapeLayerDemoUITests; 503 | PRODUCT_NAME = "$(TARGET_NAME)"; 504 | TEST_TARGET_NAME = CAShapeLayerDemo; 505 | }; 506 | name = Release; 507 | }; 508 | /* End XCBuildConfiguration section */ 509 | 510 | /* Begin XCConfigurationList section */ 511 | 75B357B91DDB041300F847DE /* Build configuration list for PBXProject "CAShapeLayerDemo" */ = { 512 | isa = XCConfigurationList; 513 | buildConfigurations = ( 514 | 75B357E91DDB041300F847DE /* Debug */, 515 | 75B357EA1DDB041300F847DE /* Release */, 516 | ); 517 | defaultConfigurationIsVisible = 0; 518 | defaultConfigurationName = Release; 519 | }; 520 | 75B357EB1DDB041300F847DE /* Build configuration list for PBXNativeTarget "CAShapeLayerDemo" */ = { 521 | isa = XCConfigurationList; 522 | buildConfigurations = ( 523 | 75B357EC1DDB041300F847DE /* Debug */, 524 | 75B357ED1DDB041300F847DE /* Release */, 525 | ); 526 | defaultConfigurationIsVisible = 0; 527 | }; 528 | 75B357EE1DDB041300F847DE /* Build configuration list for PBXNativeTarget "CAShapeLayerDemoTests" */ = { 529 | isa = XCConfigurationList; 530 | buildConfigurations = ( 531 | 75B357EF1DDB041300F847DE /* Debug */, 532 | 75B357F01DDB041300F847DE /* Release */, 533 | ); 534 | defaultConfigurationIsVisible = 0; 535 | }; 536 | 75B357F11DDB041300F847DE /* Build configuration list for PBXNativeTarget "CAShapeLayerDemoUITests" */ = { 537 | isa = XCConfigurationList; 538 | buildConfigurations = ( 539 | 75B357F21DDB041300F847DE /* Debug */, 540 | 75B357F31DDB041300F847DE /* Release */, 541 | ); 542 | defaultConfigurationIsVisible = 0; 543 | }; 544 | /* End XCConfigurationList section */ 545 | }; 546 | rootObject = 75B357B61DDB041300F847DE /* Project object */; 547 | } 548 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo.xcodeproj/project.xcworkspace/xcuserdata/wyy.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YYWDark/MMWaveView/52c7bd803c81843c89f6fc2f4c8514c2f1c4ffdf/CAShapeLayerDemo/CAShapeLayerDemo.xcodeproj/project.xcworkspace/xcuserdata/wyy.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo.xcodeproj/xcuserdata/wyy.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo.xcodeproj/xcuserdata/wyy.xcuserdatad/xcschemes/CAShapeLayerDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo.xcodeproj/xcuserdata/wyy.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CAShapeLayerDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 75B357BD1DDB041300F847DE 16 | 17 | primary 18 | 19 | 20 | 75B357D61DDB041300F847DE 21 | 22 | primary 23 | 24 | 25 | 75B357E11DDB041300F847DE 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CAShapeLayerDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CAShapeLayerDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/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 | 27 | 28 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/Base.lproj/Main.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 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/MMSubView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMSubView.h 3 | // CAShapeLayerDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import "MMWaveView.h" 10 | 11 | @interface MMSubView : MMWaveView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/MMSubView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMSubView.m 3 | // CAShapeLayerDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import "MMSubView.h" 10 | 11 | @implementation MMSubView 12 | 13 | /* 14 | // Only override drawRect: if you perform custom drawing. 15 | // An empty implementation adversely affects performance during animation. 16 | - (void)drawRect:(CGRect)rect { 17 | // Drawing code 18 | } 19 | */ 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/MMWaveView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMWaveView.h 3 | // CADisplayLinkDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import 10 | @protocol MMWaveViewDelegate; 11 | 12 | @interface MMWaveView : UIView 13 | @property (nonatomic, weak) id delegate; 14 | @end 15 | 16 | @protocol MMWaveViewDelegate 17 | - (void)waveViewTriggerAction:(MMWaveView *)waveView; 18 | @end -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/MMWaveView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMWaveView.m 3 | // CADisplayLinkDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import "MMWaveView.h" 10 | #define waveFillColor [[UIColor colorWithRed:118/255.0 green:178/255.0 blue:252/255.0 alpha:1] CGColor] 11 | static const CGFloat arrowInitializationDistanceToRightEdge = 20.0f; 12 | static const CGFloat arrowInitializationDistanceToLeft = 20.0f; 13 | static const CGFloat arrowLineWidth = 3.0; 14 | static const NSInteger rate = 4; 15 | 16 | @interface MMWaveView () 17 | @property (nonatomic, strong) CAShapeLayer *waveLayer; 18 | @property (nonatomic, strong) CAShapeLayer *arrowLayer; 19 | @property (nonatomic, assign) BOOL isAnimation; 20 | @property (nonatomic, assign) CGFloat maxX; 21 | @end 22 | 23 | @implementation MMWaveView 24 | -(id)initWithFrame:(CGRect)frame{ 25 | self = [super initWithFrame:frame]; 26 | if (self) { 27 | self.isAnimation = NO; 28 | [self.layer addSublayer:self.waveLayer]; 29 | [self.layer addSublayer:self.arrowLayer]; 30 | [self _addPanGestureRecognizer]; 31 | } 32 | return self; 33 | } 34 | 35 | 36 | #pragma mark - private method 37 | - (void)_addPanGestureRecognizer{ 38 | UIScreenEdgePanGestureRecognizer*panGestureRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(respondToPanGestureRecognizerAction:)]; 39 | panGestureRecognizer.edges = UIRectEdgeRight; 40 | [self addGestureRecognizer:panGestureRecognizer]; 41 | } 42 | 43 | #pragma mark - gesture event 44 | - (void)respondToPanGestureRecognizerAction:(UIPanGestureRecognizer *)gestureRecognizer{ 45 | CGPoint point = [gestureRecognizer translationInView:self]; 46 | 47 | if (gestureRecognizer.state == UIGestureRecognizerStateBegan ||self.isAnimation == NO) { 48 | self.isAnimation = YES; 49 | self.waveLayer.path = [self getWaveLinePathWithLeftPositionX:0.0]; 50 | }else if (gestureRecognizer.state == UIGestureRecognizerStateChanged){ 51 | self.waveLayer.path = [self getWaveLinePathWithLeftPositionX:fabs(point.x)]; 52 | self.arrowLayer.path = [self getRightArrowPathWithPositionX:fabs(point.x)]; 53 | 54 | self.maxX = fabs(point.x); 55 | }else if(gestureRecognizer.state == UIGestureRecognizerStateCancelled ||gestureRecognizer.state == UIGestureRecognizerStateEnded ||gestureRecognizer.state == UIGestureRecognizerStateFailed){ 56 | self.isAnimation = NO; 57 | 58 | if ([self.delegate respondsToSelector:@selector(waveViewTriggerAction:)] && (self.maxX >=(arrowInitializationDistanceToRightEdge + arrowInitializationDistanceToRightEdge) * rate)) { 59 | self.arrowLayer.path = [self getRightArrowPathWithPositionX:0.0]; 60 | self.waveLayer.path = [self getWaveLinePathWithLeftPositionX:0.0]; 61 | [self.delegate waveViewTriggerAction:self]; 62 | }else{ 63 | [self waveAnimationWithPositionX:fabs(self.maxX)]; 64 | [self arrowAnimationWithPositionX:fabs(self.maxX)]; 65 | } 66 | self.maxX = 0.0f; 67 | } 68 | 69 | 70 | } 71 | #pragma mark - get CGPathRef 72 | -(CGPathRef)getWaveLinePathWithLeftPositionX:(CGFloat)positionX{ 73 | UIBezierPath *waveLine = [UIBezierPath bezierPath]; 74 | CGPoint topPoint = CGPointMake(self.bounds.size.width , 0); 75 | CGPoint midControlPoint = CGPointMake(self.bounds.size.width - positionX, self.bounds.size.height/2); 76 | CGPoint bottomPoint = CGPointMake(self.bounds.size.width , self.bounds.size.height); 77 | 78 | [waveLine moveToPoint:topPoint]; 79 | [waveLine addQuadCurveToPoint:bottomPoint controlPoint:midControlPoint]; 80 | [waveLine closePath]; 81 | 82 | return [waveLine CGPath]; 83 | } 84 | 85 | /** 86 | * draw the arrow path 87 | */ 88 | - (CGPathRef)getRightArrowPathWithPositionX:(CGFloat)positionX{ 89 | UIBezierPath *arrowLine = [UIBezierPath bezierPath]; 90 | CGPoint point1 = CGPointMake(self.bounds.size.width + arrowInitializationDistanceToRightEdge , self.bounds.size.height/2); 91 | CGPoint point2 = CGPointMake(self.bounds.size.width - positionX/rate + arrowInitializationDistanceToRightEdge , self.bounds.size.height/2); 92 | CGPoint point3 = CGPointMake(self.bounds.size.width - positionX/rate + arrowInitializationDistanceToLeft + arrowInitializationDistanceToRightEdge, self.bounds.size.height/2 - 20); 93 | CGPoint point4 = CGPointMake(self.bounds.size.width - positionX/rate + arrowInitializationDistanceToRightEdge - 2 , self.bounds.size.height/2); 94 | CGPoint point5 = CGPointMake(self.bounds.size.width - positionX/rate + arrowInitializationDistanceToLeft + arrowInitializationDistanceToRightEdge, self.bounds.size.height/2 + 20); 95 | 96 | [arrowLine moveToPoint:point1]; 97 | [arrowLine addLineToPoint:point2]; 98 | [arrowLine addLineToPoint:point3]; 99 | [arrowLine moveToPoint:point4]; 100 | [arrowLine addLineToPoint:point5]; 101 | return [arrowLine CGPath]; 102 | } 103 | 104 | #pragma mark - animation 105 | - (void)waveAnimationWithPositionX:(CGFloat)positionX { 106 | CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animationWithKeyPath:@"path"]; 107 | keyAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 108 | NSArray *values = @[ 109 | (id) [self getWaveLinePathWithLeftPositionX:positionX], 110 | (id) [self getWaveLinePathWithLeftPositionX:0.0] 111 | ]; 112 | keyAnimation.values = values; 113 | keyAnimation.duration = .5; 114 | keyAnimation.removedOnCompletion = NO; 115 | keyAnimation.fillMode = kCAFillModeForwards; 116 | keyAnimation.delegate = self; 117 | [self.waveLayer addAnimation:keyAnimation forKey:@"wave_right"]; 118 | 119 | } 120 | 121 | - (void)arrowAnimationWithPositionX:(CGFloat)positionX { 122 | 123 | CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animationWithKeyPath:@"path"]; 124 | keyAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 125 | NSArray *values = @[ 126 | (id) [self getRightArrowPathWithPositionX:positionX], 127 | (id) [self getRightArrowPathWithPositionX:0.0] 128 | ]; 129 | keyAnimation.values = values; 130 | keyAnimation.duration = .5; 131 | keyAnimation.removedOnCompletion = NO; 132 | keyAnimation.fillMode = kCAFillModeForwards; 133 | keyAnimation.delegate = self; 134 | [self.arrowLayer addAnimation:keyAnimation forKey:@"arrow_right"]; 135 | 136 | } 137 | 138 | #pragma mark - CAAnimationDelegate 139 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 140 | if (anim == [self.arrowLayer animationForKey:@"arrow_right"] ) { 141 | self.arrowLayer.path = [self getRightArrowPathWithPositionX:0.0]; 142 | [self.arrowLayer removeAllAnimations]; 143 | 144 | }else if(anim == [self.waveLayer animationForKey:@"wave_right"]){ 145 | self.waveLayer.path = [self getWaveLinePathWithLeftPositionX:0.0]; 146 | [self.waveLayer removeAllAnimations]; 147 | 148 | } 149 | [self _addPanGestureRecognizer]; 150 | } 151 | 152 | #pragma mark - get 153 | - (CAShapeLayer *)waveLayer{ 154 | if (_waveLayer == nil) { 155 | _waveLayer = [CAShapeLayer layer]; 156 | _waveLayer.strokeColor = [[UIColor clearColor] CGColor]; 157 | _waveLayer.lineWidth = 1.0; 158 | _waveLayer.fillColor = waveFillColor; 159 | 160 | } 161 | return _waveLayer; 162 | } 163 | 164 | - (CAShapeLayer *)arrowLayer{ 165 | if (_arrowLayer == nil) { 166 | _arrowLayer = [CAShapeLayer layer]; 167 | _arrowLayer.lineWidth = arrowLineWidth; 168 | _arrowLayer.fillColor = [UIColor clearColor].CGColor; 169 | _arrowLayer.strokeColor = [[UIColor whiteColor] CGColor]; 170 | } 171 | return _arrowLayer; 172 | } 173 | @end 174 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/SecondViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.h 3 | // CADisplayLinkDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SecondViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/SecondViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.m 3 | // CADisplayLinkDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import "SecondViewController.h" 10 | #import "MMSubView.h" 11 | @interface SecondViewController () 12 | 13 | @end 14 | 15 | @implementation SecondViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | self.view.backgroundColor = [UIColor colorWithRed:70/255.0 green:136/255.0 blue:65/255.0 alpha:1]; 20 | MMSubView *view = [[MMSubView alloc] initWithFrame:self.view.bounds]; 21 | 22 | [self.view addSubview:view]; 23 | } 24 | 25 | - (void)didReceiveMemoryWarning { 26 | [super didReceiveMemoryWarning]; 27 | // Dispose of any resources that can be recreated. 28 | } 29 | 30 | /* 31 | #pragma mark - Navigation 32 | 33 | // In a storyboard-based application, you will often want to do a little preparation before navigation 34 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 35 | // Get the new view controller using [segue destinationViewController]. 36 | // Pass the selected object to the new view controller. 37 | } 38 | */ 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CAShapeLayerDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CAShapeLayerDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "MMWaveView.h" 11 | #import "SecondViewController.h" 12 | 13 | @interface ViewController () 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | MMWaveView *view = [[MMWaveView alloc] initWithFrame:self.view.bounds]; 21 | view.delegate = self; 22 | [self.view addSubview:view]; 23 | 24 | } 25 | - (void)didReceiveMemoryWarning { 26 | [super didReceiveMemoryWarning]; 27 | // Dispose of any resources that can be recreated. 28 | } 29 | 30 | #pragma mark - MMWaveViewDelegate 31 | - (void)waveViewTriggerAction:(MMWaveView *)waveView{ 32 | SecondViewController *vc = [[SecondViewController alloc] init]; 33 | [self.navigationController pushViewController:vc animated:YES]; 34 | NSLog(@"respond to event action"); 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CAShapeLayerDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemoTests/CAShapeLayerDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // CAShapeLayerDemoTests.m 3 | // CAShapeLayerDemoTests 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CAShapeLayerDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation CAShapeLayerDemoTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemoUITests/CAShapeLayerDemoUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // CAShapeLayerDemoUITests.m 3 | // CAShapeLayerDemoUITests 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CAShapeLayerDemoUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation CAShapeLayerDemoUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /CAShapeLayerDemo/CAShapeLayerDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /MMWaveView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "MMWaveView" #名称 3 | s.version = "0.0.1" #版本号 4 | s.summary = "The waves of push action" #简短介绍 5 | s.description = <<-DESC 6 | 私有Pods测试 7 | * Markdown 格式 8 | DESC 9 | 10 | s.homepage = "http://aoto.io/" 11 | # s.screenshots = "www.example.com/screenshots_1.gif" 12 | s.license = "MIT" #开源协议 13 | s.author = { "wangyayun" => "wangyayun0629@163.com" } 14 | 15 | s.source = { :git => "https://github.com/YYWDark/MMWaveView.git" } 16 | ## 这里不支持ssh的地址,只支持HTTP和HTTPS,最好使用HTTPS 17 | ## 正常情况下我们会使用稳定的tag版本来访问,如果是在开发测试的时候,不需要发布release版本,直接指向git地址使用 18 | ## 待测试通过完成后我们再发布指定release版本,使用如下方式 19 | #s.source = { :git => "http://EXAMPLE/O2View.git", :tag => version } 20 | 21 | s.platform = :ios, "6.0" #支持的平台及版本,这里我们呢用swift,直接上9.0 22 | s.requires_arc = true #是否使用ARC 23 | 24 | s.source_files = "MMWaveView/**/*.{h,m}" #OC可以使用类似这样"Classes/**/*.{h,m}" 25 | 26 | s.frameworks = 'UIKit', 'QuartzCore', 'Foundation' #所需的framework,多个用逗号隔开 27 | s.module_name = 'MMWaveView' #模块名称 28 | 29 | # s.dependency "JSONKit", "~> 1.4" #依赖关系,该项目所依赖的其他库,如果有多个可以写多个 s.dependency 30 | 31 | end 32 | -------------------------------------------------------------------------------- /MMWaveView/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YYWDark/MMWaveView/52c7bd803c81843c89f6fc2f4c8514c2f1c4ffdf/MMWaveView/.DS_Store -------------------------------------------------------------------------------- /MMWaveView/MMWaveView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMWaveView.h 3 | // CADisplayLinkDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import 10 | @protocol MMWaveViewDelegate; 11 | 12 | @interface MMWaveView : UIView 13 | @property (nonatomic, weak) id delegate; 14 | @end 15 | 16 | @protocol MMWaveViewDelegate 17 | - (void)waveViewTriggerAction:(MMWaveView *)waveView; 18 | @end -------------------------------------------------------------------------------- /MMWaveView/MMWaveView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMWaveView.m 3 | // CADisplayLinkDemo 4 | // 5 | // Created by wyy on 16/11/15. 6 | // Copyright © 2016年 yyx. All rights reserved. 7 | // 8 | 9 | #import "MMWaveView.h" 10 | #define waveFillColor [[UIColor colorWithRed:118/255.0 green:178/255.0 blue:252/255.0 alpha:1] CGColor] 11 | static const CGFloat arrowInitializationDistanceToRightEdge = 20.0f; 12 | static const CGFloat arrowInitializationDistanceToLeft = 20.0f; 13 | static const CGFloat arrowLineWidth = 3.0; 14 | static const NSInteger rate = 4; 15 | 16 | @interface MMWaveView () 17 | @property (nonatomic, strong) CAShapeLayer *waveLayer; 18 | @property (nonatomic, strong) CAShapeLayer *arrowLayer; 19 | @property (nonatomic, assign) BOOL isAnimation; 20 | @property (nonatomic, assign) CGFloat maxX; 21 | @end 22 | 23 | @implementation MMWaveView 24 | -(id)initWithFrame:(CGRect)frame{ 25 | self = [super initWithFrame:frame]; 26 | if (self) { 27 | self.isAnimation = NO; 28 | [self.layer addSublayer:self.waveLayer]; 29 | [self.layer addSublayer:self.arrowLayer]; 30 | [self _addPanGestureRecognizer]; 31 | } 32 | return self; 33 | } 34 | 35 | 36 | #pragma mark - private method 37 | - (void)_addPanGestureRecognizer{ 38 | UIScreenEdgePanGestureRecognizer*panGestureRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(respondToPanGestureRecognizerAction:)]; 39 | panGestureRecognizer.edges = UIRectEdgeRight; 40 | [self addGestureRecognizer:panGestureRecognizer]; 41 | } 42 | 43 | #pragma mark - gesture event 44 | - (void)respondToPanGestureRecognizerAction:(UIPanGestureRecognizer *)gestureRecognizer{ 45 | CGPoint point = [gestureRecognizer translationInView:self]; 46 | 47 | if (gestureRecognizer.state == UIGestureRecognizerStateBegan ||self.isAnimation == NO) { 48 | self.isAnimation = YES; 49 | self.waveLayer.path = [self getWaveLinePathWithLeftPositionX:0.0]; 50 | }else if (gestureRecognizer.state == UIGestureRecognizerStateChanged){ 51 | self.waveLayer.path = [self getWaveLinePathWithLeftPositionX:fabs(point.x)]; 52 | self.arrowLayer.path = [self getRightArrowPathWithPositionX:fabs(point.x)]; 53 | 54 | self.maxX = fabs(point.x); 55 | }else if(gestureRecognizer.state == UIGestureRecognizerStateCancelled ||gestureRecognizer.state == UIGestureRecognizerStateEnded ||gestureRecognizer.state == UIGestureRecognizerStateFailed){ 56 | self.isAnimation = NO; 57 | 58 | if ([self.delegate respondsToSelector:@selector(waveViewTriggerAction:)] && (self.maxX >=(arrowInitializationDistanceToRightEdge + arrowInitializationDistanceToRightEdge) * rate)) { 59 | self.arrowLayer.path = [self getRightArrowPathWithPositionX:0.0]; 60 | self.waveLayer.path = [self getWaveLinePathWithLeftPositionX:0.0]; 61 | [self.delegate waveViewTriggerAction:self]; 62 | }else{ 63 | [self waveAnimationWithPositionX:fabs(self.maxX)]; 64 | [self arrowAnimationWithPositionX:fabs(self.maxX)]; 65 | } 66 | self.maxX = 0.0f; 67 | } 68 | 69 | 70 | } 71 | #pragma mark - get CGPathRef 72 | -(CGPathRef)getWaveLinePathWithLeftPositionX:(CGFloat)positionX{ 73 | UIBezierPath *waveLine = [UIBezierPath bezierPath]; 74 | CGPoint topPoint = CGPointMake(self.bounds.size.width , 0); 75 | CGPoint midControlPoint = CGPointMake(self.bounds.size.width - positionX, self.bounds.size.height/2); 76 | CGPoint bottomPoint = CGPointMake(self.bounds.size.width , self.bounds.size.height); 77 | 78 | [waveLine moveToPoint:topPoint]; 79 | [waveLine addQuadCurveToPoint:bottomPoint controlPoint:midControlPoint]; 80 | [waveLine closePath]; 81 | 82 | return [waveLine CGPath]; 83 | } 84 | 85 | /** 86 | * draw the arrow path 87 | */ 88 | - (CGPathRef)getRightArrowPathWithPositionX:(CGFloat)positionX{ 89 | UIBezierPath *arrowLine = [UIBezierPath bezierPath]; 90 | CGPoint point1 = CGPointMake(self.bounds.size.width + arrowInitializationDistanceToRightEdge , self.bounds.size.height/2); 91 | CGPoint point2 = CGPointMake(self.bounds.size.width - positionX/rate + arrowInitializationDistanceToRightEdge , self.bounds.size.height/2); 92 | CGPoint point3 = CGPointMake(self.bounds.size.width - positionX/rate + arrowInitializationDistanceToLeft + arrowInitializationDistanceToRightEdge, self.bounds.size.height/2 - 20); 93 | CGPoint point4 = CGPointMake(self.bounds.size.width - positionX/rate + arrowInitializationDistanceToRightEdge - 2 , self.bounds.size.height/2); 94 | CGPoint point5 = CGPointMake(self.bounds.size.width - positionX/rate + arrowInitializationDistanceToLeft + arrowInitializationDistanceToRightEdge, self.bounds.size.height/2 + 20); 95 | 96 | [arrowLine moveToPoint:point1]; 97 | [arrowLine addLineToPoint:point2]; 98 | [arrowLine addLineToPoint:point3]; 99 | [arrowLine moveToPoint:point4]; 100 | [arrowLine addLineToPoint:point5]; 101 | return [arrowLine CGPath]; 102 | } 103 | 104 | #pragma mark - animation 105 | - (void)waveAnimationWithPositionX:(CGFloat)positionX { 106 | CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animationWithKeyPath:@"path"]; 107 | keyAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 108 | NSArray *values = @[ 109 | (id) [self getWaveLinePathWithLeftPositionX:positionX], 110 | (id) [self getWaveLinePathWithLeftPositionX:0.0] 111 | ]; 112 | keyAnimation.values = values; 113 | keyAnimation.duration = .5; 114 | keyAnimation.removedOnCompletion = NO; 115 | keyAnimation.fillMode = kCAFillModeForwards; 116 | keyAnimation.delegate = self; 117 | [self.waveLayer addAnimation:keyAnimation forKey:@"wave_right"]; 118 | 119 | } 120 | 121 | - (void)arrowAnimationWithPositionX:(CGFloat)positionX { 122 | 123 | CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animationWithKeyPath:@"path"]; 124 | keyAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 125 | NSArray *values = @[ 126 | (id) [self getRightArrowPathWithPositionX:positionX], 127 | (id) [self getRightArrowPathWithPositionX:0.0] 128 | ]; 129 | keyAnimation.values = values; 130 | keyAnimation.duration = .5; 131 | keyAnimation.removedOnCompletion = NO; 132 | keyAnimation.fillMode = kCAFillModeForwards; 133 | keyAnimation.delegate = self; 134 | [self.arrowLayer addAnimation:keyAnimation forKey:@"arrow_right"]; 135 | 136 | } 137 | 138 | #pragma mark - CAAnimationDelegate 139 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 140 | if (anim == [self.arrowLayer animationForKey:@"arrow_right"] ) { 141 | self.arrowLayer.path = [self getRightArrowPathWithPositionX:0.0]; 142 | [self.arrowLayer removeAllAnimations]; 143 | 144 | }else if(anim == [self.waveLayer animationForKey:@"wave_right"]){ 145 | self.waveLayer.path = [self getWaveLinePathWithLeftPositionX:0.0]; 146 | [self.waveLayer removeAllAnimations]; 147 | 148 | } 149 | [self _addPanGestureRecognizer]; 150 | } 151 | 152 | #pragma mark - get 153 | - (CAShapeLayer *)waveLayer{ 154 | if (_waveLayer == nil) { 155 | _waveLayer = [CAShapeLayer layer]; 156 | _waveLayer.strokeColor = [[UIColor clearColor] CGColor]; 157 | _waveLayer.lineWidth = 1.0; 158 | _waveLayer.fillColor = waveFillColor; 159 | 160 | } 161 | return _waveLayer; 162 | } 163 | 164 | - (CAShapeLayer *)arrowLayer{ 165 | if (_arrowLayer == nil) { 166 | _arrowLayer = [CAShapeLayer layer]; 167 | _arrowLayer.lineWidth = arrowLineWidth; 168 | _arrowLayer.fillColor = [UIColor clearColor].CGColor; 169 | _arrowLayer.strokeColor = [[UIColor whiteColor] CGColor]; 170 | } 171 | return _arrowLayer; 172 | } 173 | @end 174 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Demo效果: 2 | 3 | ![Demo效果.gif](http://upload-images.jianshu.io/upload_images/307963-77440d5ef9003846.gif?imageMogr2/auto-orient/strip) 4 | 5 | ### Installation 6 | 7 | 1.using CocoaPods: 8 | ``` 9 | source 'https://github.com/CocoaPods/Specs.git' 10 | platform :ios, '6.0' 11 | 12 | target 'TargetName' do 13 | pod 'MMWaveView' 14 | end 15 | ``` 16 | 2.by cloning the project into your repository 17 | 18 | 19 | ### How To Use: 20 | ``` 21 | #import "MMWaveView.h" 22 |  MMWaveView *view = [[MMWaveView alloc] initWithFrame:self.view.bounds]; 23 |  view.delegate = self; 24 |  [self.view addSubview:view]; 25 | 26 | #pragma mark - MMWaveViewDelegate 27 | - (void)waveViewTriggerAction:(MMWaveView *)waveView{ 28 |   NSLog(@"respond to event action"); 29 | } 30 | ``` 31 | 当原有工程的某个视图想有这个功能只需要继承`MMWaveView`即可。 32 | 33 | ### 事件响应: 34 | 当手指离开屏幕,整个箭头出现在屏幕则会触发事件响应回调 35 | 简书: 36 | http://www.jianshu.com/p/1be3bee0d6ae 37 | --------------------------------------------------------------------------------