iOS 谁说程序猿不懂浪漫之 爱心
近来无事,想想IT该怎样才能彰显浪漫情怀,不能口头上说说而已,最关键的是要有可视化的东西展示出来才行~
废话不多说,直接上Demo
HeartView.h
1 // 2 // HeartView.h 3 // DrawHeart 4 // 5 // Created by WQL on 16/3/1. 6 // Copyright © 2016年 WQL. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h> 10 11 @interface HeartView : UIView 12 /** 13 * 比率 14 */ 15 @property (nonatomic,assign) CGFloat rate; 16 /** 17 * 填充的颜色 18 */ 19 @property (nonatomic,strong) UIColor *fillColor; 20 /** 21 * 线条的颜色 22 */ 23 @property (nonatomic,strong) UIColor *strokeColor; 24 /** 25 * 线条的宽度 26 */ 27 @property (nonatomic,assign) CGFloat lineWidth; 28 @end
HeartView.m文件:
1 // 2 // HeartView.m 3 // DrawHeart 4 // 5 // Created by WQL on 16/3/1. 6 // Copyright © 2016年 WQL. All rights reserved. 7 // 8 9 #import "HeartView.h" 10 //间距 11 NSInteger const spaceWidth = 5; 12 //波浪的振幅 13 NSInteger const waveAmplitude = 5; 14 @interface HeartView () 15 { 16 CGFloat t; 17 } 18 @end 19 20 @implementation HeartView 21 22 - (instancetype)initWithFrame:(CGRect)frame 23 { 24 self = [super initWithFrame:frame]; 25 if (self) { 26 [self loadTimer]; 27 } 28 return self; 29 } 30 31 - (void)drawRect:(CGRect)rect 32 { 33 [super drawRect:rect]; 34 35 //上面的两个半圆 半径为整个frame的四分之一 36 CGFloat radius = MIN((self.frame.size.width-spaceWidth*2)/4, (self.frame.size.height-spaceWidth*2)/4); 37 38 //左侧圆心 位于左侧边距+半径宽度 39 CGPoint leftCenter = CGPointMake(spaceWidth+radius, spaceWidth+radius); 40 //右侧圆心 位于左侧圆心的右侧 距离为两倍半径 41 CGPoint rightCenter = CGPointMake(spaceWidth+radius*3, spaceWidth+radius); 42 43 //左侧半圆 44 UIBezierPath *heartLine = [UIBezierPath bezierPathWithArcCenter:leftCenter radius:radius startAngle:M_PI endAngle:0 clockwise:YES]; 45 46 //右侧半圆 47 [heartLine addArcWithCenter:rightCenter radius:radius startAngle:M_PI endAngle:0 clockwise:YES]; 48 49 //曲线连接到新的底部顶点 为了弧线的效果,控制点,坐标x为总宽度减spaceWidth,刚好可以相切,平滑过度 y可以根据需要进行调整,y越大,所画出来的线越接近内切圆弧 50 [heartLine addQuadCurveToPoint:CGPointMake((self.frame.size.width/2), self.frame.size.height-spaceWidth*2) controlPoint:CGPointMake(self.frame.size.width-spaceWidth, self.frame.size.height*0.6)]; 51 52 //用曲线 底部的顶点连接到左侧半圆的左起点 为了弧线的效果,控制点,坐标x为spaceWidth,刚好可以相切,平滑过度。y可以根据需要进行调整,y越大,所画出来的线越接近内切圆弧(效果是越胖) 53 [heartLine addQuadCurveToPoint:CGPointMake(spaceWidth, spaceWidth+radius) controlPoint:CGPointMake(spaceWidth, self.frame.size.height*0.6)]; 54 55 //线条处理 56 [heartLine setLineCapStyle:kCGLineCapRound]; 57 //线宽 58 [self setHeartLineWidthWithPath:heartLine]; 59 //线条的颜色 60 [self setHeartStrokeColor]; 61 62 //根据坐标点连线 63 [heartLine stroke]; 64 //clipToBounds 切掉多余的部分 65 [heartLine addClip]; 66 67 68 //初始化波浪的构成 69 UIBezierPath *waves = [UIBezierPath bezierPath]; 70 71 //首先 把起始点设置为左侧 x坐标为spaceWidth 心形从下往上填充,y坐标需要满足一定的函数关系式,当rate为0时,位置为总高度-2倍的留白距离(spaceWidth)+波浪的振幅;当rate为1时,位置为留白距离(spaceWidth)-振幅。由这两个状态构建函数表达式,即可得到如下表达式 72 CGPoint startPoint = CGPointMake(spaceWidth, (self.frame.size.height-3*spaceWidth+waveAmplitude*2)*(1-self.rate)+spaceWidth-waveAmplitude); 73 [waves moveToPoint:startPoint]; 74 75 //关键的地方来了 波浪线怎么画? 76 //首先,x坐标是从左往右连续的 y坐标是起始的高度加上一定的波动 这里选择了cos函数。5是波动的幅度大小,50控制的是波峰的间距,t是为了让其动起来,随时间发生波动 77 for (int i = 0; i<self.frame.size.width-spaceWidth*2+self.lineWidth*2; i++) { 78 //x是要考虑线宽的 不然的话,会导致填充的宽度不够 y就是在某个值附近波动 79 CGPoint middlePoint = CGPointMake(spaceWidth+i-self.lineWidth, startPoint.y+waveAmplitude*cos(M_PI/50*i+t)); 80 81 [waves addLineToPoint:middlePoint]; 82 } 83 84 //画波浪线的右端 到底部的垂直线 85 [waves addLineToPoint:CGPointMake(self.frame.size.width-spaceWidth*2, self.frame.size.height-spaceWidth*2)]; 86 //画右侧底部的点 到达左侧底部的点之间的横线 87 [waves addLineToPoint:CGPointMake(spaceWidth, self.frame.size.height-spaceWidth*2)]; 88 //设置填充颜色 89 [self setHeartFillColor]; 90 //填充 91 [waves fill]; 92 93 } 94 //设置线条宽度 默认为1 95 - (void)setHeartLineWidthWithPath:(UIBezierPath*)path 96 { 97 CGFloat lineW; 98 if (self.lineWidth) { 99 lineW = self.lineWidth; 100 }else{ 101 lineW = 1; 102 } 103 104 [path setLineWidth:lineW]; 105 } 106 107 //设置线条颜色 108 - (void)setHeartStrokeColor 109 { 110 UIColor *strokColor; 111 if (self.strokeColor) { 112 strokColor = self.strokeColor; 113 }else{ 114 strokColor = [UIColor blackColor]; 115 } 116 117 [strokColor set]; 118 } 119 //设置填充的颜色 120 - (void)setHeartFillColor 121 { 122 UIColor *fillColor; 123 if (self.fillColor) { 124 fillColor = self.fillColor; 125 }else{ 126 fillColor = [UIColor orangeColor]; 127 } 128 129 [fillColor set]; 130 131 } 132 133 //为了实现动态的效果,加一个Timer 134 - (void)loadTimer 135 { 136 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(timerAction) userInfo:nil repeats:YES]; 137 [timer fire]; 138 } 139 //t 是一个影响波浪线的参数,每次修改之,再画,则每次的都不一样,则有动态的效果 140 - (void)timerAction 141 { 142 t += M_PI/50; 143 144 if (t == M_PI) { 145 t = 0; 146 } 147 //修改了t之后 要调用draw方法 148 [self setNeedsDisplay]; 149 } 150 151 @end
一些关键点,我已经注释啦~
下面就是看看怎么使用这个视图了:
ViewController.m中:
1 // 2 // ViewController.m 3 // DrawHeart 4 // 5 // Created by WQL on 16/3/1. 6 // Copyright © 2016年 WQL. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import "HeartView.h" 11 12 NSInteger const heartWidth = 200; 13 NSInteger const heartHeight = 200; 14 15 @interface ViewController () 16 { 17 HeartView *heartView; 18 } 19 @end 20 21 @implementation ViewController 22 23 - (void)viewDidLoad { 24 [super viewDidLoad]; 25 heartView = [[HeartView alloc]initWithFrame:CGRectMake((self.view.frame.size.width-heartWidth)/2, (self.view.frame.size.height-heartHeight)/2, heartWidth, heartHeight)]; 26 27 heartView.rate = 0.5; 28 heartView.lineWidth = 1; 29 heartView.strokeColor = [UIColor blackColor]; 30 heartView.fillColor = [UIColor redColor]; 31 heartView.backgroundColor = [UIColor clearColor]; 32 [self.view addSubview:heartView]; 33 34 [self loadSlider]; 35 } 36 37 - (void)loadSlider 38 { 39 UISlider *valueSlider = [[UISlider alloc]initWithFrame:CGRectMake((self.view.frame.size.width-300)/2, self.view.frame.size.height-150, 300, 50)]; 40 valueSlider.minimumValue = 0.0; 41 valueSlider.maximumValue = 1.0; 42 valueSlider.value = 0.5; 43 [valueSlider addTarget:self action:@selector(valueChangedAction:) forControlEvents:UIControlEventValueChanged]; 44 [self.view addSubview:valueSlider]; 45 } 46 47 - (void)valueChangedAction:(UISlider*)slider 48 { 49 heartView.rate = slider.value; 50 } 51 52 53 - (void)didReceiveMemoryWarning { 54 [super didReceiveMemoryWarning]; 55 // Dispose of any resources that can be recreated. 56 } 57 58 @end
这里我添加了一个slider,为了实现随意设置爱心填充的rate。
哈,下面就是看看效果了:
(请原谅我不会弄gif图,它的实际效果是可以不断晃动的~)
如果有感兴趣的小伙伴可以去下载看一下,地址是:https://github.com/Coolll/DrawHeart.git
欢迎各位园友提出意见和建议,如有不足,请多多指教,拜谢~
这里是博客园的下载地址:Download
posted on 2016-03-02 11:50 独叹梅花瘦2015 阅读(1317) 评论(0) 编辑 收藏 举报