核心動畫(二)

CALayer透視投影修改

動畫案例準(zhǔn)備工作:新建空工程CoreAnimation-Transform陆爽,在Main.storyboard文件中拖入一個UIImageView,添加圖片資源進行配置并關(guān)連,命名為layerView

案例一:下面實現(xiàn)一張圖片圍繞一個Y軸旋轉(zhuǎn)
#import "ViewController.h"

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

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // CATransform3D矩陣可以是一個旋轉(zhuǎn)矩陣仆百、平移矩陣、縮放矩陣奔脐、投影矩陣
    // 參數(shù)一:圍繞角度
    // 參數(shù)二:圍繞x軸
    // 參數(shù)三:圍繞y軸
    // 參數(shù)四:圍繞z軸
    CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);
    self.layerView.layer.transform = transform;
}

@end
查看圖片圍繞Y軸旋轉(zhuǎn)效果

運行工程俄周,我們查看圖片發(fā)現(xiàn)并沒有旋轉(zhuǎn)效果吁讨,圖片甚至發(fā)生了變形。

案例二:修改代碼圍繞Z軸旋轉(zhuǎn)并查看效果
CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);
圖片圍繞Z軸旋轉(zhuǎn)效果

通過對比發(fā)現(xiàn)峦朗,圍繞Z軸可以發(fā)生旋轉(zhuǎn)建丧,而圍繞Y軸我們并沒有查看出旋轉(zhuǎn)效果氧敢。是什么原因造成圖片沒有辦法圍繞Y軸旋轉(zhuǎn)呢罩锐?
原因是在投影的時候西乖,圖片是平面的漱逸;對Y軸進行投影礁芦,我們沒有考慮投影方式炒事,如果我們要想呈現(xiàn)立體效果方咆,我們就要設(shè)置透視投影的方式浸船。

案例三:設(shè)置透視投影方式
- (void)viewDidLoad {
    [super viewDidLoad];
    //投影方式: 2種.正投影,透視投影;
    //CATransform3DIdentity表示單元矩陣
    CATransform3D transform1 = CATransform3DIdentity;
    //m34表示透視投影迄埃,500表示投影的距離疗韵,一般為500/1000
    transform1.m34 = -1.0/500.0;
    /*
     CATransform3D CATransform3DRotate (CATransform3D t, CGFloat angle,
     CGFloat x, CGFloat y, CGFloat z)
     參數(shù)1: t,矩陣CATransform3D對象
     參數(shù)2: 角度(弧度為單位,如果是度數(shù)需要做轉(zhuǎn)化)
     參數(shù)3:  x, (1=旋轉(zhuǎn),0=不旋轉(zhuǎn))
     參數(shù)4:  y,
     參數(shù)5:  z,
     */
    transform1 = CATransform3DRotate(transform1, M_PI_4, 0, 1, 0);
    self.layerView.layer.transform = transform1;
}
圍繞Y軸的旋轉(zhuǎn)效果

我們在做3D旋轉(zhuǎn)的時候,如果針對的是一個平面圖形侄非,我們要想呈現(xiàn)立體效果蕉汪,就要設(shè)置透視投影的屬性。

注意:設(shè)置投影方式跟圍繞哪個軸旋轉(zhuǎn)并沒有關(guān)系逞怨,只是讓圖形呈現(xiàn)出立體效果者疤;如果對圖形平移并且想要呈現(xiàn)立體效果,也需要設(shè)置投影方式叠赦。

滅點:在透視投影中驹马,一束平行于投影面的平行線的投影可以保持平行,而不平行于投影面的平行線的投影會聚集到一個點除秀,這個點稱為滅點糯累;滅點可以看作是無限遠處的一點在投影面上的投影

滅點
案例四:兩張圖片都呈現(xiàn)透視投影的方式(同時可以引申為多張圖片)

Main.storyboard文件中拖入一個UIView并命名為containerView册踩,在containerView上分別拖入兩個UIImageView并命名為layerView1泳姐、layerView2 代碼如下

