IOS Core Animation Advanced Techniques的学习笔记(五)

第六章:Specialized Layers

 


类别


用途


CAEmitterLayer


用于实现基于Core Animation粒子发射系统。发射器层对象控制粒子的生成和起源


CAGradientLayer


用于绘制一个颜色渐变填充图层的形状(所有圆角矩形边界内的部分)


CAEAGLLayer/CAOpenGLLayer


用于设置需要使用OpenGL ES(iOS)或OpenGL(OS X)绘制的内容与内容储备。


CAReplicatorLayer


当你想自动生成一个或多个子层的拷贝。复制器为你生成拷贝并使用你指定的属性值以修改复制品的外观和属性。


CAScrollLayer


用于管理由多个子区域组成的大的可滚动区域


CAShaperLayer


用于绘制三次贝塞尔曲线。CAShaperLayer对绘制基于路径的形状非常有帮助。因为CAShaperLayer总是生成一个最新的路径。而如果将路径画在图层储备中,一旦图层被缩放,形状就变形了。


CATextLayer


用于渲染一个无格式或属性文本字符


CATransformLayer


用于渲染一个真3D的图层层级。而不是由其他图层类实现的2D图层层级。


QCCompositionLayer


用于渲染一个Quartz组件元素(仅在OS X中有效)

 

CAShapeLayer

使用CGPath绘制矢量图,UIBezierPath类可以创建基于矢量的路径,此类是Core Graphics框架关于path的一个封装。它可以定义简单的形状,如椭圆或者矩形,或者有多个直线和曲线段组成的形状。

源码在这里下载:http://www.informit.com/title/9780133440751

例子6.1

[objc] view plaincopyprint?

  1. @interface ViewController ()
  2. @property (nonatomic, weak) IBOutlet UIView *containerView;
  3. @end
  4. @implementation ViewController
  5. - (void)viewDidLoad
  6. {
  7. [super viewDidLoad];
  8. //create path
  9. UIBezierPath *path = [[UIBezierPath alloc] init];
  10. [path moveToPoint:CGPointMake(175, 100)];
  11. [path addArcWithCenter:CGPointMake(150, 100) radius:25 startAngle:0 endAngle:2*M_PI clockwise:YES];
  12. [path moveToPoint:CGPointMake(150, 125)];
  13. [path addLineToPoint:CGPointMake(150, 175)];
  14. [path addLineToPoint:CGPointMake(125, 225)];
  15. [path moveToPoint:CGPointMake(150, 175)];
  16. [path addLineToPoint:CGPointMake(175, 225)];
  17. [path moveToPoint:CGPointMake(100, 150)];
  18. [path addLineToPoint:CGPointMake(200, 150)];
  19. //create shape layer
  20. CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  21. shapeLayer.strokeColor = [UIColor redColor].CGColor;
  22. shapeLayer.fillColor = [UIColor clearColor].CGColor;
  23. shapeLayer.lineWidth = 5;
  24. shapeLayer.lineJoin = kCALineJoinRound;
  25. shapeLayer.lineCap = kCALineCapRound;
  26. shapeLayer.path = path.CGPath;
  27. //add it to our view
  28. [self.containerView.layer addSublayer:shapeLayer];
  29. }
  30. @end

先说说CAShapeLayer的属性设置

1. 线颜色

[objc] view plaincopyprint?

  1. @property CGColorRef strokeColor

2. 填充色

[objc] view plaincopyprint?

  1. @property CGColorRef fillColor

3. 填充规则

[objc] view plaincopyprint?

  1. @property(copy) NSString *fillRule

修改例子6.1

默认值kCAFillRuleNonZero的情况

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //create path
  5. UIBezierPath *path = [[UIBezierPath alloc] init];
  6. [path moveToPoint:CGPointMake(200, 150)];
  7. [path addArcWithCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2*M_PI clockwise:YES];
  8. [path moveToPoint:CGPointMake(250, 150)];
  9. [path addArcWithCenter:CGPointMake(150, 150) radius:100 startAngle:0 endAngle:2*M_PI clockwise:YES];
  10. //create shape layer
  11. CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  12. shapeLayer.strokeColor = [UIColor redColor].CGColor;
  13. shapeLayer.fillColor = [UIColor blueColor].CGColor;
  14. shapeLayer.fillRule = kCAFillRuleNonZero;
  15. //shapeLayer.fillRule = kCAFillRuleEvenOdd;
  16. shapeLayer.lineWidth = 5;
  17. shapeLayer.lineJoin = kCALineJoinBevel;
  18. shapeLayer.lineCap = kCALineCapRound;
  19. shapeLayer.path = path.CGPath;
  20. //add it to our view
  21. [self.containerView.layer addSublayer:shapeLayer];
  22. }


再修改

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //create path
  5. UIBezierPath *path = [[UIBezierPath alloc] init];
  6. [path moveToPoint:CGPointMake(200, 150)];
  7. [path addArcWithCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2*M_PI clockwise:YES];
  8. [path moveToPoint:CGPointMake(250, 150)];
  9. [path addArcWithCenter:CGPointMake(150, 150) radius:100 startAngle:0 endAngle:-2*M_PI clockwise:NO];
  10. //create shape layer
  11. CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  12. shapeLayer.strokeColor = [UIColor redColor].CGColor;
  13. shapeLayer.fillColor = [UIColor blueColor].CGColor;
  14. shapeLayer.fillRule = kCAFillRuleNonZero;
  15. //shapeLayer.fillRule = kCAFillRuleEvenOdd;
  16. shapeLayer.lineWidth = 5;
  17. shapeLayer.lineJoin = kCALineJoinBevel;
  18. shapeLayer.lineCap = kCALineCapRound;
  19. shapeLayer.path = path.CGPath;
  20. //add it to our view
  21. [self.containerView.layer addSublayer:shapeLayer];
  22. }

kCAFillRuleEvenOdd的情况

修改代码

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //create path
  5. UIBezierPath *path = [[UIBezierPath alloc] init];
  6. [path moveToPoint:CGPointMake(200, 150)];
  7. [path addArcWithCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2*M_PI clockwise:YES];
  8. [path moveToPoint:CGPointMake(250, 150)];
  9. [path addArcWithCenter:CGPointMake(150, 150) radius:100 startAngle:0 endAngle:2*M_PI clockwise:YES];
  10. //create shape layer
  11. CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  12. shapeLayer.strokeColor = [UIColor redColor].CGColor;
  13. shapeLayer.fillColor = [UIColor blueColor].CGColor;
  14. //shapeLayer.fillRule = kCAFillRuleNonZero;
  15. shapeLayer.fillRule = kCAFillRuleEvenOdd;
  16. shapeLayer.lineWidth = 5;
  17. shapeLayer.lineJoin = kCALineJoinBevel;
  18. shapeLayer.lineCap = kCALineCapRound;
  19. shapeLayer.path = path.CGPath;
  20. //add it to our view
  21. [self.containerView.layer addSublayer:shapeLayer];
  22. }

同样修改

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //create path
  5. UIBezierPath *path = [[UIBezierPath alloc] init];
  6. [path moveToPoint:CGPointMake(200, 150)];
  7. [path addArcWithCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2*M_PI clockwise:YES];
  8. [path moveToPoint:CGPointMake(250, 150)];
  9. [path addArcWithCenter:CGPointMake(150, 150) radius:100 startAngle:0 endAngle:-2*M_PI clockwise:NO];
  10. //create shape layer
  11. CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  12. shapeLayer.strokeColor = [UIColor redColor].CGColor;
  13. shapeLayer.fillColor = [UIColor blueColor].CGColor;
  14. //shapeLayer.fillRule = kCAFillRuleNonZero;
  15. shapeLayer.fillRule = kCAFillRuleEvenOdd;
  16. shapeLayer.lineWidth = 5;
  17. shapeLayer.lineJoin = kCALineJoinBevel;
  18. shapeLayer.lineCap = kCALineCapRound;
  19. shapeLayer.path = path.CGPath;
  20. //add it to our view
  21. [self.containerView.layer addSublayer:shapeLayer];
  22. }


