您的位置:首页 > 产品设计 > UI/UE

IOS Core Animation Advanced Techniques

2017-12-21 20:05 471 查看
#import "ViewController.h"

#import <QuartzCore/QuartzCore.h>

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView1;

@property (nonatomic, weak) IBOutlet UIView *layerView2;

@end

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//set the corner radius on our layers

self.layerView1.layer.cornerRadius = 20.0f;

self.layerView2.layer.cornerRadius = 20.0f;

//enable clipping on the second layer

self.layerView2.layer.masksToBounds = YES;

}

@end



稍微修改一下

[objc] view
plain copy

- (void)viewDidLoad

{

[super viewDidLoad];

//set the corner radius on our layers

self.layerView1.layer.cornerRadius = 20.0f;

self.layerView2.layer.cornerRadius = 20.0f;

self.layerView1.clipsToBounds = YES;

//enable clipping on the second layer

self.layerView2.layer.masksToBounds = YES;

}



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

Layer Borders

例子4.2 borderWidth

[objc] view
plain copy

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView1;

@property (nonatomic, weak) IBOutlet UIView *layerView2;

@end

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//set the corner radius on our layers

self.layerView1.layer.cornerRadius = 20.0f;

self.layerView2.layer.cornerRadius = 20.0f;

//add a border to our layers

self.layerView1.layer.borderWidth = 5.0f;

self.layerView2.layer.borderWidth = 5.0f;

//enable clipping on the second layer

self.layerView2.layer.masksToBounds = YES;

}

@end



修改代码 borderColor

[objc] view
plain copy

- (void)viewDidLoad

{

[super viewDidLoad];

//set the corner radius on our layers

self.layerView1.layer.cornerRadius = 20.0f;

self.layerView2.layer.cornerRadius = 20.0f;

//add a border to our layers

self.layerView1.layer.borderWidth = 5.0f;

self.layerView1.layer.borderColor = [UIColor brownColor].CGColor;

self.layerView2.layer.borderWidth = 5.0f;

//enable clipping on the second layer

self.layerView2.layer.masksToBounds = YES;

}



再做个试验,修改代码



[objc] view
plain copy

- (void)viewDidLoad

{

[super viewDidLoad];

//set the corner radius on our layers

//self.layerView1.layer.cornerRadius = 20.0f;

self.layerView2.layer.cornerRadius = 20.0f;

//add a border to our layers

self.layerView1.layer.borderWidth = 5.0f;

self.layerView1.layer.borderColor = [UIColor brownColor].CGColor;

self.layerView2.layer.borderWidth = 5.0f;

//enable clipping on the second layer

self.layerView2.layer.masksToBounds = YES;

}



没有看到红色

再修改



看结果



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

Drop Shadows & Shadow Clipping

先修改例子2.2

[objc] view
plain copy

- (void)viewDidLoad

{

[super viewDidLoad];

//load an image

UIImage *image = [UIImage imageNamed:@"Snowman.png"];

self.layerView.backgroundColor = [UIColor clearColor];

//add it directly to our view's layer

self.layerView.layer.contents = (__bridge id)image.CGImage;

//center the image

self.layerView.layer.contentsGravity = kCAGravityCenter;

//set the contentsScale to match screen

self.layerView.layer.contentsScale = image.scale;

self.layerView.layer.shadowOpacity = 0.3;

self.layerView.layer.shadowOffset = CGSizeMake(10, 20);

//clip the snowman to fit his bounds

//self.layerView.layer.masksToBounds = YES;

}



继续

[objc] view
plain copy

- (void)viewDidLoad

{

[super viewDidLoad];

//load an image

UIImage *image = [UIImage imageNamed:@"Snowman.png"];

//self.layerView.backgroundColor = [UIColor clearColor];

//add it directly to our view's layer

self.layerView.layer.contents = (__bridge id)image.CGImage;

//center the image

self.layerView.layer.contentsGravity = kCAGravityCenter;

//set the contentsScale to match screen

self.layerView.layer.contentsScale = image.scale;

self.layerView.layer.shadowOpacity = 0.3;

self.layerView.layer.shadowOffset = CGSizeMake(10, 20);

//clip the snowman to fit his bounds

//self.layerView.layer.masksToBounds = YES;

}



再改

[objc] view
plain copy

- (void)viewDidLoad

{

[super viewDidLoad];

//load an image

UIImage *image = [UIImage imageNamed:@"Snowman.png"];

self.layerView.backgroundColor = [UIColor clearColor];

//add it directly to our view's layer

self.layerView.layer.contents = (__bridge id)image.CGImage;

//center the image

self.layerView.layer.contentsGravity = kCAGravityCenter;

//set the contentsScale to match screen

self.layerView.layer.contentsScale = image.scale;

self.layerView.layer.shadowOpacity = 0.3;

self.layerView.layer.shadowOffset = CGSizeMake(10, 20);

//clip the snowman to fit his bounds

self.layerView.layer.masksToBounds = YES;

}



再改

[objc] view
plain copy

- (void)viewDidLoad

{

[super viewDidLoad];

//load an image

UIImage *image = [UIImage imageNamed:@"Snowman.png"];

//self.layerView.backgroundColor = [UIColor clearColor];

//add it directly to our view's layer

self.layerView.layer.contents = (__bridge id)image.CGImage;

//center the image

self.layerView.layer.contentsGravity = kCAGravityCenter;

//set the contentsScale to match screen

self.layerView.layer.contentsScale = image.scale;

self.layerView.layer.shadowOpacity = 0.3;

self.layerView.layer.shadowOffset = CGSizeMake(10, 20);

//clip the snowman to fit his bounds

self.layerView.layer.masksToBounds = YES;

}



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

