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

第四章:Visual Effects

 

Rounded Corners

 

例子4.1 cornerRadius

 

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

 

  1. #import "ViewController.h"  
  2. #import <QuartzCore/QuartzCore.h>  
  3.   
  4. @interface ViewController ()  
  5.   
  6. @property (nonatomic, weak) IBOutlet UIView *layerView1;  
  7. @property (nonatomic, weak) IBOutlet UIView *layerView2;  
  8.   
  9. @end  
  10.   
  11. @implementation ViewController  
  12.   
  13. - (void)viewDidLoad  
  14. {  
  15.     [super viewDidLoad];  
  16.       
  17.     //set the corner radius on our layers  
  18.     self.layerView1.layer.cornerRadius = 20.0f;  
  19.     self.layerView2.layer.cornerRadius = 20.0f;  
  20.       
  21.     //enable clipping on the second layer  
  22.     self.layerView2.layer.masksToBounds = YES;  
  23. }  
  24.   
  25. @end  

 

稍微修改一下

 

  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.       
  5.     //set the corner radius on our layers  
  6.     self.layerView1.layer.cornerRadius = 20.0f;  
  7.     self.layerView2.layer.cornerRadius = 20.0f;  
  8.   
  9.     self.layerView1.clipsToBounds = YES;  
  10.   
  11.     //enable clipping on the second layer  
  12.     self.layerView2.layer.masksToBounds = YES;  
  13. }  


前面讲过了,UIView的clipsToBounds的函数等同于masksToBounds


Layer Borders

例子4.2 borderWidth

 

 

  1. @interface ViewController ()  
  2.   
  3. @property (nonatomic, weak) IBOutlet UIView *layerView1;  
  4. @property (nonatomic, weak) IBOutlet UIView *layerView2;  
  5.   
  6. @end  
  7.   
  8. @implementation ViewController  
  9.   
  10. - (void)viewDidLoad  
  11. {  
  12.     [super viewDidLoad];  
  13.       
  14.     //set the corner radius on our layers  
  15.     self.layerView1.layer.cornerRadius = 20.0f;  
  16.     self.layerView2.layer.cornerRadius = 20.0f;  
  17.       
  18.     //add a border to our layers  
  19.     self.layerView1.layer.borderWidth = 5.0f;  
  20.     self.layerView2.layer.borderWidth = 5.0f;  
  21.       
  22.     //enable clipping on the second layer  
  23.     self.layerView2.layer.masksToBounds = YES;  
  24. }  
  25.   
  26. @end  



修改代码 borderColor

 

 

  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.       
  5.     //set the corner radius on our layers  
  6.     self.layerView1.layer.cornerRadius = 20.0f;  
  7.     self.layerView2.layer.cornerRadius = 20.0f;  
  8.       
  9.     //add a border to our layers  
  10.     self.layerView1.layer.borderWidth = 5.0f;  
  11.     self.layerView1.layer.borderColor = [UIColor brownColor].CGColor;  
  12.     self.layerView2.layer.borderWidth = 5.0f;  
  13.       
  14.     //enable clipping on the second layer  
  15.     self.layerView2.layer.masksToBounds = YES;  
  16. }  



再做个试验,修改代码

 



  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.       
  5.     //set the corner radius on our layers  
  6.     //self.layerView1.layer.cornerRadius = 20.0f;  
  7.     self.layerView2.layer.cornerRadius = 20.0f;  
  8.       
  9.     //add a border to our layers  
  10.     self.layerView1.layer.borderWidth = 5.0f;  
  11.     self.layerView1.layer.borderColor = [UIColor brownColor].CGColor;  
  12.     self.layerView2.layer.borderWidth = 5.0f;  
  13.       
  14.     //enable clipping on the second layer  
  15.     self.layerView2.layer.masksToBounds = YES;  
  16. }  


没有看到红色

 

再修改

看结果

验证borderWidth是往内部画的,和使用CGContextStrokeEllipseInRect画圆时的方式不同

 

Drop Shadows & Shadow Clipping