继续为了看清奇偶的效果,画3个同方向圆圈

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //create path
  5. UIBezierPath *path = [[UIBezierPath alloc] init];
  6. [path moveToPoint:CGPointMake(200, 150)];
  7. [path addArcWithCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2*M_PI clockwise:YES];
  8. [path moveToPoint:CGPointMake(250, 150)];
  9. [path addArcWithCenter:CGPointMake(150, 150) radius:100 startAngle:0 endAngle:2*M_PI clockwise:YES];
  10. [path moveToPoint:CGPointMake(300, 150)];
  11. [path addArcWithCenter:CGPointMake(150, 150) radius:150 startAngle:0 endAngle:2*M_PI clockwise:YES];
  12. //create shape layer
  13. CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  14. shapeLayer.strokeColor = [UIColor redColor].CGColor;
  15. shapeLayer.fillColor = [UIColor blueColor].CGColor;
  16. //shapeLayer.fillRule = kCAFillRuleNonZero;
  17. shapeLayer.fillRule = kCAFillRuleEvenOdd;
  18. shapeLayer.lineWidth = 5;
  19. shapeLayer.lineJoin = kCALineJoinBevel;
  20. shapeLayer.lineCap = kCALineCapRound;
  21. shapeLayer.path = path.CGPath;
  22. //add it to our view
  23. [self.containerView.layer addSublayer:shapeLayer];
  24. }

以上我们应该清楚不同的规则了吧,挪用别人的描述

nonzero字面意思是“非零”。按该规则,要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点情况。从0开始计数,路径从左向右穿过射线则计数加1,从右向左穿过射线则计数减1。得出计数结果后,如果结果是0,则认为点在图形外部,否则认为在内部。下图演示了nonzero规则:

evenodd字面意思是“奇偶”。按该规则,要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点的数量。如果结果是奇数则认为点在内部,是偶数则认为点在外部。下图演示了evenodd 规则:

4. 线端点类型

[objc] view plaincopyprint?

  1. @property(copy) NSString *lineCap

5. 线连接类型

[objc] view plaincopyprint?

  1. @property(copy) NSString *lineJoin

6. 线宽

[objc] view plaincopyprint?

  1. @property CGFloat lineWidth

7. 线型模板

[objc] view plaincopyprint?

  1. @property(copy) NSArray *lineDashPattern

这是一个NSNumber的数组,索引从1开始记,奇数位数值表示实线长度,偶数位数值表示空白长度

8. 线型模板的起始位置

[objc] view plaincopyprint?

  1. @property CGFloat lineDashPhase

修改例子6.1,为了看得更清楚,把lineCap的设置注释,,自己看看不注释是什么结果

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //create path
  5. UIBezierPath *path = [[UIBezierPath alloc] init];
  6. [path moveToPoint:CGPointMake(175, 100)];
  7. [path addArcWithCenter:CGPointMake(150, 100) radius:25 startAngle:0 endAngle:2*M_PI clockwise:YES];
  8. [path moveToPoint:CGPointMake(150, 125)];
  9. [path addLineToPoint:CGPointMake(150, 175)];
  10. [path addLineToPoint:CGPointMake(125, 225)];
  11. [path moveToPoint:CGPointMake(150, 175)];
  12. [path addLineToPoint:CGPointMake(175, 225)];
  13. [path moveToPoint:CGPointMake(100, 150)];
  14. [path addLineToPoint:CGPointMake(200, 150)];
  15. //create shape layer
  16. CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  17. shapeLayer.strokeColor = [UIColor redColor].CGColor;
  18. shapeLayer.fillColor = [UIColor clearColor].CGColor;
  19. shapeLayer.lineWidth = 5;
  20. shapeLayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:20], [NSNumber numberWithInt:10], [NSNumber numberWithInt:10], [NSNumber numberWithInt:2], nil nil];
  21. //shapeLayer.lineDashPhase = 15;
  22. shapeLayer.lineJoin = kCALineJoinBevel;
  23. //shapeLayer.lineCap = kCALineCapRound;
  24. //    shapeLayer.strokeStart = 0.1;
  25. //    shapeLayer.strokeEnd = 0.6;
  26. shapeLayer.path = path.CGPath;
  27. //add it to our view
  28. [self.containerView.layer addSublayer:shapeLayer];
  29. }


再修改lineDashPhase值=15

9. 最大斜接长度。

[objc] view plaincopyprint?

  1. @property CGFloat miterLimit

斜接长度指的是在两条线交汇处内角和外角之间的距离。

只有lineJoin属性为kCALineJoinMiter时miterLimit才有效

边角的角度越小,斜接长度就会越大。

为了避免斜接长度过长,我们可以使用 miterLimit 属性。

如果斜接长度超过 miterLimit 的值,边角会以 lineJoin的 "bevel"即kCALineJoinBevel类型来显示

10. 部分绘线

[objc] view plaincopyprint?

  1. @property CGFloat strokeStart
  2. @property CGFloat strokeEnd

