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

原文地址:https://www.cnblogs.com/520myp1314/p/5234364.html