再看看例子4.3去体会一下

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

The shadowPath Property

例子4.4

[objc] view
plain copy

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView1;

@property (nonatomic, weak) IBOutlet UIView *layerView2;

@end

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//enable layer shadows

self.layerView1.layer.shadowOpacity = 0.5f;

self.layerView2.layer.shadowOpacity = 0.5f;

//create a square shadow

CGMutablePathRef squarePath = CGPathCreateMutable();

CGPathAddRect(squarePath, NULL, self.layerView1.bounds);

self.layerView1.layer.shadowPath = squarePath;

CGPathRelease(squarePath);

//create a circular shadow

CGMutablePathRef circlePath = CGPathCreateMutable();

CGPathAddEllipseInRect(circlePath, NULL, self.layerView2.bounds);

self.layerView2.layer.shadowPath = circlePath;

CGPathRelease(circlePath);

}



Layer Masking

例子4.5

[objc] view
plain copy

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//create mask layer

CALayer *maskLayer = [CALayer layer];

maskLayer.frame = self.imageView.bounds;

UIImage *maskImage = [UIImage imageNamed:@"Cone.png"];

maskLayer.contents = (__bridge id)maskImage.CGImage;

//apply mask to image layer

self.imageView.layer.mask = maskLayer;

}

@end





Scaling Filters

minificationFilter和magnificationFilter属性

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

默认值都是kCAFilterLinear即‘linear’

有3中设置:kCAFilterLinear,kCAFilterNearest,kCAFilterTrilinear

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

kCAFilterTrilinear:基本和kCAFilterLinear相同

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

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

原图


[objc] view
plain copy

@interface ViewController ()

@property (nonatomic, strong) IBOutletCollection(UIView) NSArray *digitViews;

@property (nonatomic, weak) NSTimer *timer;

@end

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//get spritesheet image

UIImage *digits = [UIImage imageNamed:@"Digits.png"];

//set up digit views

for (UIView *view in self.digitViews)

{

//set contents

view.layer.contents = (__bridge id)digits.CGImage;

view.layer.contentsRect = CGRectMake(0, 0, 0.1, 1.0);

view.layer.contentsGravity = kCAGravityResizeAspect;

//use nearest-neighbor scaling

view.layer.magnificationFilter = kCAFilterNearest;

}

//start timer

self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0

target:self

selector:@selector(tick)

userInfo:nil

repeats:YES];

//set initial clock time

[self tick];

}

- (void)setDigit:(NSInteger)digit forView:(UIView *)view

{

//adjust contentsRect to select correct digit

view.layer.contentsRect = CGRectMake(digit * 0.1, 0, 0.1, 1.0);

}

- (void)tick

{

//convert time to hours, minutes and seconds

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSUInteger units = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;

NSDateComponents *components = [calendar components:units fromDate:[NSDate date]];

//set hours

[self setDigit:components.hour / 10 forView:self.digitViews[0]];

[self setDigit:components.hour % 10 forView:self.digitViews[1]];

//set minutes

[self setDigit:components.minute / 10 forView:self.digitViews[2]];

[self setDigit:components.minute % 10 forView:self.digitViews[3]];

//set seconds

[self setDigit:components.second / 10 forView:self.digitViews[4]];

[self setDigit:components.second % 10 forView:self.digitViews[5]];

}

@end

kCAFilterNearest的效果



注释掉

[objc] view
plain copy

//view.layer.magnificationFilter = kCAFilterNearest;

使用用默认kCAFilterLinear效果



明显模糊了

Group Opacity

先看例子4.7:

[objc] view
plain copy

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *containerView;

@end

@implementation ViewController

- (UIButton *)customButton

{

//create button

CGRect frame = CGRectMake(0, 0, 150, 50);

UIButton *button = [[UIButton alloc] initWithFrame:frame];

button.backgroundColor = [UIColor whiteColor];

button.layer.cornerRadius = 10;

//add label

frame = CGRectMake(20, 10, 110, 30);

UILabel *label = [[UILabel alloc] initWithFrame:frame];

label.text = @"Hello World";

//label.backgroundColor = [UIColor clearColor];

label.textAlignment = NSTextAlignmentCenter;

[button addSubview:label];

return button;

}

- (void)viewDidLoad

{

[super viewDidLoad];

//create opaque button

UIButton *button1 = [self customButton];

button1.center = CGPointMake(50, 150);

[self.containerView addSubview:button1];

//create translucent button

UIButton *button2 = [self customButton];

button2.center = CGPointMake(250, 150);

button2.alpha = 0.5;

[self.containerView addSubview:button2];

//enable rasterization for the translucent button

//button2.layer.shouldRasterize = YES;

//button2.layer.rasterizationScale = [UIScreen mainScreen].scale;

}

@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叠加为一张图像

修改代码,

[objc] view
plain copy

- (void)viewDidLoad

{

[super viewDidLoad];

//create opaque button

UIButton *button1 = [self customButton];

button1.center = CGPointMake(50, 150);

[self.containerView addSubview:button1];

//create translucent button

UIButton *button2 = [self customButton];

button2.center = CGPointMake(250, 150);

button2.alpha = 0.5;

[self.containerView addSubview:button2];

//enable rasterization for the translucent button

button2.layer.shouldRasterize = YES;

button2.layer.rasterizationScale = [UIScreen mainScreen].scale;

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: