动画—CALayer的初步学习三:CALayer绘图—通过代理方法绘图扩展1.2(带阴影效果的绘图和图层的形变)(学会从博客上自学)

扩展1--带阴影效果的圆形图片裁切

如果设置了masksToBounds=YES之后确实可以显示图片圆角效果,但遗憾的是设置了这个属性之后就无法设置阴影效果。因为masksToBounds=YES就意味着外边框不能显示,而阴影恰恰作为外边框绘制的,这样两个设置就产生了矛盾。要解决这个问题不妨换个思路:使用两个大小一样的图层,下面的图层负责绘制阴影,上面的图层用来显示图片。

  上代码:跟着敲:

//
//  KCMainViewController.m
//  CALayer
//
//  Created by Kenshin Cui on 14-3-22.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import "KCMainViewController.h"
#define PHOTO_HEIGHT 150

@interface KCMainViewController ()

@end

@implementation KCMainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    CGPoint position= CGPointMake(160, 200);
    CGRect bounds=CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT);
    CGFloat cornerRadius=PHOTO_HEIGHT/2;
    CGFloat borderWidth=2;
    
    //阴影图层
    CALayer *layerShadow=[[CALayer alloc]init];
    layerShadow.bounds=bounds;
    layerShadow.position=position;
    layerShadow.cornerRadius=cornerRadius;
    layerShadow.shadowColor=[UIColor grayColor].CGColor;
    layerShadow.shadowOffset=CGSizeMake(2, 1);
    layerShadow.shadowOpacity=1;
    layerShadow.borderColor=[UIColor whiteColor].CGColor;
    layerShadow.borderWidth=borderWidth;
    [self.view.layer addSublayer:layerShadow];
    
    //容器图层
    CALayer *layer=[[CALayer alloc]init];
    layer.bounds=bounds;
    layer.position=position;
    layer.backgroundColor=[UIColor redColor].CGColor;
    layer.cornerRadius=cornerRadius;
    layer.masksToBounds=YES;
    layer.borderColor=[UIColor whiteColor].CGColor;
    layer.borderWidth=borderWidth;
    
    //设置图层代理
    layer.delegate=self;
    
    //添加图层到根图层
    [self.view.layer addSublayer:layer];
    
    //调用图层setNeedDisplay,否则代理方法不会被调用
    [layer setNeedsDisplay];
}

#pragma mark 绘制图形、图像到图层,注意参数中的ctx是图层的图形上下文,其中绘图位置也是相对图层而言的
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
    //    NSLog(@"%@",layer);//这个图层正是上面定义的图层
    CGContextSaveGState(ctx);
    
    //图形上下文形变,解决图片倒立的问题
    CGContextScaleCTM(ctx, 1, -1);
    CGContextTranslateCTM(ctx, 0, -PHOTO_HEIGHT);
    
    UIImage *image=[UIImage imageNamed:@"photo.jpg"];
    //注意这个位置是相对于图层而言的不是屏幕
    CGContextDrawImage(ctx, CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT), image.CGImage);
    
    //    CGContextFillRect(ctx, CGRectMake(0, 0, 100, 100));
    //    CGContextDrawPath(ctx, kCGPathFillStroke);
    
    CGContextRestoreGState(ctx);
}
@end
      

运行效果


扩展2--图层的形变

从上面代码中大家不难发现使用Core Graphics绘制图片时会倒立显示,对图层的图形上下文进行了反转。  

今天学习了图层之后,其实可以控制图层直接旋转而不用借助于图形上下文的形变操作,而且这么操作起来会更加简单和直观。

对于上面的程序,只需要设置图层的transform属性即可。需要注意的是transform是CATransform3D类型,形变可以在三个维度上进行,使用方法和前面介绍的二维形变是类似的,而且都有对应的形变设置方法(如:CATransform3DMakeTranslation()、CATransform3DMakeScale()、CATransform3DMakeRotation())。下面的代码通过CATransform3DMakeRotation()方法在x轴旋转180度解决倒立问题:

事实上如果仅仅就显示一张图片在图层中当然没有必要那么麻烦,直接设置图层contents就可以了,不牵涉到绘图也就没有倒立的问题了。  

