CAShapeLayer
与UIBezierPath
的关系:
CAShapeLayer
中shape
代表形状的意思,所以需要形状才能生效- 贝塞尔曲线可以创建基于矢量的路径,而
UIBezierPath
类是对CGPathRef
的封装 - 贝塞尔曲线给
CAShapeLayer
提供路径,CAShapeLayer
在提供的路径中进行渲染。路径会闭环,所以绘制出了Shape
- 用于
CAShapeLayer
的贝塞尔曲线作为path
,其path
是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线
CAShapeLayer与UIBezierPath画圆
效果图如下:
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
|
- (CAShapeLayer *)drawCircle {
CAShapeLayer *circleLayer = [CAShapeLayer layer];
// 指定frame,只是为了设置宽度和高度
circleLayer.frame = CGRectMake(0, 0, 200, 200);
// 设置居中显示
circleLayer.position = self.view.center;
// 设置填充颜色
circleLayer.fillColor = [UIColor clearColor].CGColor;
// 设置线宽
circleLayer.lineWidth = 2.0;
// 设置线的颜色
circleLayer.strokeColor = [UIColor redColor].CGColor;
// 使用UIBezierPath创建路径
CGRect frame = CGRectMake(0, 0, 200, 200);
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:frame];
// 设置CAShapeLayer与UIBezierPath关联
circleLayer.path = circlePath.CGPath;
// 将CAShaperLayer放到某个层上显示
[self.view.layer addSublayer:circleLayer];
return circleLayer;
}
|
注意,我们这里不是放在-drawRect:
方法中调用的。我们直接将这个CAShaperLayer
放到了self.view.layer
上,直接呈现出来。
我们创建一个CAShapeLayer
,然后配置相关属性,然后再通过UIBezierPath
的类方法创建一个内切圆路径,然后将路径指定给CAShapeLayer.path
,这就将两者关联起来了。最后,将这个层放到了self.view.layer
上呈现出来。
CAShapeLayer与UIBezierPath的简单Loading效果
效果图类似这样(懒自己做图,就百度了一个):
我们调用了上面这个画圆效果的代码:
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
|
- (void)drawHalfCircle {
self.loadingLayer = [self drawCircle];
// 这个是用于指定画笔的开始与结束点
self.loadingLayer.strokeStart = 0.0;
self.loadingLayer.strokeEnd = 0.75;
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:@selector(updateCircle)
userInfo:nil
repeats:YES];
}
- (void)updateCircle {
if (self.loadingLayer.strokeEnd > 1 && self.loadingLayer.strokeStart < 1) {
self.loadingLayer.strokeStart += 0.1;
} else if (self.loadingLayer.strokeStart == 0) {
self.loadingLayer.strokeEnd += 0.1;
}
if (self.loadingLayer.strokeEnd == 0) {
self.loadingLayer.strokeStart = 0;
}
if (self.loadingLayer.strokeStart >= 1 && self.loadingLayer.strokeEnd >= 1) {
self.loadingLayer.strokeStart = 0;
[self.timer invalidate];
self.timer = nil;
}
}
|
我们要实现这个效果,是通过strokeStar
和strokeEnd
这两个属性来完成的,看看官方说明:
1
2
3
4
5
6
7
8
9
10
11
|
/* These values define the subregion of the path used to draw the
* stroked outline. The values must be in the range [0,1] with zero
* representing the start of the path and one the end. Values in
* between zero and one are interpolated linearly along the path
* length. strokeStart defaults to zero and strokeEnd to one. Both are
* animatable. */
@property CGFloat strokeStart;
@property CGFloat strokeEnd
|