#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *containerView;
@property (weak, nonatomic) IBOutlet UIImageView *layerView1;
@property (weak, nonatomic) IBOutlet UIImageView *layerView2;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    CATransform3D perspective = CATransform3DIdentity;
    perspective.m34 = -1.0/500;
    //sublayerTransform 子圖層上仿射變換(會影響添加在此圖層上的子圖層)
    self.containerView.layer.sublayerTransform = perspective;
    
    CATransform3D transform2 = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);
    CATransform3D transform3 = CATransform3DMakeRotation(-M_PI_4, 0, 1, 0);
    
    self.layerView1.layer.transform = transform2;
    self.layerView2.layer.transform = transform3;
}

@end

運行工程,兩張圖片都發(fā)生了旋轉(zhuǎn)暂吉,效果圖如下

多張圖片旋轉(zhuǎn)的效果
案例五:圖片旋轉(zhuǎn)180度胖秒,查看圖片背面效果
- (void)viewDidLoad {
    [super viewDidLoad];
    CATransform3D transform1 = CATransform3DIdentity;
    transform1.m34 = -1.0/500.0;
    transform1 = CATransform3DRotate(transform1, M_PI, 0, 1, 0);
    self.layerView.layer.transform = transform1;
}
查看圖片背面

運行工程,我們發(fā)現(xiàn)可以看到圖片背面的效果慕的,原因是圖層默認(rèn)開啟正背面渲染扒怖。
舉例:如果想要呈現(xiàn)一個正方體的立體效果,默認(rèn)情況下最多可以看到三個面业稼,剩下看不到的三個面是不需要畫出來的盗痒,OpenGL ES不會去畫看不到的三個面,這樣的話性能就會提高50%。所以這里我們可以根據(jù)業(yè)務(wù)場景關(guān)閉圖層的正背面渲染屬性俯邓,以提高渲染性能骡楼。

案例六:關(guān)閉圖層的正背面渲染
- (void)viewDidLoad {
    [super viewDidLoad];
    CATransform3D transform1 = CATransform3DIdentity;
    transform1.m34 = -1.0/500.0;
    transform1 = CATransform3DRotate(transform1, M_PI, 0, 1, 0);
    self.layerView.layer.transform = transform1;
    //正背面渲染--> 渲染技術(shù)正背面剔除,判斷用戶可見/不可見
    self.layerView.layer.doubleSided = NO;
}

再次運行工程,我們就看不到圖片的背面效果稽鞭。

透視投影實現(xiàn)立體盒子

動畫案例準(zhǔn)備工作:新建空工程CoreAnimation5鸟整,在Main.storyboard文件中拖入兩個UIView,其中一個view是另一個view的子視圖朦蕴;父視圖view命名為outerView篮条,背景色設(shè)置為紅色,子視圖view命名為innerView吩抓,背景色設(shè)置為藍色涉茧。

案例七:父視圖圍繞Z軸順時針旋轉(zhuǎn)45度,子視圖圍繞Z軸逆時針旋轉(zhuǎn)45度
預(yù)期效果
#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *outerView;
@property (weak, nonatomic) IBOutlet UIView *innerView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    CATransform3D outer = CATransform3DIdentity;
    //透視投影
    outer.m34 = -1.0/500;
    //旋轉(zhuǎn)變換,圍繞Z軸.45度
    outer = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);
    self.outerView.layer.transform = outer;
    
    CATransform3D inner = CATransform3DIdentity;
    inner.m34 = -1.0/500;
    inner = CATransform3DMakeRotation(-M_PI_4, 0, 0, 1);
    self.innerView.layer.transform = inner;
}

@end
運行工程實際效果

疑問:為什么沒有達到我們預(yù)期的效果呢疹娶?
因為手機屏幕是平面的伴栓,紅色view往內(nèi)旋轉(zhuǎn),藍色view往外旋轉(zhuǎn)雨饺,旋轉(zhuǎn)的軸就會相悖钳垮,這時候就需要一個立體空間來解決;如果要想實現(xiàn)預(yù)期效果额港,就要使用3D圖層饺窿;即CALayer無法實現(xiàn),需要專門的3D圖層CATransformLayer來實現(xiàn)移斩。

案例八:使用CATransformLayer圖層實現(xiàn)立體效果

新建帶xib文件的CCViewController頁面肚医,并在CCViewController頁面的View上拖入一個UIView命名為containerView,背景色設(shè)置為黑色叹哭,然后再分別拖入6個UIView忍宋,分別命名為view0痕貌、view1风罩、view2view3舵稠、view4超升、view5 如下圖所示

