├── AFWaveView ├── AFWaveView.h └── AFWaveView.m ├── AFWaveViewDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── Afry.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── chuyi.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── Afry.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── AFWaveViewDemo.xcscheme │ │ └── xcschememanagement.plist │ └── chuyi.xcuserdatad │ └── xcschemes │ ├── AFWaveViewDemo.xcscheme │ └── xcschememanagement.plist ├── AFWaveViewDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m ├── AFWaveViewDemo1.gif ├── AFWaveViewDemo2.gif └── README.md /AFWaveView/AFWaveView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AFWaveView.h 3 | // AFWaveViewDemo 4 | // 5 | // Created by AfryMask on 15/11/30. 6 | // Copyright © 2015年 AfryMask. All rights reserved. 7 | // 8 | 9 | #import 10 | typedef enum{ 11 | Heart = 0, 12 | Circle = 1 13 | 14 | }WaveStyle; 15 | 16 | @interface AFWaveView : UIView 17 | //可选属性,有默认值 18 | 19 | @property(nonatomic,assign)NSInteger duration;//持续时间,默认1秒 20 | @property(nonatomic,assign)NSInteger maxR;//最大半径,默认50 21 | @property(nonatomic,assign)NSInteger waveCount;//wave层数,默认5 22 | @property(nonatomic,assign)NSInteger waveDelta;//wave间距,默认10 23 | @property(nonatomic,assign)CGFloat boundaryAlpha;//边界透明度(基于wave) 24 | @property(nonatomic,assign)CGFloat maxAlpha;//wave起始透明度,默认1 25 | @property(nonatomic,assign)CGFloat minAlpha;//wave末尾透明度,默认0 26 | @property(nonatomic,assign)CGFloat degree;//清晰度,默认0.05 27 | @property(nonatomic,strong)UIColor *mainColor;//主要颜色,默认红色 28 | @property(nonatomic,assign)NSInteger maxHearts;//wave的最大数量 29 | @property(nonatomic,assign)WaveStyle waveStyle;//wave类型 30 | 31 | 32 | -(instancetype)initWithPoint:(CGPoint)point; 33 | @end 34 | -------------------------------------------------------------------------------- /AFWaveView/AFWaveView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AFWaveView.m 3 | // AFWaveViewDemo 4 | // 5 | // Created by AfryMask on 15/11/30. 6 | // Copyright © 2015年 AfryMask. All rights reserved. 7 | // 8 | 9 | #import "AFWaveView.h" 10 | #define kMaxX 1.138 11 | 12 | @interface AFWaveView () 13 | @property(nonatomic,weak)NSTimer *timer;//计时器 14 | @property(nonatomic,assign)CGFloat r;//圆的当前半径 15 | @end 16 | 17 | static NSInteger heartCount = 0;//心形数量 18 | @implementation AFWaveView 19 | 20 | 21 | + (Class)layerClass { 22 | return [CAShapeLayer class]; 23 | } 24 | 25 | /** 26 | 绘图 27 | */ 28 | - (void)drawRect:(CGRect)rect { 29 | 30 | CGPoint drawPoint = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2); 31 | for (int i = 0; i < self.waveCount; i++) { 32 | 33 | // 如果当前半径为负或超出边界,则不显示 34 | CGFloat currentR = self.r-i*self.waveDelta; 35 | if (currentR < 0 || currentR > self.maxR) { 36 | continue; 37 | } 38 | 39 | // 设定路径 40 | UIBezierPath *path; 41 | 42 | if (_waveStyle == Heart) { 43 | // 心形曲线的绘制 44 | path = [[UIBezierPath alloc] init]; 45 | 46 | // 定位到初始点 47 | float i = -kMaxX; 48 | float y = [self getHeartYWithX:fabs(i) andKey:2]; 49 | [path moveToPoint:CGPointMake(i*currentR+drawPoint.x, -y*currentR/2+drawPoint.y)]; 50 | 51 | // 上半部 52 | for (float i = -kMaxX; i < kMaxX; i += self.degree) { 53 | y = [self getHeartYWithX:fabs(i) andKey:1]; 54 | [path addLineToPoint:CGPointMake(i*currentR+drawPoint.x, -y*currentR/2+drawPoint.y)]; 55 | } 56 | 57 | // 下半部 58 | for (float i = kMaxX; i > -kMaxX; i -= self.degree) { 59 | y = [self getHeartYWithX:fabs(i) andKey:2]; 60 | [path addLineToPoint:CGPointMake(i*currentR+drawPoint.x, -y*currentR/2+drawPoint.y)]; 61 | } 62 | 63 | // 封闭 64 | i = -kMaxX; 65 | y = [self getHeartYWithX:fabs(i) andKey:2]; 66 | [path addLineToPoint:CGPointMake(i*currentR+drawPoint.x, -y*currentR/2+drawPoint.y)]; 67 | 68 | }else { 69 | path = [UIBezierPath bezierPathWithArcCenter:drawPoint radius:currentR startAngle:0 endAngle:M_PI*2 clockwise:NO]; 70 | } 71 | 72 | // 颜色和透明度设置 73 | [self.mainColor set]; 74 | CGFloat currentAlpha = [self getAlphaWithIndex:currentR/(self.maxR*1.0)]; 75 | 76 | // 渲染 77 | [path fillWithBlendMode:kCGBlendModeNormal alpha:currentAlpha]; 78 | [path strokeWithBlendMode:kCGBlendModeNormal alpha:currentAlpha+self.boundaryAlpha]; 79 | } 80 | 81 | } 82 | 83 | /** 84 | 绘图,当到达最大半径的时候移除 85 | */ 86 | -(void)startView:(id)sender{ 87 | self.r += 1; 88 | if (self.r-self.waveCount*self.waveDelta>self.maxR) { 89 | [self.timer invalidate]; 90 | [self removeFromSuperview]; 91 | heartCount -= 1; 92 | } 93 | [self setNeedsDisplay]; 94 | } 95 | 96 | /** 97 | 唯一初始化方法 98 | */ 99 | -(instancetype)initWithPoint:(CGPoint)point{ 100 | if (self = [super init]) { 101 | // view背景颜色设定clear,防止阴影出现 102 | self.backgroundColor=[UIColor clearColor]; 103 | 104 | // 默认动画时间和半径 105 | 106 | self.duration = 1; 107 | self.maxR = 50; 108 | self.waveCount = 3; 109 | self.waveDelta = 10; 110 | self.boundaryAlpha = 0.2; 111 | self.maxAlpha = 1; 112 | self.minAlpha = 0; 113 | self.degree = 0.05; 114 | self.mainColor = [UIColor redColor]; 115 | self.maxHearts = 10; 116 | self.waveStyle = Heart; 117 | // 获取当前点击的位置 118 | 119 | self.center = point; 120 | 121 | 122 | } 123 | return self; 124 | } 125 | 126 | 127 | /** 128 | 令动画开始的方法 129 | */ 130 | -(void)fire{ 131 | if (heartCount > self.maxHearts) { 132 | return; 133 | } 134 | heartCount += 1; 135 | 136 | //设定间隔时间 设定的总时间/半径刻度 137 | CGFloat time = self.duration/(self.maxR*1.0); 138 | self.timer = [NSTimer scheduledTimerWithTimeInterval:time target:self selector:@selector(startView:) userInfo:nil repeats:YES]; 139 | 140 | } 141 | 142 | 143 | 144 | /** 145 | 根据maxR,设定view的frame 146 | */ 147 | -(void)setMaxR:(NSInteger)maxR{ 148 | _maxR = maxR; 149 | self.bounds = CGRectMake(0, 0, maxR*8, maxR*8); 150 | } 151 | 152 | //计算alpha x:当前半径/最大半径 153 | float getAlpha(float x){ 154 | //原数据从0到1 155 | //返回从0.8到0.1的数 156 | return (0.7-x*0.7); 157 | } 158 | 159 | 160 | //获取正确的Alpha值 161 | -(CGFloat)getAlphaWithIndex:(CGFloat)index{ 162 | CGFloat a = self.minAlpha-self.maxAlpha; 163 | CGFloat b = self.maxAlpha; 164 | return a*index + b; 165 | } 166 | 167 | //笛卡尔心形公式 168 | -(CGFloat)getHeartYWithX:(CGFloat)x andKey:(NSInteger)key{ 169 | if (key==1) { 170 | return powf(x, 2.0/3)+powf(powf(x, 4.0/3)-4*powf(x, 2)+4, 1.0/2); 171 | }else{ 172 | return powf(x, 2.0/3)-powf(powf(x, 4.0/3)-4*powf(x, 2)+4, 1.0/2); 173 | } 174 | 175 | 176 | } 177 | 178 | //添加到父控件时自动开始动画 179 | -(void)willMoveToSuperview:(UIView *)newSuperview{ 180 | [self fire]; 181 | } 182 | @end 183 | -------------------------------------------------------------------------------- /AFWaveViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E846178A1C0C68E50060AF1F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E84617891C0C68E50060AF1F /* main.m */; }; 11 | E846178D1C0C68E50060AF1F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E846178C1C0C68E50060AF1F /* AppDelegate.m */; }; 12 | E84617901C0C68E50060AF1F /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E846178F1C0C68E50060AF1F /* ViewController.m */; }; 13 | E84617931C0C68E50060AF1F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E84617911C0C68E50060AF1F /* Main.storyboard */; }; 14 | E84617951C0C68E50060AF1F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E84617941C0C68E50060AF1F /* Assets.xcassets */; }; 15 | E84617981C0C68E50060AF1F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E84617961C0C68E50060AF1F /* LaunchScreen.storyboard */; }; 16 | E84617AD1C0C73950060AF1F /* AFWaveView.m in Sources */ = {isa = PBXBuildFile; fileRef = E84617AC1C0C73950060AF1F /* AFWaveView.m */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 3E3D22941D53926B007F710A /* AFWaveViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AFWaveViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | E84617891C0C68E50060AF1F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 22 | E846178B1C0C68E50060AF1F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 23 | E846178C1C0C68E50060AF1F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 24 | E846178E1C0C68E50060AF1F /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 25 | E846178F1C0C68E50060AF1F /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 26 | E84617921C0C68E50060AF1F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 27 | E84617941C0C68E50060AF1F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 28 | E84617971C0C68E50060AF1F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 29 | E84617991C0C68E50060AF1F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | E84617AB1C0C73950060AF1F /* AFWaveView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFWaveView.h; sourceTree = ""; }; 31 | E84617AC1C0C73950060AF1F /* AFWaveView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFWaveView.m; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | E84617821C0C68E50060AF1F /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | E846177C1C0C68E50060AF1F = { 46 | isa = PBXGroup; 47 | children = ( 48 | E84617AA1C0C73950060AF1F /* AFWaveView */, 49 | E84617871C0C68E50060AF1F /* AFWaveViewDemo */, 50 | 3E3D22941D53926B007F710A /* AFWaveViewDemo.app */, 51 | ); 52 | sourceTree = ""; 53 | }; 54 | E84617871C0C68E50060AF1F /* AFWaveViewDemo */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | E846178E1C0C68E50060AF1F /* ViewController.h */, 58 | E846178F1C0C68E50060AF1F /* ViewController.m */, 59 | E84617881C0C68E50060AF1F /* Supporting Files */, 60 | ); 61 | path = AFWaveViewDemo; 62 | sourceTree = ""; 63 | }; 64 | E84617881C0C68E50060AF1F /* Supporting Files */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | E846178B1C0C68E50060AF1F /* AppDelegate.h */, 68 | E846178C1C0C68E50060AF1F /* AppDelegate.m */, 69 | E84617911C0C68E50060AF1F /* Main.storyboard */, 70 | E84617961C0C68E50060AF1F /* LaunchScreen.storyboard */, 71 | E84617991C0C68E50060AF1F /* Info.plist */, 72 | E84617941C0C68E50060AF1F /* Assets.xcassets */, 73 | E84617891C0C68E50060AF1F /* main.m */, 74 | ); 75 | name = "Supporting Files"; 76 | sourceTree = ""; 77 | }; 78 | E84617AA1C0C73950060AF1F /* AFWaveView */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | E84617AB1C0C73950060AF1F /* AFWaveView.h */, 82 | E84617AC1C0C73950060AF1F /* AFWaveView.m */, 83 | ); 84 | path = AFWaveView; 85 | sourceTree = ""; 86 | }; 87 | /* End PBXGroup section */ 88 | 89 | /* Begin PBXNativeTarget section */ 90 | E84617841C0C68E50060AF1F /* AFWaveViewDemo */ = { 91 | isa = PBXNativeTarget; 92 | buildConfigurationList = E846179C1C0C68E50060AF1F /* Build configuration list for PBXNativeTarget "AFWaveViewDemo" */; 93 | buildPhases = ( 94 | E84617811C0C68E50060AF1F /* Sources */, 95 | E84617821C0C68E50060AF1F /* Frameworks */, 96 | E84617831C0C68E50060AF1F /* Resources */, 97 | ); 98 | buildRules = ( 99 | ); 100 | dependencies = ( 101 | ); 102 | name = AFWaveViewDemo; 103 | productName = AFWaveViewDemo; 104 | productReference = 3E3D22941D53926B007F710A /* AFWaveViewDemo.app */; 105 | productType = "com.apple.product-type.application"; 106 | }; 107 | /* End PBXNativeTarget section */ 108 | 109 | /* Begin PBXProject section */ 110 | E846177D1C0C68E50060AF1F /* Project object */ = { 111 | isa = PBXProject; 112 | attributes = { 113 | LastUpgradeCheck = 0710; 114 | ORGANIZATIONNAME = Afry; 115 | TargetAttributes = { 116 | E84617841C0C68E50060AF1F = { 117 | CreatedOnToolsVersion = 7.1; 118 | DevelopmentTeam = F7JAV3CR6S; 119 | DevelopmentTeamName = "Blink Academy Limited"; 120 | }; 121 | }; 122 | }; 123 | buildConfigurationList = E84617801C0C68E50060AF1F /* Build configuration list for PBXProject "AFWaveViewDemo" */; 124 | compatibilityVersion = "Xcode 3.2"; 125 | developmentRegion = English; 126 | hasScannedForEncodings = 0; 127 | knownRegions = ( 128 | en, 129 | Base, 130 | ); 131 | mainGroup = E846177C1C0C68E50060AF1F; 132 | productRefGroup = E846177C1C0C68E50060AF1F; 133 | projectDirPath = ""; 134 | projectRoot = ""; 135 | targets = ( 136 | E84617841C0C68E50060AF1F /* AFWaveViewDemo */, 137 | ); 138 | }; 139 | /* End PBXProject section */ 140 | 141 | /* Begin PBXResourcesBuildPhase section */ 142 | E84617831C0C68E50060AF1F /* Resources */ = { 143 | isa = PBXResourcesBuildPhase; 144 | buildActionMask = 2147483647; 145 | files = ( 146 | E84617981C0C68E50060AF1F /* LaunchScreen.storyboard in Resources */, 147 | E84617951C0C68E50060AF1F /* Assets.xcassets in Resources */, 148 | E84617931C0C68E50060AF1F /* Main.storyboard in Resources */, 149 | ); 150 | runOnlyForDeploymentPostprocessing = 0; 151 | }; 152 | /* End PBXResourcesBuildPhase section */ 153 | 154 | /* Begin PBXSourcesBuildPhase section */ 155 | E84617811C0C68E50060AF1F /* Sources */ = { 156 | isa = PBXSourcesBuildPhase; 157 | buildActionMask = 2147483647; 158 | files = ( 159 | E84617AD1C0C73950060AF1F /* AFWaveView.m in Sources */, 160 | E84617901C0C68E50060AF1F /* ViewController.m in Sources */, 161 | E846178D1C0C68E50060AF1F /* AppDelegate.m in Sources */, 162 | E846178A1C0C68E50060AF1F /* main.m in Sources */, 163 | ); 164 | runOnlyForDeploymentPostprocessing = 0; 165 | }; 166 | /* End PBXSourcesBuildPhase section */ 167 | 168 | /* Begin PBXVariantGroup section */ 169 | E84617911C0C68E50060AF1F /* Main.storyboard */ = { 170 | isa = PBXVariantGroup; 171 | children = ( 172 | E84617921C0C68E50060AF1F /* Base */, 173 | ); 174 | name = Main.storyboard; 175 | sourceTree = ""; 176 | }; 177 | E84617961C0C68E50060AF1F /* LaunchScreen.storyboard */ = { 178 | isa = PBXVariantGroup; 179 | children = ( 180 | E84617971C0C68E50060AF1F /* Base */, 181 | ); 182 | name = LaunchScreen.storyboard; 183 | sourceTree = ""; 184 | }; 185 | /* End PBXVariantGroup section */ 186 | 187 | /* Begin XCBuildConfiguration section */ 188 | E846179A1C0C68E50060AF1F /* Debug */ = { 189 | isa = XCBuildConfiguration; 190 | buildSettings = { 191 | ALWAYS_SEARCH_USER_PATHS = NO; 192 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 193 | CLANG_CXX_LIBRARY = "libc++"; 194 | CLANG_ENABLE_MODULES = YES; 195 | CLANG_ENABLE_OBJC_ARC = YES; 196 | CLANG_WARN_BOOL_CONVERSION = YES; 197 | CLANG_WARN_CONSTANT_CONVERSION = YES; 198 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 199 | CLANG_WARN_EMPTY_BODY = YES; 200 | CLANG_WARN_ENUM_CONVERSION = YES; 201 | CLANG_WARN_INT_CONVERSION = YES; 202 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 203 | CLANG_WARN_UNREACHABLE_CODE = YES; 204 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 205 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 206 | COPY_PHASE_STRIP = NO; 207 | DEBUG_INFORMATION_FORMAT = dwarf; 208 | ENABLE_STRICT_OBJC_MSGSEND = YES; 209 | ENABLE_TESTABILITY = YES; 210 | GCC_C_LANGUAGE_STANDARD = gnu99; 211 | GCC_DYNAMIC_NO_PIC = NO; 212 | GCC_NO_COMMON_BLOCKS = YES; 213 | GCC_OPTIMIZATION_LEVEL = 0; 214 | GCC_PREPROCESSOR_DEFINITIONS = ( 215 | "DEBUG=1", 216 | "$(inherited)", 217 | ); 218 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 219 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 220 | GCC_WARN_UNDECLARED_SELECTOR = YES; 221 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 222 | GCC_WARN_UNUSED_FUNCTION = YES; 223 | GCC_WARN_UNUSED_VARIABLE = YES; 224 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 225 | MTL_ENABLE_DEBUG_INFO = YES; 226 | ONLY_ACTIVE_ARCH = YES; 227 | SDKROOT = iphoneos; 228 | TARGETED_DEVICE_FAMILY = "1,2"; 229 | }; 230 | name = Debug; 231 | }; 232 | E846179B1C0C68E50060AF1F /* Release */ = { 233 | isa = XCBuildConfiguration; 234 | buildSettings = { 235 | ALWAYS_SEARCH_USER_PATHS = NO; 236 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 237 | CLANG_CXX_LIBRARY = "libc++"; 238 | CLANG_ENABLE_MODULES = YES; 239 | CLANG_ENABLE_OBJC_ARC = YES; 240 | CLANG_WARN_BOOL_CONVERSION = YES; 241 | CLANG_WARN_CONSTANT_CONVERSION = YES; 242 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 243 | CLANG_WARN_EMPTY_BODY = YES; 244 | CLANG_WARN_ENUM_CONVERSION = YES; 245 | CLANG_WARN_INT_CONVERSION = YES; 246 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 247 | CLANG_WARN_UNREACHABLE_CODE = YES; 248 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 249 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 250 | COPY_PHASE_STRIP = NO; 251 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 252 | ENABLE_NS_ASSERTIONS = NO; 253 | ENABLE_STRICT_OBJC_MSGSEND = YES; 254 | GCC_C_LANGUAGE_STANDARD = gnu99; 255 | GCC_NO_COMMON_BLOCKS = YES; 256 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 257 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 258 | GCC_WARN_UNDECLARED_SELECTOR = YES; 259 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 260 | GCC_WARN_UNUSED_FUNCTION = YES; 261 | GCC_WARN_UNUSED_VARIABLE = YES; 262 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 263 | MTL_ENABLE_DEBUG_INFO = NO; 264 | SDKROOT = iphoneos; 265 | TARGETED_DEVICE_FAMILY = "1,2"; 266 | VALIDATE_PRODUCT = YES; 267 | }; 268 | name = Release; 269 | }; 270 | E846179D1C0C68E50060AF1F /* Debug */ = { 271 | isa = XCBuildConfiguration; 272 | buildSettings = { 273 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 274 | INFOPLIST_FILE = AFWaveViewDemo/Info.plist; 275 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 276 | PRODUCT_BUNDLE_IDENTIFIER = com.Afry.www.AFWaveViewDemo; 277 | PRODUCT_NAME = "$(TARGET_NAME)"; 278 | }; 279 | name = Debug; 280 | }; 281 | E846179E1C0C68E50060AF1F /* Release */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 285 | INFOPLIST_FILE = AFWaveViewDemo/Info.plist; 286 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 287 | PRODUCT_BUNDLE_IDENTIFIER = com.Afry.www.AFWaveViewDemo; 288 | PRODUCT_NAME = "$(TARGET_NAME)"; 289 | }; 290 | name = Release; 291 | }; 292 | /* End XCBuildConfiguration section */ 293 | 294 | /* Begin XCConfigurationList section */ 295 | E84617801C0C68E50060AF1F /* Build configuration list for PBXProject "AFWaveViewDemo" */ = { 296 | isa = XCConfigurationList; 297 | buildConfigurations = ( 298 | E846179A1C0C68E50060AF1F /* Debug */, 299 | E846179B1C0C68E50060AF1F /* Release */, 300 | ); 301 | defaultConfigurationIsVisible = 0; 302 | defaultConfigurationName = Release; 303 | }; 304 | E846179C1C0C68E50060AF1F /* Build configuration list for PBXNativeTarget "AFWaveViewDemo" */ = { 305 | isa = XCConfigurationList; 306 | buildConfigurations = ( 307 | E846179D1C0C68E50060AF1F /* Debug */, 308 | E846179E1C0C68E50060AF1F /* Release */, 309 | ); 310 | defaultConfigurationIsVisible = 0; 311 | defaultConfigurationName = Release; 312 | }; 313 | /* End XCConfigurationList section */ 314 | }; 315 | rootObject = E846177D1C0C68E50060AF1F /* Project object */; 316 | } 317 | -------------------------------------------------------------------------------- /AFWaveViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AFWaveViewDemo.xcodeproj/project.xcworkspace/xcuserdata/Afry.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AfryMask/AFWaveView/6ea0d2116e4f76029f683ebbafc7c5ab537ec5db/AFWaveViewDemo.xcodeproj/project.xcworkspace/xcuserdata/Afry.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AFWaveViewDemo.xcodeproj/project.xcworkspace/xcuserdata/chuyi.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AfryMask/AFWaveView/6ea0d2116e4f76029f683ebbafc7c5ab537ec5db/AFWaveViewDemo.xcodeproj/project.xcworkspace/xcuserdata/chuyi.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AFWaveViewDemo.xcodeproj/xcuserdata/Afry.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /AFWaveViewDemo.xcodeproj/xcuserdata/Afry.xcuserdatad/xcschemes/AFWaveViewDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /AFWaveViewDemo.xcodeproj/xcuserdata/Afry.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AFWaveViewDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | E84617841C0C68E50060AF1F 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /AFWaveViewDemo.xcodeproj/xcuserdata/chuyi.xcuserdatad/xcschemes/AFWaveViewDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /AFWaveViewDemo.xcodeproj/xcuserdata/chuyi.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AFWaveViewDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | E84617841C0C68E50060AF1F 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /AFWaveViewDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // AFWaveViewDemo 4 | // 5 | // Created by AfryMask on 15/11/30. 6 | // Copyright © 2015年 AfryMask. 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 | -------------------------------------------------------------------------------- /AFWaveViewDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // AFWaveViewDemo 4 | // 5 | // Created by AfryMask on 15/11/30. 6 | // Copyright © 2015年 AfryMask. 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 | -------------------------------------------------------------------------------- /AFWaveViewDemo/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 | } -------------------------------------------------------------------------------- /AFWaveViewDemo/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 | 29 | -------------------------------------------------------------------------------- /AFWaveViewDemo/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 | -------------------------------------------------------------------------------- /AFWaveViewDemo/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 | -------------------------------------------------------------------------------- /AFWaveViewDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // AFWaveViewDemo 4 | // 5 | // Created by AfryMask on 15/11/30. 6 | // Copyright © 2015年 AfryMask. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /AFWaveViewDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // AFWaveViewDemo 4 | // 5 | // Created by Afry on 15/11/30. 6 | // Copyright © 2015年 AfryMask. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "AFWaveView.h" 11 | 12 | @interface ViewController () 13 | @property(nonatomic,weak)AFWaveView *waveView; 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | self.view.backgroundColor=[UIColor whiteColor]; 21 | 22 | } 23 | 24 | -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 25 | 26 | UITouch *t = touches.anyObject; 27 | CGPoint p = [t locationInView:self.view]; 28 | 29 | AFWaveView *waveView = [[AFWaveView alloc]initWithPoint:p]; 30 | 31 | // waveView.maxR=50; 32 | // waveView.duration=2; 33 | // waveView.waveDelta=10; 34 | // waveView.waveCount=1; 35 | // waveView.maxAlpha=1; 36 | // waveView.minAlpha=0; 37 | waveView.waveStyle = Circle; 38 | // waveView.waveStyle = Heart; 39 | waveView.mainColor = [UIColor colorWithRed:0 green:0.7 blue:1 alpha:1]; 40 | // waveView.boundaryAlpha = 0.8; 41 | 42 | [self.view addSubview:waveView]; 43 | 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /AFWaveViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AFWaveViewDemo 4 | // 5 | // Created by Afry on 15/11/30. 6 | // Copyright © 2015年 Afry. 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 | -------------------------------------------------------------------------------- /AFWaveViewDemo1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AfryMask/AFWaveView/6ea0d2116e4f76029f683ebbafc7c5ab537ec5db/AFWaveViewDemo1.gif -------------------------------------------------------------------------------- /AFWaveViewDemo2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AfryMask/AFWaveView/6ea0d2116e4f76029f683ebbafc7c5ab537ec5db/AFWaveViewDemo2.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AFWaveView 2 | 3 | Animation with heart shape witch can wave (use René Descartes line) 4 | 5 | 波浪效果,心形波浪图像,笛卡尔曲线 6 | 7 | ![Alt text](./AFWaveViewDemo1.gif) 8 | 9 | ![Alt text](./AFWaveViewDemo2.gif) 10 | 11 | # To ues: 12 | 13 | 1.import AFWaveView.h and AFWaveView.m 14 | 15 | (导入头文件) 16 | 17 | 2.written these code in "touchesBegan" 18 | 19 | (在touchesBegan中写入下面的代码) 20 | 21 | ``` 22 | UITouch *t = touches.anyObject; 23 | CGPoint p = [t locationInView:self.view]; 24 | AFWaveView *waveView = [[AFWaveView alloc]initWithPoint:p]; 25 | [self.view addSubview:waveView]; 26 | ``` 27 | 3.optional 28 | 29 | (可选项) 30 | ``` 31 | waveView.maxR=50; //radius of the heart 32 | waveView.duration=2; //the duration of the heart show 33 | waveView.waveDelta=10; //the delta between wave to wave 34 | waveView.waveCount=3; //the count of wave 35 | waveView.waveStyle = Circle; //style of the wave 36 | //read more? Clone it :) 37 | ``` 38 | --------------------------------------------------------------------------------