当然,通过key path设置形变参数就需要了解有哪些key path可以设置,这里就不再一一列举,大家可以参照Xcode帮助文档中“CATransform3D Key Paths”一节,里面描述的很详细。

     因为接下来的博客写了1.改变图层 改变图层又分为CATransform3DMakeRotation()方法 和 通过key path设置形变参数 2.设置图层contents 所以我把这些统一集在了一起。

#pragma mark 关于CALayer绘图——代理方法绘图——扩展2
- (void)calayerBian
{
    CGPoint position = CGPointMake(160, 200);
    CGRect bounds = CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT);
    CGFloat cornerRadius = PHOTO_HEIGHT / 2;
    CGFloat borderWidth = 2;
    
    // 阴影图层
    CALayer *layerShadow = [[CALayer alloc] init];
    layerShadow.bounds = bounds;
    layerShadow.position = position;
    layerShadow.cornerRadius = cornerRadius;
    layerShadow.borderWidth = borderWidth;
    layerShadow.borderColor = [UIColor whiteColor].CGColor;
    layerShadow.shadowColor = [UIColor grayColor].CGColor;
    layerShadow.shadowOffset = CGSizeMake(2, 2);
    layerShadow.shadowOpacity = 1;
    [self.view.layer addSublayer:layerShadow];
    
    // 容器图层
    CALayer *layer = [[CALayer alloc] init];
    layer.bounds = bounds;
    layer.position = position;
    layer.backgroundColor = [UIColor redColor].CGColor;
    layer.cornerRadius = cornerRadius;
    layer.borderWidth = borderWidth;
    // 注意仅仅设置圆角,对于图形而言可以正常显示,但是对于图层中绘制的图片无法正常显示
    // 如果想要正确显示则必须设置maskToBounds=YES,剪切子图层
    layer.masksToBounds = YES;
    // 阴影效果无法和masksToBounds同时使用,因为masksToBounds的目的就是剪切外边框
    // 而阴影效果刚好在外边框
    layer.borderColor = [UIColor whiteColor].CGColor;
    
    // 事实上如果仅仅就显示一张图片在图层中当然没有必要那么麻烦,直接设置图层contents就可以了,不牵涉到绘图也就没有倒立的问题了。
    /* 1111111111111111111111111
    UIImage *image = [UIImage imageNamed:@"150-150"];
    [layer setContents:(id)image.CGImage];
    */ //1111111111111111111111111
    
    
    // 111111和22222222选一种都可以达到效果
    
    
    // 22222222222222222222222
    // 利用图层形变解决图像倒立问题
    
    // layer.transform = CATransform3DMakeRotation(M_PI, 1, 0, 0);
    // 既然如此为什么还大费周章的说形变呢,因为形变对于动画有特殊的意义。在动画开发中形变往往不是直接设置transform,而是通过keyPath进行设置。这种方法设置形变的本质和前面没有区别,只是利用了KVC可以动态修改其属性值而已,但是这种方式在动画中确实很常用的,因为它可以很方便的将几种形变组合到一起使用。同样是解决动画旋转问题,只要将 上面那句 的旋转代码改为下面的代码即可:
    [layer setValue:@M_PI forKeyPath:@"transform.rotation.x"];
    
    // 当然,通过key path设置形变参数就需要了解有哪些key path可以设置,这里就不再一一列举,大家可以参照Xcode帮助文档中“CATransform3D Key Paths”一节,里面描述的很详细。
    // 设置图层代理
    layer.delegate = self;
    
    // 调用图层setNeedDisplay,否则代理方法不会被调用
    [layer setNeedsDisplay];
    // 222222222222222222222222
    
    
    [self.view.layer addSublayer:layer];
}
#pragma mark 绘制图形,图像到图层,注意参数中的ctx是图层的图形上下文,其中绘制位置也是相对图层而言的  calayerBian方法用到
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    UIImage *image = [UIImage imageNamed:@"150-150"];
    CGContextDrawImage(ctx, CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT), image.CGImage);
}

发布了40 篇原创文章 · 获赞 10 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/ai_pple/article/details/50963602