陈斌彬的技术博客

Stay foolish,stay hungry

CALayer 的视觉效果

稍微写过一些Web网站的开发者可能就明白,我要描述什么东西了,iOS里的“CSS”,其实UIView也有对应的东西,知道一点很重要,CALayer需要的属性都是以CG开头,Ref结尾的“东西”,只要做相应的转换即可。那么,这些“东西”是什么呢?它们有些属于C函数指针,有些是C结构体指针。

让我们先创建一个CALayer

CALayer *calayer = [CALayer layer];
calayer.frame = CGRectMake(50, 50, 100, 100);

然后,创建一个背景颜色

calayer.backgroundColor = [UIColor colorWithRed:1.000 green:0.400 blue:0.400 alpha:1.000].CGColor;

CALayer有一对属性非常有用,它们分别是borderWidth和borderColor,它们共同定义了图层边的绘制样式,这条线是沿着bounds绘制的,同时也包含了图层的角。

calayer.borderWidth = 2;
calayer.borderColor = [UIColor colorWithRed:0.000 green:0.502 blue:0.251 alpha:1.000].CGColor;

那么,此刻我画了一个矩阵出来,我在想,要是添加些圆角,是不是会更好看? 是的,你可以这么想,CALayer也提供了一个属性来绘制圆角,它就是conrnerRadius,默认情况下,它不会影响背景图片和子图层,如果我想把凸出图层的东西干掉,怎么办?

没错,你可以把masksToBounds设置为YES,此时图层内所有的东西会被裁剪。

calayer.cornerRadius = 20;
calayer.masksToBounds = YES;

此刻,我想我们拥有了一个看起来还不错的矩阵圆角,也许添加点阴影,会更有立体感。

CALayer提供了五个属性来控制阴影的绘制,它们分别是shadowColor,shadowOpacity,shadowOffset,shadowPath,shadowRadius

第一个shadowColor,顾名思义,这是设置颜色的

calayer.shadowColor = [UIColor colorWithWhite:0.498 alpha:1.000].CGColor;

shadowOpacity可以设置一个0-1的浮点数,也就是从不可见到完全不透明。

calayer.shadowOpacity = 0.6;

shadowOffset这个属性可能有时候会更有用些,它能控制阴影的展示方向,它接收一个CGSize,x轴表示左右,y轴表示上下。唯一,一点不同的是,正数表示方向,向下,负数刚好相反。

calayer.shadowOffset = CGSizeMake(0, 3);

shadowRadius可以控制阴影的模糊度,当它的值为0的时候,阴影与图层会有一个明显的边界,当值越来越大的时候,边界会越来越模糊与自然。

calayer.shadowRadius = 100;

有时候阴影并不一定是方型的,shadowPath就能派上用场了。

CGMutablePathRef circlePath = CGPathCreateMutable();
CGPathAddEllipseInRect(circlePath, NULL, self.layerView2.bounds);

现在我的矩阵圆角阴影也有了,我把整个view设置成了黑色背景,我想看看透明效果,好不好看。UIView我们都知道可以通过alpha属性来设置,那么CALayer也有一个对应的属性opacity,它的子图层也会受影响喔。

看起来好像跟给一个div设置透明的效果类似,是不是?名字都一样。

calayer.opacity = 0.6;

其实透明,也会出现一些问题,比如我两个图层是父子关系,父和子的透明会有明显的差别,为什么会这样?因为图层只会显示自己的颜色,然后才显示图层下面的颜色。 如果我们设置一个透明50%的图层,我们看见的父子图层可能是这样的,父的颜色是透明的,这个透明色来自25%父图层的颜色,50%子图层,25%背景颜色的综合体,看起来好像不是我想要的。

那么我只能使用shouldRasterize和rasterizationScale属性来解决这个问题了。PS(iOS 6 本人不想玩)

layer.shouldRasterize = YES;
layer.rasterizationScale = [UIScreen mainScreen].scale;

到目前,为止画的都是一个矩阵,然后给矩阵添加圆角,阴影。 搞张图片看看

calayer.contents = (__bridge id)[UIImage imageNamed:@"mockingbird.png"].CGImage;

现在我们可以尝试对这个图片拉伸或过滤一下,这里就可以用到minificationFilter和magnificationFilter属性了。

而CALayer也提供了三种

  • kCAFilterLinear
  • kCAFilterNearest
  • kCAFilterTrilinear

从前面的两个属性名字,不难看出作用在哪里,分别是缩小图片和放大图片。

它们的默认过滤器就是kCAFilterLinear了,算法什么的知道有这么回事就好,其实kCAFilterTrilinearkCAFilterLinear看起没啥区别咧,前一个是三线性滤波算法,后一个是双线性滤波算法,说实在的这个算法内部怎么实现,我也不知道,我只是知道,如果图片有多张,它们采样不同。

但是kCAFilterTrilinear有一个好处,这个方法在于算法能够从一系列已经接近于最终大小的图片中得到想要的结果,也就是说不要对很多像素同步取样。这不仅提高了性能,也避免了小概率因舍入错误引起的取样失灵的问题

kCAFilterNearest则是一种比较武断的算法,从名字上来看,是最近过滤。怎么玩呢?就是就近取样本,不管其它的样本,不过它也有好处,就是很快。坏处呢,可想而知,压缩或者放大后的情况很糟糕。