先修改例子2.2

 

  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.       
  5.     //load an image  
  6.     UIImage *image = [UIImage imageNamed:@"Snowman.png"];  
  7.   
  8.     self.layerView.backgroundColor = [UIColor clearColor];  
  9.   
  10.     //add it directly to our view's layer  
  11.     self.layerView.layer.contents = (__bridge id)image.CGImage;  
  12.       
  13.     //center the image  
  14.     self.layerView.layer.contentsGravity = kCAGravityCenter;  
  15.       
  16.     //set the contentsScale to match screen  
  17.     self.layerView.layer.contentsScale = image.scale;  
  18.   
  19.     self.layerView.layer.shadowOpacity = 0.3;  
  20.     self.layerView.layer.shadowOffset = CGSizeMake(10, 20);  
  21.   
  22.     //clip the snowman to fit his bounds  
  23.     //self.layerView.layer.masksToBounds = YES;  
  24. }  

 

继续

 

  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.       
  5.     //load an image  
  6.     UIImage *image = [UIImage imageNamed:@"Snowman.png"];  
  7.   
  8.     //self.layerView.backgroundColor = [UIColor clearColor];  
  9.   
  10.     //add it directly to our view's layer  
  11.     self.layerView.layer.contents = (__bridge id)image.CGImage;  
  12.       
  13.     //center the image  
  14.     self.layerView.layer.contentsGravity = kCAGravityCenter;  
  15.       
  16.     //set the contentsScale to match screen  
  17.     self.layerView.layer.contentsScale = image.scale;  
  18.   
  19.     self.layerView.layer.shadowOpacity = 0.3;  
  20.     self.layerView.layer.shadowOffset = CGSizeMake(10, 20);  
  21.   
  22.     //clip the snowman to fit his bounds  
  23.     //self.layerView.layer.masksToBounds = YES;  
  24. }  

 

再改

 

  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.       
  5.     //load an image  
  6.     UIImage *image = [UIImage imageNamed:@"Snowman.png"];  
  7.   
  8.     self.layerView.backgroundColor = [UIColor clearColor];  
  9.   
  10.     //add it directly to our view's layer  
  11.     self.layerView.layer.contents = (__bridge id)image.CGImage;  
  12.       
  13.     //center the image  
  14.     self.layerView.layer.contentsGravity = kCAGravityCenter;  
  15.       
  16.     //set the contentsScale to match screen  
  17.     self.layerView.layer.contentsScale = image.scale;  
  18.   
  19.     self.layerView.layer.shadowOpacity = 0.3;  
  20.     self.layerView.layer.shadowOffset = CGSizeMake(10, 20);  
  21.   
  22.     //clip the snowman to fit his bounds  
  23.     self.layerView.layer.masksToBounds = YES;  
  24. }  



再改

  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.       
  5.     //load an image  
  6.     UIImage *image = [UIImage imageNamed:@"Snowman.png"];  
  7.   
  8.     //self.layerView.backgroundColor = [UIColor clearColor];  
  9.   
  10.     //add it directly to our view's layer  
  11.     self.layerView.layer.contents = (__bridge id)image.CGImage;  
  12.       
  13.     //center the image  
  14.     self.layerView.layer.contentsGravity = kCAGravityCenter;  
  15.       
  16.     //set the contentsScale to match screen  
  17.     self.layerView.layer.contentsScale = image.scale;  
  18.   
  19.     self.layerView.layer.shadowOpacity = 0.3;  
  20.     self.layerView.layer.shadowOffset = CGSizeMake(10, 20);  
  21.   
  22.     //clip the snowman to fit his bounds  
  23.     self.layerView.layer.masksToBounds = YES;  
  24. }  

shadow是根据layer实际显示的内容绘制的

再看看例子4.3去体会一下

 

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

 

 

 

The shadowPath Property

 

