资讯专栏INFORMATION COLUMN

视觉效果 -- iOS Core Animation 系列三

idealcn / 863人阅读

摘要:边框绘制在图层边界里面,在所有子图层之前。对上面的示例代码坐下调整运行效果如下如上面的示例的结果一样,边框并不会把寄宿图或子图层的相撞计算出来。属性可以实现组透明,如果设置成,图层和它的子图层会被合成一个整体图片。

本片文章前三章内容大家比较常用,后面的可能会不那么常用,前面的基础内容不想看了可以直接从第4段开始

圆角 conrnerRadius
这个功能还是很常见的,本来不想记了,为了整个系列的完整性,还是啰嗦一下。

CALayer有一个conrnerRadius的属性控制图层的圆角曲率,默认值为0。这个曲率值默认只影响背景颜色而不影响背景图片或者子图层。可以用过下面的示例看一下。

Storyboard中放置两个白色的view,每个view分别有两个子view(一个黄色,一个青色),而且都超出了父视图的边界:


然后在代码中写入如下代码:


@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *leftView;
@property (weak, nonatomic) IBOutlet UIView *rightView;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  
  self.leftView.layer.cornerRadius = 20.f;
  self.rightView.layer.cornerRadius = 20.f;
  
  self.rightView.layer.masksToBounds = YES;
}


@end

然后运行效果如下:

通过上面的示例可以发现:

只设置cornerRadius时,默认情况下,只影响背景颜色,而不影响背景图片或者子图层。

如果想要截取这个视图的图片和子视图,需要设置masksToBoundsYES

图层边框 border

CALayer另外两个非常有用的属性borderWidthborderColor
borderWidth是以点为单位定义边框粗细的浮点数,默认为0。borderColor定义了边框的颜色,默认为黑色。

borderColorCGColorRef类型。

边框绘制在图层边界里面,在所有子图层之前。对上面的示例代码坐下调整:

- (void)viewDidLoad {
  [super viewDidLoad];
  
  self.leftView.layer.cornerRadius = 20.f;
  self.rightView.layer.cornerRadius = 20.f;
  
  self.leftView.layer.borderWidth = 5.f;
  self.rightView.layer.borderWidth = 5.f;
  
  self.rightView.layer.masksToBounds = YES;
}

运行效果如下:

如上面的示例的结果一样,边框并不会把寄宿图或子图层的相撞计算出来。而且绘制边框会显示在最上层。
阴影 shadow
阴影属性

控制图层阴影的属性会比前面的边框多一些。

shadowOpacity属性控制阴影透明度的,它是一个在0.01.0之间的浮点数,如果设置为1.0将会显示一个轻微模糊的阴影。

shadowColor属性控制着阴影的颜色,和borderColor一样,它的类型也是CGColorRef,阴影默认是黑色的。