xib文件創(chuàng)建的view
#import "CCViewController.h"

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

@property (strong, nonatomic) IBOutlet UIView *view0;
@property (strong, nonatomic) IBOutlet UIView *view1;
@property (strong, nonatomic) IBOutlet UIView *view2;
@property (strong, nonatomic) IBOutlet UIView *view3;
@property (strong, nonatomic) IBOutlet UIView *view4;
@property (strong, nonatomic) IBOutlet UIView *view5;

@property(nonatomic,strong)NSArray *faces;
@end

@implementation CCViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.faces = @[_view0,_view1,_view2,_view3,_view4,_view5];
    
    //我們不用修改子視圖,只修改父視圖
    //父View的layer圖層
    CATransform3D perspective = CATransform3DIdentity;
    perspective.m34 = -1.0 / 500.0;
    //父視圖旋轉(zhuǎn)之后查看立體效果哺徊,沿X軸室琢、Y軸分別旋轉(zhuǎn)一次就能看到正方體的三個面
    perspective = CATransform3DRotate(perspective, -M_PI_4, 1, 0, 0);
    perspective = CATransform3DRotate(perspective, -M_PI_4, 0, 1, 0);
    self.containerView.layer.sublayerTransform = perspective;
    
    //add cube face 1
    //Z軸平移100
    CATransform3D transform = CATransform3DMakeTranslation(0, 0, 100);
    [self addFace:0 withTransform:transform];
    
    //add cube face 2
    transform = CATransform3DMakeTranslation(100, 0, 0);
    transform = CATransform3DRotate(transform, M_PI_2, 0, 1, 0);
    [self addFace:1 withTransform:transform];
    
    //add cube face 3
    transform = CATransform3DMakeTranslation(0, -100, 0);
    transform = CATransform3DRotate(transform, M_PI_2, 1, 0, 0);
    [self addFace:2 withTransform:transform];
    
    //add cube face 4
    transform = CATransform3DMakeTranslation(0, 100, 0);
    transform = CATransform3DRotate(transform, -M_PI_2, 1, 0, 0);
    [self addFace:3 withTransform:transform];
    
    //add cube face 5
    transform = CATransform3DMakeTranslation(-100, 0, 0);
    transform = CATransform3DRotate(transform, -M_PI_2, 0, 1, 0);
    [self addFace:4 withTransform:transform];
    
    //add cube face 6
    transform = CATransform3DMakeTranslation(0, 0, -100);
    transform = CATransform3DRotate(transform, M_PI, 0, 1, 0);
    [self addFace:5 withTransform:transform];
}

- (void)addFace:(NSInteger)index withTransform:(CATransform3D)transform
{
    //獲取face視圖并將其添加到容器中
    UIView *face = self.faces[index];
    [self.containerView addSubview:face];
    
    //將face視圖放在容器的中心
    CGSize containerSize = self.containerView.bounds.size;
    face.center = CGPointMake(containerSize.width / 2.0, containerSize.height / 2.0);
    
    //添加transform
    face.layer.transform = transform;
}

@end

ViewController頁面添加跳入CCViewController頁面的邏輯,運行工程查看立體效果

立體盒子效果

父視圖containerView本身的transform并沒有發(fā)生變化落追,只是一個平面盈滴,只是其子視圖發(fā)生了透視投影,讓其子視圖發(fā)生位置與角度的變化。

CAShaperLayer

CoreAnimation專用圖層
專用圖層
專用圖層
CAShaperLayer

CAShaperLayer是?個通過?量圖形指定諸如顏?和線寬等屬性巢钓,?CGPath來定義想要繪制的圖形病苗,最后CAShaperLayer就能渲染出現(xiàn)

  • 渲染快速CAShapeLayer使?了硬件加速器症汹,繪制同?圖形會?用Core Graphics快很多硫朦。
  • ?效使用內(nèi)存。?個CAShapeLayer不需要像普通CALayer一樣創(chuàng)建?個寄宿圖形背镇,所以?論有多大咬展,都不會占?用太多的內(nèi)存。
  • 不會被圖層邊界剪裁掉瞒斩。?個CAShapeLayer可以在邊界之外繪制破婆。你的圖層路徑不會像在使用Core Graphics的普通CALayer一樣被剪裁掉。
  • 不會出現(xiàn)像素化济瓢。當(dāng)你給CAShapeLayer做3D變換時荠割,它不像?個有寄宿圖的普通圖層一樣變得像素化。
案例九:使用CAShaperLayer繪制火柴人
#import "ViewController.h"

@interface ViewController ()
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    UIBezierPath *path = [[UIBezierPath alloc] init];
    [path moveToPoint:CGPointMake(175, 100)];
    //繪制一個圓形
    [path addArcWithCenter:CGPointMake(150, 100) radius:25 startAngle:0 endAngle:2*M_PI clockwise:YES];
    
    [path moveToPoint:CGPointMake(150, 125)];
    
    [path addLineToPoint:CGPointMake(150, 175)];
    [path addLineToPoint:CGPointMake(125, 225)];
    
    [path moveToPoint:CGPointMake(150, 175)];
    [path addLineToPoint:CGPointMake(175, 225)];
    
    [path moveToPoint:CGPointMake(100, 150)];
    [path addLineToPoint:CGPointMake(200, 150)];
    
    //create shape layer
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    //stroke color 畫筆顏色
    shapeLayer.strokeColor = [UIColor redColor].CGColor;
    //fill color 填充顏色
    shapeLayer.fillColor = [UIColor blueColor].CGColor;
    //line width 線段寬度
    shapeLayer.lineWidth = 5;
    //形狀路徑連線樣式
    shapeLayer.lineJoin = kCALineJoinRound;
    //形狀路徑線帽樣式
    shapeLayer.lineCap = kCALineCapRound;
    //shaperLayer 繪制圖形路徑
    shapeLayer.path = path.CGPath;
    //add it to our view
    [self.view.layer addSublayer:shapeLayer];
}
@end
火柴人效果

使用CAShaperLayer繪制圓角旺矾,也可以實現(xiàn)部分圓角

- (void)viewDidLoad {
    [super viewDidLoad];
    //define path parameters
    CGRect rect = CGRectMake(50, 50, 100, 100);
    CGSize radii = CGSizeMake(20, 20);
    UIRectCorner corners1 = UIRectCornerBottomRight | UIRectCornerBottomLeft;
    UIRectCorner corners2 = UIRectCornerTopLeft | UIRectCornerTopRight;
    //create path
    UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corners2 cornerRadii:radii];
    
    //create shape layer
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    //stroke color 畫筆顏色
    shapeLayer.strokeColor = [UIColor redColor].CGColor;
    //fill color 填充顏色
    shapeLayer.fillColor = [UIColor blueColor].CGColor;
    //line width 線段寬度
    shapeLayer.lineWidth = 5;
    //形狀路徑連線樣式
    shapeLayer.lineJoin = kCALineJoinRound;
    //形狀路徑線帽樣式
    shapeLayer.lineCap = kCALineCapRound;
    //shaperLayer 繪制圖形路徑
    shapeLayer.path = path2.CGPath;
    //add it to our view
    [self.view.layer addSublayer:shapeLayer];
}
部分圓角效果

CATextLayer圖層講解

如果你想在一個圖層?面顯示?字蔑鹦,完全可以借助圖層代替字符串,可以使?CATextLayer將內(nèi)容寫入圖層箕宙;UILabel的原理是通過Core Graphics寫入內(nèi)容嚎朽,CATextLayer幾乎包含了所有UILabel的繪制特性,而且比UILabel渲染要快很多柬帕。

案例:使用CATextLayer來渲染文字
- (void)viewDidLoad {
    [super viewDidLoad];
    //create a text layer
    CATextLayer *textLayer = [CATextLayer layer];
    textLayer.frame = CGRectMake(10,100 , self.view.frame.size.width -20, 200);
    [self.view.layer addSublayer:textLayer];
    
    //set text attributes(設(shè)置text的屬性)
    //字體顏色
    textLayer.foregroundColor = [UIColor blackColor].CGColor;
    //對齊方式
    textLayer.alignmentMode = kCAAlignmentCenter;
    //環(huán)繞在邊界范圍內(nèi)
    textLayer.wrapped = YES;
    
    //choose a font (選擇字體)
    UIFont *font = [UIFont systemFontOfSize:15];
    
    //set layer font (設(shè)置圖層字體)
    //將font改成圖層字體
    CFStringRef fontName = (__bridge CFStringRef)font.fontName;
    CGFontRef fontRef = CGFontCreateWithFontName(fontName);
    textLayer.font = fontRef;
    textLayer.fontSize = font.pointSize;
    //模糊的原因是哟忍,沒有以Retina來渲染,contentsScale默認(rèn)值為1陷寝,所以需要傳合適的值
    textLayer.contentsScale = [UIScreen mainScreen].scale;
    //fontRef使用完要記著釋放
    CGFontRelease(fontRef);
    
    //choose some text 文字信息
    NSString *text = @"Hello World";
    
    //set layer text 設(shè)置layer的文字信息
    textLayer.string = text;
}
CATextLayer渲染文字

CATextLayer其實比UILabel更加好用锅很,而且能夠支持富文本

案例:下面我們使用CATextLayer來自定義UILabel
<!-- LayerLabel.h文件 -->
#import <UIKit/UIKit.h>

@interface LayerLabel : UILabel

@end

<!-- LayerLabel.m文件 -->
#import "LayerLabel.h"

@implementation LayerLabel

+ (Class)layerClass
{
    return [CATextLayer class];
}

- (CATextLayer *)textLayer
{
    return (CATextLayer *)self.layer;
}

- (void)setUp
{
    //set defaults from UILabel settings
    self.text = self.text;
    self.textColor = self.textColor;
    self.font = self.font;
    
    [self textLayer].alignmentMode = kCAAlignmentJustified;
    [self textLayer].wrapped = YES;
    [self.layer display];
}

- (id)initWithFrame:(CGRect)frame
{
    //called when creating label programmatically
    if (self = [super initWithFrame:frame]) {
        [self setUp];
    }
    return self;
}

- (void)awakeFromNib
{
    //called when creating label using Interface Builder
    [self setUp];
}

- (void)setText:(NSString *)text
{
    super.text = text;
    //set layer text
    [self textLayer].string = text;
}

- (void)setTextColor:(UIColor *)textColor
{
    super.textColor = textColor;
    //set layer text color
    [self textLayer].foregroundColor = textColor.CGColor;
}

- (void)setFont:(UIFont *)font
{
    super.font = font;
    //set layer font
    CFStringRef fontName = (__bridge CFStringRef)font.fontName;
    CGFontRef fontRef = CGFontCreateWithFontName(fontName);
    [self textLayer].font = fontRef;
    [self textLayer].fontSize = font.pointSize;
    CGFontRelease(fontRef);
}

@end

Main.storyboard拖入LayerLabel控件凤跑,在ViewController.m文件的viewDidLoad方法中設(shè)置layerLabeltext值爆安。

@interface ViewController ()
@property (weak, nonatomic) IBOutlet LayerLabel *LLabel;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.LLabel.text = @"Hello  I'm LayerLabel";  
}

@end

LayerLabel的原理是替換UILabel的圖層,其性能比原來的UILabel更好仔引,渲染更快扔仓。

CATransformLayer圖層講解

CATransformLayer是專?用來創(chuàng)建三維視圖的,上面我們使用的layer.sublayerTransform實現(xiàn)的立體效果咖耘,下面我們使用CATransformLayer來實現(xiàn)翘簇;OpenGL ES也可以實現(xiàn),只是會很麻煩儿倒。

#import "ViewController.h"

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

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor blackColor];
    
    //set up the perspective transform(設(shè)置投影矩陣)
    //CATransformLayer的使用也是需要設(shè)置透視投影的
    //如果想要有一個立體的投影效果版保,必須要設(shè)置投影方式,否則沒有立體效果
    CATransform3D pt = CATransform3DIdentity;
    pt.m34 = -1.0 / 500.0;
    //設(shè)置子圖層是有透視效果的
    self.containerView.layer.sublayerTransform = pt;
    
    //set up the transform for cube 1 and add it
    CATransform3D c1t = CATransform3DIdentity;
    c1t = CATransform3DTranslate(c1t, -100, 0, 0);
    CALayer *cube1 = [self cubeWithTransform:c1t];
    [self.containerView.layer addSublayer:cube1];
    
    //set up the transform for cube 2 and add it
    CATransform3D c2t = CATransform3DIdentity;
    c2t = CATransform3DTranslate(c2t, 100, 0, 0);
    c2t = CATransform3DRotate(c2t, -M_PI_4, 1, 0, 0);
    c2t = CATransform3DRotate(c2t, -M_PI_4, 0, 1, 0);
    CALayer *cube2 = [self cubeWithTransform:c2t];
    [self.containerView.layer addSublayer:cube2];  
}

- (CALayer *)faceWithTransform:(CATransform3D)transform
{
    //create cube face layer
    CALayer *face = [CALayer layer];
    face.frame = CGRectMake(-50, -50, 100, 100);
    //apply a random color
    CGFloat red = (rand() / (double)INT_MAX);
    CGFloat green = (rand() / (double)INT_MAX);
    CGFloat blue = (rand() / (double)INT_MAX);
    face.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
    face.transform = transform;
    return face;
}

- (CALayer *)cubeWithTransform:(CATransform3D)transform
{
    //create cube layer
    CATransformLayer *cube = [CATransformLayer layer];
    
    //add cube face 1
    CATransform3D ct = CATransform3DMakeTranslation(0, 0, 50);
    [cube addSublayer:[self faceWithTransform:ct]];
    
    //add cube face 2
    ct = CATransform3DMakeTranslation(50, 0, 0);
    ct = CATransform3DRotate(ct, M_PI_2, 0, 1, 0);
    [cube addSublayer:[self faceWithTransform:ct]];
    
    //add cube face 3
    ct = CATransform3DMakeTranslation(0, -50, 0);
    ct = CATransform3DRotate(ct, M_PI_2, 1, 0, 0);
    [cube addSublayer:[self faceWithTransform:ct]];
    
    //add cube face 4
    ct = CATransform3DMakeTranslation(0, 50, 0);
    ct = CATransform3DRotate(ct, -M_PI_2, 1, 0, 0);
    [cube addSublayer:[self faceWithTransform:ct]];
    
    //add cube face 5
    ct = CATransform3DMakeTranslation(-50, 0, 0);
    ct = CATransform3DRotate(ct, -M_PI_2, 0, 1, 0);
    [cube addSublayer:[self faceWithTransform:ct]];
    
    //add cube face 6
    ct = CATransform3DMakeTranslation(0, 0, -50);
    ct = CATransform3DRotate(ct, M_PI, 0, 1, 0);
    [cube addSublayer:[self faceWithTransform:ct]];
    
    //center the cube layer within the container(將立方體層至于容器中心)
    CGSize containerSize = self.containerView.bounds.size;
    cube.position = CGPointMake(containerSize.width / 2.0, containerSize.height / 2.0);
    
    //apply the transform and return
    cube.transform = transform;
    return cube;
}

@end
CATransformLayer實現(xiàn)立體效果

CAGradientLayer圖層講解

CAGradientLayer是?來?成兩種或更多種顏?平滑漸變,下面使用CAGradientLayer來實現(xiàn)一個漸變色效果:

- (void)viewDidLoad {
    [super viewDidLoad];
    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    gradientLayer.frame = CGRectMake(10, 50, self.view.frame.size.width - 20, 100);
    // locations數(shù)量要與colors一致彻犁,設(shè)置顏色位置
    gradientLayer.locations = @[@0.25,@0.5,@0.25];
    gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor,(__bridge id)[UIColor blueColor].CGColor,(__bridge id)[UIColor purpleColor].CGColor];
    
    //startPoint蹈垢,endPoint 決定漸變方向,默認(rèn)左上角(0, 0) 右下角坐標(biāo)(1, 1)
    //左上角的位置
    gradientLayer.startPoint = CGPointMake(0, 0);
    //右下角的位置
    gradientLayer.endPoint = CGPointMake(1, 1);
    [self.view.layer addSublayer:gradientLayer];
}
漸變圖層

課后練習(xí):嘗試實現(xiàn)一個環(huán)形的漸變效果袖裕?

CARelicatorLayer圖層講解

CAReplicatorLayer的目的就是為了高效?成許多相似的圖層曹抬,他會繪制一個或者多個圖層的子圖層,并在每個復(fù)制體上應(yīng)?不同的變換急鳄。

下面我們使用CAReplicatorLayer來生成一個圖層的倒影