例子4.4

 

  1. @interface ViewController ()  
  2.   
  3. @property (nonatomic, weak) IBOutlet UIView *layerView1;  
  4. @property (nonatomic, weak) IBOutlet UIView *layerView2;  
  5.   
  6. @end  
  7.   
  8. @implementation ViewController  
  9.   
  10. - (void)viewDidLoad  
  11. {  
  12.     [super viewDidLoad];  
  13.       
  14.     //enable layer shadows  
  15.     self.layerView1.layer.shadowOpacity = 0.5f;  
  16.     self.layerView2.layer.shadowOpacity = 0.5f;  
  17.       
  18.     //create a square shadow  
  19.     CGMutablePathRef squarePath = CGPathCreateMutable();  
  20.     CGPathAddRect(squarePath, NULL, self.layerView1.bounds);  
  21.     self.layerView1.layer.shadowPath = squarePath;  
  22.     CGPathRelease(squarePath);  
  23.       
  24.     //create a circular shadow  
  25.     CGMutablePathRef circlePath = CGPathCreateMutable();  
  26.     CGPathAddEllipseInRect(circlePath, NULL, self.layerView2.bounds);  
  27.     self.layerView2.layer.shadowPath = circlePath;  
  28.     CGPathRelease(circlePath);  
  29. }  



 

Layer Masking

 

例子4.5

 

 

  1. @interface ViewController ()  
  2.   
  3. @property (nonatomic, weak) IBOutlet UIImageView *imageView;  
  4.   
  5. @end  
  6.   
  7. @implementation ViewController  
  8.   
  9. - (void)viewDidLoad  
  10. {  
  11.     [super viewDidLoad];  
  12.       
  13.     //create mask layer  
  14.     CALayer *maskLayer = [CALayer layer];  
  15.     maskLayer.frame = self.imageView.bounds;  
  16.     UIImage *maskImage = [UIImage imageNamed:@"Cone.png"];  
  17.     maskLayer.contents = (__bridge id)maskImage.CGImage;  
  18.       
  19.     //apply mask to image layer  
  20.     self.imageView.layer.mask = maskLayer;  
  21. }  
  22.   
  23. @end  

 



Scaling Filters

minificationFilter和magnificationFilter属性

这两个属性主要是设置layer的‘contents’数据缩放拉伸时的描绘方式,minificationFilter用于缩小,magnificationFilter用于放大

默认值都是kCAFilterLinear即‘linear’

有3中设置:kCAFilterLinear,kCAFilterNearest,kCAFilterTrilinear

kCAFilterLinear:默认值,缩放平滑,但容易产生模糊效果

kCAFilterTrilinear:基本和kCAFilterLinear相同

kCAFilterNearest:速度快不会产生模糊,但会降低质量并像素化图像

 

例子4.6,放大图像,设置magnificationFilter

原图   

 

  1. @interface ViewController ()  
  2.   
  3. @property (nonatomic, strong) IBOutletCollection(UIView) NSArray *digitViews;  
  4. @property (nonatomic, weak) NSTimer *timer;  
  5.   
  6. @end  
  7.   
  8. @implementation ViewController  
  9.   
  10. - (void)viewDidLoad  
  11. {  
  12.     [super viewDidLoad];  
  13.       
  14.     //get spritesheet image  
  15.     UIImage *digits = [UIImage imageNamed:@"Digits.png"];  
  16.       
  17.     //set up digit views  
  18.     for (UIView *view in self.digitViews)  
  19.     {  
  20.         //set contents  
  21.         view.layer.contents = (__bridge  id)digits.CGImage;  
  22.         view.layer.contentsRect = CGRectMake(0, 0, 0.1, 1.0);  
  23.         view.layer.contentsGravity = kCAGravityResizeAspect;  
  24.           
  25.         //use nearest-neighbor scaling  
  26.         view.layer.magnificationFilter = kCAFilterNearest;  
  27.     }  
  28.       
  29.     //start timer  
  30.     self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0  
  31.                                                   target:self  
  32.                                                 selector:@selector(tick)  
  33.                                                 userInfo:nil  
  34.                                                  repeats:YES];  
  35.     //set initial clock time  
  36.     [self tick];  
  37. }  
  38.   
  39. - (void)setDigit:(NSInteger)digit forView:(UIView *)view  
  40. {  
  41.     //adjust contentsRect to select correct digit  
  42.     view.layer.contentsRect = CGRectMake(digit * 0.1, 0, 0.1, 1.0);  
  43. }  
  44.   
  45. - (void)tick  
  46. {  
  47.     //convert time to hours, minutes and seconds  
  48.     NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];  
  49.     NSUInteger units = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;  
  50.     NSDateComponents *components = [calendar components:units fromDate:[NSDate date]];  
  51.       
  52.     //set hours  
  53.     [self setDigit:components.hour / 10 forView:self.digitViews[0]];  
  54.     [self setDigit:components.hour % 10 forView:self.digitViews[1]];  
  55.       
  56.     //set minutes  
  57.     [self setDigit:components.minute / 10 forView:self.digitViews[2]];  
  58.     [self setDigit:components.minute % 10 forView:self.digitViews[3]];  
  59.       
  60.     //set seconds  
  61.     [self setDigit:components.second / 10 forView:self.digitViews[4]];  
  62.     [self setDigit:components.second % 10 forView:self.digitViews[5]];  
  63. }  
  64.   
  65. @end  