都是0.0~1.0的取值范围

具体看修改例子6.1

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //create path
  5. UIBezierPath *path = [[UIBezierPath alloc] init];
  6. [path moveToPoint:CGPointMake(175, 100)];
  7. [path addArcWithCenter:CGPointMake(150, 100) radius:25 startAngle:0 endAngle:2*M_PI clockwise:YES];
  8. [path moveToPoint:CGPointMake(150, 125)];
  9. [path addLineToPoint:CGPointMake(150, 175)];
  10. [path addLineToPoint:CGPointMake(125, 225)];
  11. [path moveToPoint:CGPointMake(150, 175)];
  12. [path addLineToPoint:CGPointMake(175, 225)];
  13. [path moveToPoint:CGPointMake(100, 150)];
  14. [path addLineToPoint:CGPointMake(200, 150)];
  15. //create shape layer
  16. CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  17. shapeLayer.strokeColor = [UIColor redColor].CGColor;
  18. shapeLayer.fillColor = [UIColor clearColor].CGColor;
  19. shapeLayer.lineWidth = 5;
  20. //shapeLayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:20], [NSNumber numberWithInt:10], [NSNumber numberWithInt:10], [NSNumber numberWithInt:2], nil];
  21. //shapeLayer.lineDashPhase = 15;
  22. shapeLayer.lineJoin = kCALineJoinBevel;
  23. shapeLayer.lineCap = kCALineCapRound;
  24. shapeLayer.strokeStart = 0.1;
  25. shapeLayer.strokeEnd = 0.6;
  26. shapeLayer.path = path.CGPath;
  27. //add it to our view
  28. [self.containerView.layer addSublayer:shapeLayer];
  29. }

UIBezierPath贝塞尔曲线的常用绘图方法

1. 矩形

[objc] view plaincopyprint?

  1. + (UIBezierPath *)bezierPathWithRect:(CGRect)rect

2. 矩形内切椭圆