<!-- ReflectionView.h文件 -->
#import <UIKit/UIKit.h>
@interface ReflectionView : UIView
@end

<!-- ReflectionView.m文件 -->
#import "ReflectionView.h"
@implementation ReflectionView
+ (Class)layerClass
{
    return [CAReplicatorLayer class];
}

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self setUp];
    }
    return self;
}

- (void)awakeFromNib
{
    [self setUp];
}

-(void)setUp
{
    CAReplicatorLayer *layer = (CAReplicatorLayer *)self.layer;
    // 復(fù)制數(shù)量為2
    layer.instanceCount = 2;
    
    CATransform3D transform = CATransform3DIdentity;
    //間隔谤民,創(chuàng)建的兩個圖層之間的間隔
    CGFloat veticalOffset = self.bounds.size.height + 2;
    //平移的距離為veticalOffset
    transform = CATransform3DTranslate(transform, 0, veticalOffset, 0);
    //翻轉(zhuǎn)
    transform = CATransform3DScale(transform, -1, -1, 0);
    layer.instanceTransform = transform;
    
    //K-0.7= 0.3,讓layer圖層的透明度為0.3
    // 這里如果設(shè)置值為0.3疾宏,透明度就相當(dāng)于是 1 + 0.3 = 1.3
    layer.instanceAlphaOffset = -0.7;
}
@end

Main.storyboard文件中拖入一個ReflectionView圖層张足,并在ReflectionView上面添加一個UIImageView且設(shè)置好圖片,運行工程查看效果如下

圖層倒影效果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坎藐,一起剝皮案震驚了整個濱河市为牍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌岩馍,老刑警劉巖碉咆,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蛀恩,居然都是意外死亡疫铜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門双谆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來壳咕,“玉大人,你說我怎么就攤上這事顽馋∥嚼澹” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵寸谜,是天一觀的道長竟稳。 經(jīng)常有香客問我,道長程帕,這世上最難降的妖魔是什么住练? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任地啰,我火速辦了婚禮愁拭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘亏吝。我一直安慰自己岭埠,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著惜论,像睡著了一般许赃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上馆类,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天混聊,我揣著相機與錄音,去河邊找鬼乾巧。 笑死句喜,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的沟于。 我是一名探鬼主播咳胃,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼旷太!你這毒婦竟也來了展懈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤供璧,失蹤者是張志新(化名)和其女友劉穎存崖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體睡毒,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡金句,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吕嘀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片违寞。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖偶房,靈堂內(nèi)的尸體忽然破棺而出趁曼,到底是詐尸還是另有隱情,我是刑警寧澤棕洋,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布挡闰,位于F島的核電站,受9級特大地震影響掰盘,放射性物質(zhì)發(fā)生泄漏摄悯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一愧捕、第九天 我趴在偏房一處隱蔽的房頂上張望奢驯。 院中可真熱鬧,春花似錦次绘、人聲如沸瘪阁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽管跺。三九已至义黎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間豁跑,已是汗流浹背廉涕。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留艇拍,地道東北人火的。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像淑倾,于是被迫代替她去往敵國和親馏鹤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 基礎(chǔ) 核心動畫是 iOS 和 MacOS 上的圖形渲染和動畫基礎(chǔ)結(jié)構(gòu)娇哆,用于為應(yīng)用的視圖和其他視覺元素設(shè)置動畫湃累。 核...
    davon閱讀 1,904評論 0 8
  • 說明:此文僅為筆記,筆者自己總結(jié)了一些重點碍讨,查閱原文請戳這里: iOS核心動畫高級技巧 視覺效果 拉伸過濾 CAL...
    Jisen閱讀 4,816評論 1 9
  • 變換 仿射變換 CGAffineTransform UIView的transform屬性是一個CGAffineTr...
    木小易Ying閱讀 439評論 0 2
  • 書籍是人類進步的階梯 總覽思維導(dǎo)圖 一治力、圖層樹 1.1.contents 簡介:(id類型),雖然是id類型但如果...
    只敲代碼不偷桃閱讀 1,291評論 0 3
  • 本文是要點型筆記勃黍,建議先閱讀以下參考內(nèi)容后再閱讀宵统,完成知識體系的構(gòu)建:[1] View Programming ...
    SvenLearn閱讀 2,985評論 2 43