kCAFilterNearest的效果

 


注释掉

 

  1. //view.layer.magnificationFilter = kCAFilterNearest;  

 

使用用默认kCAFilterLinear效果

 

明显模糊了

 

Group Opacity

先看例子4.7:

 

  1. @interface ViewController ()  
  2.   
  3. @property (nonatomic, weak) IBOutlet UIView *containerView;  
  4.   
  5. @end  
  6.   
  7. @implementation ViewController  
  8.   
  9. - (UIButton *)customButton  
  10. {  
  11.     //create button  
  12.     CGRect frame = CGRectMake(0, 0, 150, 50);  
  13.     UIButton *button = [[UIButton alloc] initWithFrame:frame];  
  14.     button.backgroundColor = [UIColor whiteColor];  
  15.     button.layer.cornerRadius = 10;  
  16.       
  17.     //add label  
  18.     frame = CGRectMake(20, 10, 110, 30);  
  19.     UILabel *label = [[UILabel alloc] initWithFrame:frame];  
  20.     label.text = @"Hello World";  
  21.     //label.backgroundColor = [UIColor clearColor];  
  22.     label.textAlignment = NSTextAlignmentCenter;  
  23.     [button addSubview:label];  
  24.       
  25.     return button;  
  26. }  
  27.   
  28. - (void)viewDidLoad  
  29. {  
  30.     [super viewDidLoad];  
  31.       
  32.     //create opaque button  
  33.     UIButton *button1 = [self customButton];  
  34.     button1.center = CGPointMake(50, 150);  
  35.     [self.containerView addSubview:button1];  
  36.       
  37.     //create translucent button  
  38.     UIButton *button2 = [self customButton];  
  39.     button2.center = CGPointMake(250, 150);  
  40.     button2.alpha = 0.5;  
  41.     [self.containerView addSubview:button2];  
  42.       
  43.     //enable rasterization for the translucent button  
  44.     //button2.layer.shouldRasterize = YES;  
  45.     //button2.layer.rasterizationScale = [UIScreen mainScreen].scale;  
  46. }  
  47.   
  48. @end  


button的背景和其subView label的背景同为白色,

 

左边的button是不透明的,右边用同样方式创建的button透明度为50%,发现右边的label透明度不同于button

其实很容易发现原因,将button透明度设为50%后,button显示50%自己的颜色和其后面50%的颜色,label在

button上面,label也是50%显示择机的颜色,但后面有已经50%透明的button,还要再显示它的50%,即原

button的25%,重合后为75%,即出现上图效果。

有两种解决方法:

1.在工程的Info.plist文件中,添加UIViewGroupOpacity并设为YES

2.设置layer属性shouldRasterize,设为YES可在设置opacity属性时将layer及其sublayer叠加为一张图像

修改代码,

 

  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.       
  5.     //create opaque button  
  6.     UIButton *button1 = [self customButton];  
  7.     button1.center = CGPointMake(50, 150);  
  8.     [self.containerView addSubview:button1];  
  9.       
  10.     //create translucent button  
  11.     UIButton *button2 = [self customButton];  
  12.     button2.center = CGPointMake(250, 150);  
  13.     button2.alpha = 0.5;  
  14.     [self.containerView addSubview:button2];  
  15.       
  16.     //enable rasterization for the translucent button  
  17.     button2.layer.shouldRasterize = YES;  
  18.     button2.layer.rasterizationScale = [UIScreen mainScreen].scale;  
  19. }  



 

posted @ 2014-10-08 18:23  荔枝林  阅读(807)  评论(0编辑  收藏  举报