實(shí)例 1 : 簡(jiǎn)易畫板初步實(shí)現(xiàn)
在自定義的繼承于 UIView 的類 (DrawView) 中實(shí)現(xiàn)方法
定義兩個(gè)屬性:
# 用來記錄所有的路徑 需要畫的路徑都放進(jìn)去 然后統(tǒng)一進(jìn)行描畫渲染
@property (strong, nonatomic) NSMutableArray *pathArray;
# 用于記錄每一次路徑 寫成屬性便于在兩個(gè)方法中使用 具體的可以在下面方法中體現(xiàn)
@property (strong, nonatomic) UIBezierPath *path;
// 首先自定義一個(gè)方法 目的是獲取觸目點(diǎn)的坐標(biāo) 這個(gè)方法是結(jié)合觸摸方法獲得的觸目點(diǎn)集合
- (CGPoint)pointWithTouches:(NSSet *)touches
{
# 獲取 touch 對(duì)象的位置
UITouch *touch = [touches anyObject];
return [touch locationInView:self];
}
// 當(dāng)手指觸及屏幕的時(shí)候,也就是要畫線的時(shí)候! 所以, 在開移動(dòng)的時(shí)候的第一點(diǎn), 就是起筆畫圖的起點(diǎn)!
// 起點(diǎn)方法
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
#1 創(chuàng)建路徑 開始點(diǎn)擊 說明要畫一條線了 那么就創(chuàng)一條線
self.path = [UIBezierPath bezierPath];
#2 獲取開始路徑 , 創(chuàng)建一個(gè)路徑就要保存一個(gè)路徑 因?yàn)樽詈笠阉械穆窂斤@示出來 那么就要記住每一條我們創(chuàng)建的路徑 這里我們用的是數(shù)組
[self.pathArray addObject:self.path];
#3 獲取到觸摸點(diǎn) (調(diào)用自定義的方法) 當(dāng)然也可以不封裝方法,直接在這里實(shí)現(xiàn)獲取
CGPoint point = [self pointWithTouches:touches];
// 確定起點(diǎn)在哪里
[self.path moveToPoint:point];
}
// 手指點(diǎn)擊屏幕時(shí)候, 我們獲得起點(diǎn), 那么當(dāng)手指滑動(dòng)的時(shí)候其實(shí)動(dòng)一次就得到一個(gè)終止點(diǎn), 那么由起點(diǎn)到這一點(diǎn)連線, 就實(shí)現(xiàn)了手指如何滑動(dòng)就如何畫圖!
// 手指移動(dòng)畫線
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
#1: 調(diào)方法 獲取觸摸點(diǎn)
CGPoint point = [self pointWithTouches:touches];
#2: 確立終點(diǎn) 由屬性記錄的起點(diǎn)向移動(dòng)手指獲得的終點(diǎn) 畫線
[self.path addLineToPoint:point];
#3: (需要重新繪圖 調(diào)用方法 drawRect方法)
[self setNeedsDisplay];
}```
// 重新繪圖 我們有了路徑 那么就把所有的路徑描繪出來就行了 也就是存在自定義屬性的數(shù)組里面的 Path
```code
- (void)drawRect:(CGRect)rect
{
# 遍歷數(shù)組 取出所有的路徑 描繪一下
for(UIBezierPath *path in self.pathArray)
{
[path stroke];
}
}
這個(gè)是自定義的視圖 View 去視圖控制器中使用就可以實(shí)現(xiàn)效果了
可以添加按鈕去控制線條的一些屬性( 顏色 粗細(xì) ), 就可以實(shí)現(xiàn)了初步效果!
實(shí)例 2 : 實(shí)現(xiàn)扇形的統(tǒng)計(jì)條 結(jié)合 UISlider NSTime
首先是自定義畫圖的 View 中實(shí)現(xiàn)畫扇形
我們需要根據(jù)值得不同, 去繪畫不同弧度的扇形所以首先定義一個(gè)接受扇形的弧度的屬性
@property (assign, nonatomic) float angle;
在繪圖方法中去實(shí)現(xiàn):
- (void)drawRect:(CGRect)rect
{
# 獲取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
# 建一個(gè)弧形的路徑
# 這個(gè)扇形是 從 0*π 到 屬性 angle 大小 只需要改變不同的 angle 就可以控制扇形的大小
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.center radius:200 startAngle:0 endAngle:self.angle clockwise:1];
if (_angle != 0) //等于 0 度時(shí)候就不要顯示了
{
// 定義了一個(gè) Label 去顯示當(dāng)前扇形 占整個(gè)圓的百分比
self.myLabel.text = [NSString stringWithFormat:@"%.2f%%",100*0.5* _angle / M_PI];
# 這兩個(gè)步驟是把圓弧 畫成扇形
[path addLineToPoint:self.center];
[path addLineToPoint:(CGPointMake(self.center.x + 200, self.center.y))];
# 填充一個(gè)隨機(jī)的顏色
[[UIColor colorWithRed:(arc4random()%173)/346.0 + 0.5 green:(arc4random()%173)/346.0 + 0.5 blue:(arc4random()%173)/346.0 + 0.5 alpha: 1] setFill];
}else
{
self.myLabel.text = nil;
}
# 上下文加 路徑
CGContextAddPath(ref, path.CGPath);
# 渲染 類型是 填充
CGContextDrawPath(ref, kCGPathFill);
}
- 在視圖控制器中 加
MyView (自定義的畫圖視圖)
UIButton(控制開始停止)
UISlider(手動(dòng)控制扇形的大小)
UILabel(顯示時(shí)間, 也可以加到 子自定義的View中,你開心就好)
NSTime(自動(dòng)改變扇形大小)
布局就依個(gè)人喜好弄弄吧!
設(shè)置 UISlider 的取值范圍
# 范圍就是 0° 到 360° M_PI 表示 π
_MySlider.maximumValue = 2 * M_PI ;
_MySlider.minimumValue = 0 * M_PI ;
創(chuàng)建屬性 UITime
# 目的就是 每隔 0.2 秒 去執(zhí)行 changeTinmeAction 方法
self.myTime = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(changeTinmeAction) userInfo:nil repeats:1];
// 時(shí)間改變之后走的方法
- (void)changeTinmeAction
{
if (self.MySlider.value <= 2 * M_PI)
{
# 調(diào)用自定義的 UISlider 值改變走的方法
[self changeAction:self.MySlider];
}else
{
# 如果超過 360° 就自動(dòng)的停止 并把 Button 的title 改下
NSLog(@"romve time");
[self.button setTitle:@"GO" forState:(UIControlStateNormal)];
[self.myTime invalidate];
self.myTime = nil;
}
}
// 自定義 Button 的點(diǎn)擊方法
- (void)addTimeAction:(UIButton *)sender
{
# 根據(jù) Button 的 title 判斷 點(diǎn)擊 Button 的時(shí)候我們是為了 暫停計(jì)時(shí) 還是讓時(shí)間開始 走時(shí)間方法
if ([[sender titleForState:(UIControlStateNormal)]isEqualToString:@"STOP"])
{
[self.myTime invalidate];
self.myTime = nil;
[sender setTitle:@"GO" forState:(UIControlStateNormal)];
}
else{
[sender setTitle:@"STOP" forState:(UIControlStateNormal)];
self.myTime = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(changeTinmeAction) userInfo:nil repeats:1];
}
}```
// 自定義的 UISlider 值 Value 發(fā)生改改變 觸及的方法
```code
- (void)changeAction:(UISlider *)sender
{
if (sender.value == 0)
{
# 這個(gè)判斷是為了手動(dòng)調(diào)節(jié)滑塊的時(shí)候 到0的時(shí)候讓扇形也為0度
self.MyView.angle = sender.value;
self.MySlider.value = 0 + DBL_EPSILON;
}else
{
# 這是為了配合時(shí)間的改變
self.MySlider.value = self.MySlider.value + M_PI / 20;
self.MyView.angle = sender.value;
}
# 按比例算時(shí)間
_timeLabel.text = [NSString stringWithFormat:@"%.2f 秒",sender.value/M_PI *0.5 *4.0];
# 一定不能忘了這一步 調(diào)用方法 重新繪圖
[self.MyView setNeedsDisplay];
}```
其實(shí)這樣寫不太準(zhǔn)確, 可以讓自定義 View 的 angle 隨時(shí)間改變字兒方法根據(jù)angle 去改變slider 的值. 不攪和在一起, 更清晰直觀.