[objc] view plaincopyprint?

  1. + (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect

3. 圆角矩形

[objc] view plaincopyprint?

  1. + (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius

4. 可设置的圆角矩形

[objc] view plaincopyprint?

  1. + (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii

corners有以下几种类型:

UIRectCornerTopLeft,

UIRectCornerTopRight,

UIRectCornerBottomLeft,

UIRectCornerBottomRight,

UIRectCornerAllCorners

cornerRadii表示的是四个圆角拼成的椭圆的长、短半径尺寸。

5. 圆弧

[objc] view plaincopyprint?

  1. + (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise
  2. - (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise

以下需要配合moveToPoint使用

[objc] view plaincopyprint?

  1. - (void)moveToPoint:(CGPoint)point

6. 直线

[objc] view plaincopyprint?

  1. - (void)addLineToPoint:(CGPoint)point

7. 曲线

[objc] view plaincopyprint?

  1. - (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2

8. 二元曲线

[objc] view plaincopyprint?

  1. - (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint

UIBezierPath的属性设置(这些属性在使用CAShapeLayer时,只遵循CAShapeLayer的设置)

1. 线宽

[objc] view plaincopyprint?

  1. @property(nonatomic) CGFloat lineWidth

2. 端点类型

[objc] view plaincopyprint?

  1. @property(nonatomic) CGLineCap lineCapStyle

3. 连接类型

[objc] view plaincopyprint?

  1. @property(nonatomic) CGLineJoin lineJoinStyle

4. 设置线型

[objc] view plaincopyprint?

  1. - (void)setLineDash:(const CGFloat *)pattern count:(NSInteger)count phase:(CGFloat)phase

pattern:C类型的线型数据。如:CGFloat dashStyle[] = { 1.0f, 2.0f };

count:pattern中的数据个数
phase: 开始画线型的起始位置

其他的我在这里就不多说了

CATextLayer

 

例子6.2

[objc] view plaincopyprint?

  1. @interface ViewController ()
  2. @property (nonatomic, weak) IBOutlet UIView *labelView;
  3. @end
  4. @implementation ViewController
  5. - (void)viewDidLoad
  6. {
  7. [super viewDidLoad];
  8. //create a text layer
  9. CATextLayer *textLayer = [CATextLayer layer];
  10. textLayer.frame = self.labelView.bounds;
  11. [self.labelView.layer addSublayer:textLayer];
  12. //uncomment the line below to fix pixelation on Retina screens
  13. //textLayer.contentsScale = [UIScreen mainScreen].scale;
  14. //set text attributes
  15. textLayer.foregroundColor = [UIColor blackColor].CGColor;
  16. textLayer.alignmentMode = kCAAlignmentJustified;
  17. //textLayer.contentsScale = 1;
  18. textLayer.wrapped = YES;
  19. //choose a font
  20. UIFont *font = [UIFont systemFontOfSize:15];
  21. //set layer font
  22. CFStringRef fontName = (__bridge CFStringRef)font.fontName;
  23. CGFontRef fontRef = CGFontCreateWithFontName(fontName);
  24. textLayer.font = fontRef;
  25. textLayer.fontSize = font.pointSize;
  26. CGFontRelease(fontRef);
  27. //choose some text
  28. NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing \
  29. elit. Quisque massa arcu, eleifend vel varius in, facilisis pulvinar \
  30. leo. Nunc quis nunc at mauris pharetra condimentum ut ac neque. Nunc \
  31. elementum, libero ut porttitor dictum, diam odio congue lacus, vel \
  32. fringilla sapien diam at purus. Etiam suscipit pretium nunc sit amet \
  33. lobortis";
  34. //set layer text
  35. textLayer.string = text;
  36. }
  37. @end


仔细看文字周围很模糊,解决这个问题需要设置contentsScale

修改“textLayer.contentsScale = [UIScreen mainScreen].scale;”

Rich Text

例子6.3

代码不贴了

CATextLayer also renders much faster than UILabel. It’s a little-known fact that on iOS6 and earlier,UILabel actually uses WebKit to do its text drawing, which carries a significant performance overhead when you are drawing a lot of text.CATextLayer uses Core Text and is significantlyfaster.

例子6.4使用layer实现的label,有兴趣的完善一下

CATransformLayer

例子6.5

代码不贴了

修改一下,可以实现简单的拖动旋转(只是试验代码)

[objc] view plaincopyprint?

  1. @interface ViewController ()
  2. {
  3. CGPoint startPoint;
  4. CATransformLayer *s_Cube;
  5. float pix, piy;
  6. }
  7. @property (nonatomic, weak) IBOutlet UIView *containerView;
  8. @end
  9. @implementation ViewController
  10. - (CALayer *)faceWithTransform:(CATransform3D)transform
  11. {
  12. //create cube face layer
  13. CALayer *face = [CALayer layer];
  14. face.frame = CGRectMake(-50, -50, 100, 100);
  15. //apply a random color
  16. CGFloat red = (rand() / (double)INT_MAX);
  17. CGFloat green = (rand() / (double)INT_MAX);
  18. CGFloat blue = (rand() / (double)INT_MAX);
  19. face.backgroundColor = [UIColor colorWithRed:red
  20. green:green
  21. blue:blue
  22. alpha:1.0].CGColor;
  23. //apply the transform and return
  24. face.transform = transform;
  25. return face;
  26. }
  27. - (CALayer *)cubeWithTransform:(CATransform3D)transform
  28. {
  29. //create cube layer
  30. CATransformLayer *cube = [CATransformLayer layer];
  31. //add cube face 1
  32. CATransform3D ct = CATransform3DMakeTranslation(0, 0, 50);
  33. [cube addSublayer:[self faceWithTransform:ct]];
  34. //add cube face 2
  35. ct = CATransform3DMakeTranslation(50, 0, 0);
  36. ct = CATransform3DRotate(ct, M_PI_2, 0, 1, 0);
  37. [cube addSublayer:[self faceWithTransform:ct]];
  38. //add cube face 3
  39. ct = CATransform3DMakeTranslation(0, -50, 0);
  40. ct = CATransform3DRotate(ct, M_PI_2, 1, 0, 0);
  41. [cube addSublayer:[self faceWithTransform:ct]];
  42. //add cube face 4
  43. ct = CATransform3DMakeTranslation(0, 50, 0);
  44. ct = CATransform3DRotate(ct, -M_PI_2, 1, 0, 0);
  45. [cube addSublayer:[self faceWithTransform:ct]];
  46. //add cube face 5
  47. ct = CATransform3DMakeTranslation(-50, 0, 0);
  48. ct = CATransform3DRotate(ct, -M_PI_2, 0, 1, 0);
  49. [cube addSublayer:[self faceWithTransform:ct]];
  50. //add cube face 6
  51. ct = CATransform3DMakeTranslation(0, 0, -50);
  52. ct = CATransform3DRotate(ct, M_PI, 0, 1, 0);
  53. [cube addSublayer:[self faceWithTransform:ct]];
  54. //center the cube layer within the container
  55. CGSize containerSize = self.containerView.bounds.size;
  56. cube.position = CGPointMake(containerSize.width / 2.0,
  57. containerSize.height / 2.0);
  58. //apply the transform and return
  59. cube.transform = transform;
  60. return cube;
  61. }
  62. - (void)viewDidLoad
  63. {
  64. [super viewDidLoad];
  65. //set up the perspective transform
  66. CATransform3D pt = CATransform3DIdentity;
  67. pt.m34 = -1.0 / 500.0;
  68. self.containerView.layer.sublayerTransform = pt;
  69. //set up the transform for cube 1 and add it
  70. CATransform3D c1t = CATransform3DIdentity;
  71. c1t = CATransform3DTranslate(c1t, -100, 0, 0);
  72. CALayer *cube1 = [self cubeWithTransform:c1t];
  73. s_Cube = (CATransformLayer *)cube1;
  74. [self.containerView.layer addSublayer:cube1];
  75. //set up the transform for cube 2 and add it
  76. CATransform3D c2t = CATransform3DIdentity;
  77. c2t = CATransform3DTranslate(c2t, 100, 0, 0);
  78. c2t = CATransform3DRotate(c2t, -M_PI_4, 1, 0, 0);
  79. c2t = CATransform3DRotate(c2t, -M_PI_4, 0, 1, 0);
  80. CALayer *cube2 = [self cubeWithTransform:c2t];
  81. [self.containerView.layer addSublayer:cube2];
  82. }
  83. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  84. {
  85. UITouch *touch = [touches anyObject];
  86. startPoint = [touch locationInView:self.view];
  87. }
  88. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
  89. {
  90. UITouch *touch = [touches anyObject];
  91. CGPoint currentPosition = [touch locationInView:self.view];
  92. CGFloat deltaX = startPoint.x - currentPosition.x;
  93. CGFloat deltaY = startPoint.y - currentPosition.y;
  94. CATransform3D c1t = CATransform3DIdentity;
  95. c1t = CATransform3DTranslate(c1t, -100, 0, 0);
  96. c1t = CATransform3DRotate(c1t, pix+M_PI_2*deltaY/100, 1, 0, 0);
  97. c1t = CATransform3DRotate(c1t, piy-M_PI_2*deltaX/100, 0, 1, 0);
  98. s_Cube.transform = c1t;
  99. }
  100. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
  101. {
  102. UITouch *touch = [touches anyObject];
  103. CGPoint currentPosition = [touch locationInView:self.view];
  104. CGFloat deltaX = startPoint.x - currentPosition.x;
  105. CGFloat deltaY = startPoint.y - currentPosition.y;
  106. pix = M_PI_2*deltaY/100;
  107. piy = -M_PI_2*deltaX/100;
  108. }
  109. @end

 

 

CAGradientLayer

 

产生平滑过渡色,

 

例子6.6

[objc] view plaincopyprint?

  1. interface ViewController ()
  2. @property (nonatomic, weak) IBOutlet UIView *containerView;
  3. @end
  4. @implementation ViewController
  5. - (void)viewDidLoad
  6. {
  7. [super viewDidLoad];
  8. //create gradient layer and add it to our container view
  9. CAGradientLayer *gradientLayer = [CAGradientLayer layer];
  10. gradientLayer.frame = self.containerView.bounds;
  11. [self.containerView.layer addSublayer:gradientLayer];
  12. //set gradient colors
  13. gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor,
  14. (__bridge id)[UIColor blueColor].CGColor];
  15. //set gradient start and end points
  16. gradientLayer.startPoint = CGPointMake(0, 0);
  17. gradientLayer.endPoint = CGPointMake(1, 1);
  18. }
  19. @end

CAGradientLayer的属性设置

1. 类型

[objc] view plaincopyprint?

  1. @property(copy) NSString *type

目前只有NSString * const kCAGradientLayerAxial
即线性梯度变化

2. 颜色

[objc] view plaincopyprint?

  1. @property(copy) NSArray *colors

3. 位置参数

[objc] view plaincopyprint?

  1. @property(copy) NSArray *locations

颜色的区间分布,locations的数组长度和colors一致, 取值范围(0, 1),而且必须是单调递增的

修改例子6.6,增加

[objc] view plaincopyprint?

  1. <p class="p1">    gradientLayer.<span class="s1">locations</span> = <span class="s2">@[</span>[<span class="s1">NSNumber</span> <span class="s3">numberWithFloat</span>:<span class="s2">0.0</span>], [<span class="s1">NSNumber</span> <span class="s3">numberWithFloat</span>:<span class="s2">0.2</span>]<span class="s2">]</span>;</p>

[objc] view plaincopyprint?

  1. gradientLayer.locations = @[[NSNumber numberWithFloat:0.5], [NSNumber numberWithFloat:0.7]];

4. startPoint和endPoint

[objc] view plaincopyprint?

  1. @property CGPoint startPoint, endPoint;

取值都是相对于layer的bounds的。startPoint默认值为(0.5, 0),endPoint默认值为(0.5, 1)

修改例子6.6

gradientLayer.startPoint 分别设为 CGPointMake(0, 0);

CGPointMake(0.25, 0);

CGPointMake(0.5, 0);

CGPointMake(0.75, 0);

CGPointMake(1, 0);

综合修改例子6.6

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //create gradient layer and add it to our container view
  5. CAGradientLayer *gradientLayer = [CAGradientLayer layer];
  6. gradientLayer.frame = self.containerView.bounds;
  7. [self.containerView.layer addSublayer:gradientLayer];
  8. //set gradient colors
  9. gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor,
  10. (__bridge id)[UIColor blueColor].CGColor];
  11. gradientLayer.locations = @[[NSNumber numberWithFloat:0.5], [NSNumber numberWithFloat:0.7]];
  12. //set gradient start and end points
  13. gradientLayer.startPoint = CGPointMake(0.75, 0.0);
  14. gradientLayer.endPoint = CGPointMake(1.0, 1.0);
  15. }

从以上可以看出startPoint和endPoint诗表示的渐变方向,locations是渐变区域。

也可以看出locations的取值是相对于startPoint和endPoint线段的。

在网上找的描述让我很是不能理解

CAReplicatorLayer

例子6.8,修改一下看得更清楚些

[objc] view plaincopyprint?

  1. @interface ViewController ()
  2. @property (nonatomic, weak) IBOutlet UIView *containerView;
  3. @end
  4. @implementation ViewController
  5. - (void)viewDidLoad
  6. {
  7. [super viewDidLoad];
  8. //create a replicator layer and add it to our view
  9. CAReplicatorLayer *replicator = [CAReplicatorLayer layer];
  10. replicator.frame = self.containerView.bounds;
  11. [self.containerView.layer addSublayer:replicator];
  12. //configure the replicator
  13. replicator.instanceCount = 20;
  14. //apply a transform for each instance
  15. CATransform3D transform = CATransform3DIdentity;
  16. transform = CATransform3DTranslate(transform, 0, -10, 0);
  17. transform = CATransform3DRotate(transform, M_PI / 10.0, 0, 0, 1);
  18. transform = CATransform3DTranslate(transform, 0, 10, 0);
  19. replicator.instanceTransform = transform;
  20. //apply a color shift for each instance
  21. replicator.instanceBlueOffset = -0.1;
  22. replicator.instanceGreenOffset = -0.1;
  23. //create a sublayer and place it inside the replicator
  24. CALayer *layer = [CALayer layer];
  25. layer.frame = CGRectMake(137.5f, 25.0f, 25.0f, 25.0f);
  26. layer.backgroundColor = [UIColor whiteColor].CGColor;
  27. [replicator addSublayer:layer];
  28. }
  29. @end

CAReplicatorLayer应用最多的可能是倒影了,下面的链接是个很好的图片倒影例子

https://github.com/nicklockwood/ReflectionView

后面的几个特殊layer我就不在这里列举了,自己去研究吧

下一次,就将进入真正的动画部分了

时间: 2024-10-21 20:13:07

IOS Core Animation Advanced Techniques的学习笔记(五)的相关文章

IOS Core Animation Advanced Techniques的学习笔记(一)

转载. Book Description Publication Date: August 12, 2013 Core Animation is the technology underlying Apple’s iOS user interface. By unleashing the full power of Core Animation, you can enhance your app with impressive 2D and 3D visual effects and creat

IOS Core Animation Advanced Techniques的学习笔记(四)

第五章:Transforms Affine Transforms CGAffineTransform是二维的 Creating a CGAffineTransform 主要有三种变化方法 旋转: CGAffineTransformMakeRotation(CGFloat angle) 缩放: CGAffineTransformMakeScale(CGFloat sx, CGFloat sy) 移动: CGAffineTransformMakeTranslation(CGFloat tx, CGF

IOS Core Animation Advanced Techniques的学习笔记(二)

[objc] view plaincopyprint?转载学习 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx { CGFloat width = 10.0f; //draw a thick red circle CGContextSetLineWidth(ctx, width); CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor); CG

IOS Core Animation Advanced Techniques的学习笔记(三)

第四章:Visual Effects   Rounded Corners 例子4.1 cornerRadius 源码在这里下载:http://www.informit.com/title/9780133440751 [objc] view plaincopyprint? #import "ViewController.h" #import <QuartzCore/QuartzCore.h> @interface ViewController () @property (no

iOS Core Animation Advanced Techniques(四):隐式动画和显式动画

隐式动画 按照我的意思去做,而不是我说的. -- 埃德娜,辛普森 我们在第一部分讨论了Core Animation除了动画之外可以做到的任何事情.但是动画师Core Animation库一个非常显著的特性.这一章我们来看看它是怎么做到的.具体来说,我们先来讨论框架自动完成的隐式动画(除非你明确禁用了这个功能). 事务 Core Animation基于一个假设,说屏幕上的任何东西都可以(或者可能)做动画.动画并不需要你在Core Animation中手动打开,相反需要明确地关闭,否则他会一直存在.

iOS Core Animation Advanced Techniques(六): 基于定时器的动画和性能调优

基于定时器的动画 我可以指导你,但是你必须按照我说的做. -- 骇客帝国 在第10章“缓冲”中,我们研究了CAMediaTimingFunction,它是一个通过控制动画缓冲来模拟物理效果例如加速或者减速来增强现实感的东西,那么如果想更加真实地模拟 物理交互或者实时根据用户输入修改动画改怎么办呢?在这一章中,我们将继续探索一种能够允许我们精确地控制一帧一帧展示的基于定时器的动画. 定时帧 动画看起来是用来显示一段连续的运动过程,但实际上当在固定位置上展示像素的时候并不能做到这一点.一般来说这种显

iOS Core Animation Advanced Techniques(三):专用图层

到目前为止,我们已经探讨过CALayer类了,同时我们也了解到了一些非常有用的绘图和动画功能.但是Core Animation图层不仅仅能作用于图片和颜色而已.本章就会学习其他的一些图层类,进一步扩展使用Core Animation绘图的能力. CAShapeLayer 在第四章『视觉效果』我们学习到了不使用图片的情况下用CGPath去构造任意形状的阴影.如果我们能用同样的方式创建相同形状的图层就好了. CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类.你指定诸如颜色

iOS Core Animation Advanced Techniques(七):高效绘图、图像IO以及图层性能

高效绘图不必要的效率考虑往往是性能问题的万恶之源. ——William Allan Wulf 在第12章『速度的曲率』我们学习如何用Instruments来诊断Core Animation性能问题.在构建一个iOS app的时候会遇到很多潜在的性能陷阱,但是在本章我们将着眼于有关绘制的性能问题. 软件绘图 术语绘图通常在Core Animation的上下文中指代软件绘图(意即:不由GPU协助的绘图).在iOS中,软件绘图通常是由Core Graphics框架完成来完成.但是,在一些必要的情况下,

iOS Core Animation Advanced Techniques(二):视觉效果和变换

四)视觉效果 嗯,园和椭圆还不错,但如果是带圆角的矩形呢? 我们现在能做到那样了么? 史蒂芬·乔布斯 我们在第三章『图层几何学』中讨论了图层的frame,第二章『寄宿图』则讨论了图层的寄宿图.但是图层不仅仅可以是图片或是颜色的容器:还有一系列内建的特性使得创造美丽优雅的令人深刻的界面元素成为可能.在这一章,我们将会探索一些能够通过使用CALayer属性实现的视觉效果. 圆角 圆角矩形是iOS的一个标志性审美特性.这在iOS的每一个地方都得到了体现,不论是主屏幕图标,还是警告弹框,甚至是文本框.按