shadowOffset属性控制阴影的方向和距离,它是一个CGSize的值,宽度控制阴影横向位移,高度控制纵向位移。默认值是`{0, -3}。

shadowRadius属性控制着阴影的模糊度,当值为0的时候,阴影和视图一样有一个明显的边界,值越大,边界线看起来就会越模糊。

阴影裁剪

和图层边框不同,图层的阴影继承自内容的外形,而不是根据边界来界定。

有个头疼的限制,阴影通常在Layer的边界之外,如果我们开启了maskToBounds之后,所有突出图层外的内容都会被裁剪到,包括我们设置的阴影。

之前有个UI需求,同时设置阴影和圆角,圆角简单的使用layer.cornerRadiusmaskToBounds。导致一直显示不出来阴影,差的原因是无法共存,到现在才发现是maskToBounds导致的。

maskToBounds把阴影也裁掉的结果肯定不是我们想要的。但是在同一个图层缺又存在这个问题,所以这看起来很简单的效果,我们需要用到两个图层,一个图层做maskToBounds裁剪,一个图层画阴影。
下面我们用圆角下面的那个demo稍作修改做个示例:

首先对rightView做一个透明色的shadowView的包裹,用来设置阴影:

将代码修改成如下:

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *leftView;
@property (weak, nonatomic) IBOutlet UIView *rightView;
@property (weak, nonatomic) IBOutlet UIView *shadowView;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  
  self.leftView.layer.cornerRadius = 20.f;
  self.rightView.layer.cornerRadius = 20.f;

  self.leftView.layer.borderWidth = 5.f;
  self.rightView.layer.borderWidth = 5.f;

  // 不添加其他图层直接给 leftView 设置阴影试一试
  self.leftView.layer.shadowOffset = CGSizeMake(5, 5);
  self.leftView.layer.shadowOpacity = 0.8f;
  self.leftView.layer.shadowRadius = 5.f;


  // 给 shadowView 添加和 leftview 一样的阴影效果
  self.shadowView.layer.shadowOffset = CGSizeMake(5, 5);
  self.shadowView.layer.shadowOpacity = 0.8f;
  self.shadowView.layer.shadowRadius = 5.f;

  // 将view裁剪
  self.rightView.layer.masksToBounds = YES;
}

@end

运行的效果如图:

注意看左边视图的阴影范围,很好的说明了图层的阴影继承自内容的外形,而不是根据边界来界定。
shadowPath属性

图层阴影并不总是方的,而是从内容的形状继承来的。因为计算阴影是一个很耗资源的步骤,尤其有多个子图层的时候。如果我们指定阴影的形状的话,可以指定阴影的样子来节省计算阴影的资源开销。
shadowPath就是做这个事的,它是一个CGPathRef类型(指向CGPath的指针)。
下图展示了同意寄宿图不同阴影的设定:


上图的代码实现:

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *layerView1;
@property (weak, nonatomic) IBOutlet UIImageView *layerView2;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  
  self.layerView1.layer.shadowOpacity = 0.5f;
  self.layerView2.layer.shadowOpacity = 0.5f;
  
  // 添加矩形阴影
  CGMutablePathRef squarePath = CGPathCreateMutable();
  CGPathAddRect(squarePath, NULL, self.layerView1.bounds);
  self.layerView1.layer.shadowPath = squarePath;
  CGPathRelease(squarePath);
  
  // 添加圆形阴影
  CGMutablePathRef circlePath = CGPathCreateMutable();
  CGPathAddEllipseInRect(circlePath, NULL, self.layerView2.bounds);
  self.layerView2.layer.shadowPath = circlePath;
  CGPathRelease(circlePath);
  
}

@end
如果一个矩形或者圆形,用CGPath很简单可以实现,如果复杂的图就需要借助UIBezierPath来实现了。
图层蒙版 mask
这节的原文章前有一堆铺垫的,我就不说了,想看的点击查看原文

本节主要是介绍CALayermaskt属性,它可以实现一些比较好玩的裁剪效果。而不是常规的圆形、矩形裁剪。
mask图层的Color属性无关紧要,它真正有用的是图层的轮廓。如下图所示一样,mask属性像是一个切割机,mask图层实心的地方会被保留,其他地方被抛弃。

下面我们实现以下上图的效果,首先在Storyboard里创建一个UIImageView,然后代码如下:

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

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  
  // 创建mask
  CALayer *maskLayer = [CALayer layer];
  maskLayer.frame = self.imageView.bounds;
  UIImage *maskImage = [UIImage imageNamed:@"test_mask"];
  maskLayer.contents = (__bridge id)maskImage.CGImage;
  
  // 添加到 imageview 上
  self.imageView.layer.mask = maskLayer;
  
  //  两张图片素材是在原文中截图处理的,所以展示的效果和原文有所差别。
}

@end

运行效果如下:

CALayer蒙板图层不局限于静态图,也可以通过代码甚至是动画实时生成蒙板。
拉伸过滤
关于这些我看了原文,确实不懂,而且我也没碰到过,无从下手做笔记。如果想了解的话请点击此处
组透明 alpha

UIView有一个alpha属性来决定视图的透明度,对应的CALayer有一个opacity属性。这两个属性都会影响子层级的显示透明度。

下面做个示例。现在Storyboard里放置两个UIButton。然后代码如下:

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *leftBtn;
@property (weak, nonatomic) IBOutlet UIButton *rightBtn;

@end

@implementation ViewController
- (UILabel *)subLbl {
  
  UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 90, 40)];
  label.text = @"Hello World";
  label.backgroundColor = [UIColor whiteColor];
  label.textAlignment = NSTextAlignmentCenter;
  return label;
}
- (void)viewDidLoad {
  [super viewDidLoad];
  
  [self.leftBtn addSubview:[self subLbl]];
  [self.rightBtn addSubview:[self subLbl]];
  self.rightBtn.alpha = 0.5;
}

@end

运行的效果如下:

这显示的效果有点怪。右边的设置了alpha0.5。但是在UILabel的位置好像不是0.5的效果。这是因为透明度的混合叠加造成的。实际上右侧中间的透明度是0.75

当显示一个50%透明度的图层时,图层的每个像素都会一半显示自己的颜色,另一半显示图层下面的颜色。这是正常的透明度的表现。但是如果图层包含一个同样显示50%透明的子图层时,你所看到的视图,50%来自子视图,25%来了图层本身的颜色,另外的25%则来自背景色。

如果想保持透明度一直。我们可以在info.plist文件中添加UIViewGroupOpacity并设置成YES来打到这个效果。还有一种方法就是对CALayer进行设置。
shouldRasterize属性可以实现组透明,如果设置成YES,图层和它的子图层会被合成一个整体图片。
启用shouldRasterize属性,一般需要同时设置图层的rasterizationScale属性防止出现Retina屏幕像素化的问题。

shouldRasterize和UIViewGroupOpacity一起的时候,会出现性能问题,后面再讲。
对上面的展示效果处理的代码如下:
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *leftBtn;
@property (weak, nonatomic) IBOutlet UIButton *rightBtn;

@end

@implementation ViewController
- (UILabel *)subLbl {
  
  UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 90, 40)];
  label.text = @"Hello World";
  label.backgroundColor = [UIColor whiteColor];
  label.textAlignment = NSTextAlignmentCenter;
  return label;
}
- (void)viewDidLoad {
  [super viewDidLoad];
  
  [self.leftBtn addSubview:[self subLbl]];
  [self.rightBtn addSubview:[self subLbl]];
  self.rightBtn.alpha = 0.5;
  
  self.rightBtn.layer.rasterizationScale = [UIScreen mainScreen].scale;
  self.rightBtn.layer.shouldRasterize = YES;
}

@end

效果如我们所愿。

---系列三完---

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/17134.html

相关文章

  • 图层树和寄宿图 -- iOS Core Animation 系列

    摘要:提供和两个平行的层级关系,应该也是为了解耦,做职责分离。以便能适应和的系统。因为默认情况下,仍会绘制超过边界的内容,在也不例外。的属性允许我们在图层边框里显示寄宿图的一个子域。因为当图层显示在屏幕上时,不会自动重绘,这和不同。 本系列文章算是一系列读书笔记,想了解更多,请看原文 1.图层树 1.1 视图 一个视图就是在屏幕上显示的一个矩形块(比如图片,文字或者视频),它能够拦截类似于鼠...

    My_Oh_My 评论0 收藏0
  • iOS开发UI篇--iOS动画(Core Animation)总结

    摘要:能够检测动画的执行和结束。关键帧动画中的执行路径过渡动画的动画类型,系统提供了四种过渡动画。关键帧动画和都属于的子类。里面的元素称为关键帧。动画对象会在指定的时间内,依次显示数组中的每一个关键帧可以设置一个让层跟着路径移动。 一、简介 IOS 动画主要是指Core Animation框架。官方使用文档地址为:Core Animation Guide。Core Animation是IOS...

    miracledan 评论0 收藏0
  • 动画 - 收藏集 - 掘金

    摘要:本文分析主要把文件转为动画属性动画入门实践掘金前言说道动画肯定要先介绍一下,逐帧动画和补间动画。安卓动画详解一官方文档掘金概览安卓为元素和自己绘制图形提供了一系列的,这篇文章介绍了这些的主要用法。 那些年收藏的 Android 开源库集合 (UI 效果) - Android - 掘金文章内容定期更新该专题其他文章:那些年收藏的Android开源库集合(控件)那些年收藏的Android开...

    roadtogeek 评论0 收藏0
  • 正在失业中的《课多周刊》(第3期)

    摘要:正在失业中的课多周刊第期我们的微信公众号,更多精彩内容皆在微信公众号,欢迎关注。若有帮助,请把课多周刊推荐给你的朋友,你的支持是我们最大的动力。是一种祸害译本文浅谈了在中关于的不好之处。浅谈超时一运维的排查方式。 正在失业中的《课多周刊》(第3期) 我们的微信公众号:fed-talk,更多精彩内容皆在微信公众号,欢迎关注。 若有帮助,请把 课多周刊 推荐给你的朋友,你的支持是我们最大的...

    robin 评论0 收藏0
  • 正在失业中的《课多周刊》(第3期)

    摘要:正在失业中的课多周刊第期我们的微信公众号,更多精彩内容皆在微信公众号,欢迎关注。若有帮助,请把课多周刊推荐给你的朋友,你的支持是我们最大的动力。是一种祸害译本文浅谈了在中关于的不好之处。浅谈超时一运维的排查方式。 正在失业中的《课多周刊》(第3期) 我们的微信公众号:fed-talk,更多精彩内容皆在微信公众号,欢迎关注。 若有帮助,请把 课多周刊 推荐给你的朋友,你的支持是我们最大的...

    Joyven 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<