CAShapeLayer

CAShapeLayerUIBezierPath的关系:

  1. CAShapeLayershape代表形状的意思,所以需要形状才能生效
  2. 贝塞尔曲线可以创建基于矢量的路径,而UIBezierPath类是对CGPathRef的封装
  3. 贝塞尔曲线给CAShapeLayer提供路径,CAShapeLayer在提供的路径中进行渲染。路径会闭环,所以绘制出了Shape
  4. 用于CAShapeLayer的贝塞尔曲线作为path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线

CAShapeLayer与UIBezierPath画圆

效果图如下:

image

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效果

效果图类似这样(懒自己做图,就百度了一个):

image

我们调用了上面这个画圆效果的代码:

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;
  }
}
 

我们要实现这个效果,是通过strokeStarstrokeEnd这两个属性来完成的,看看官方说明:

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
一天一章
原文地址:https://www.cnblogs.com/hangman/p/5460315.html