核心动画(二)

CALayer透视投影修改

动画案例准备工作:新建空工程CoreAnimation-Transform,在Main.storyboard文件中拖入一个UIImageView,添加图片资源进行配置并关连,命名为layerView

案例一:下面实现一张图片围绕一个Y轴旋转
#import "ViewController.h"

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

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // CATransform3D矩阵可以是一个旋转矩阵、平移矩阵、缩放矩阵、投影矩阵
    // 参数一:围绕角度
    // 参数二:围绕x轴
    // 参数三:围绕y轴
    // 参数四:围绕z轴
    CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);
    self.layerView.layer.transform = transform;
}

@end
查看图片围绕Y轴旋转效果

运行工程,我们查看图片发现并没有旋转效果,图片甚至发生了变形。

案例二:修改代码围绕Z轴旋转并查看效果
CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);
图片围绕Z轴旋转效果

通过对比发现,围绕Z轴可以发生旋转,而围绕Y轴我们并没有查看出旋转效果。是什么原因造成图片没有办法围绕Y轴旋转呢
原因是在投影的时候,图片是平面的;对Y轴进行投影,我们没有考虑投影方式,如果我们要想呈现立体效果,我们就要设置透视投影的方式。

案例三:设置透视投影方式
- (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)
     参数1: t,矩阵CATransform3D对象
     参数2: 角度(弧度为单位,如果是度数需要做转化)
     参数3:  x, (1=旋转,0=不旋转)
     参数4:  y,
     参数5:  z,
     */
    transform1 = CATransform3DRotate(transform1, M_PI_4, 0, 1, 0);
    self.layerView.layer.transform = transform1;
}
围绕Y轴的旋转效果

我们在做3D旋转的时候,如果针对的是一个平面图形,我们要想呈现立体效果,就要设置透视投影的属性。

注意:设置投影方式跟围绕哪个轴旋转并没有关系,只是让图形呈现出立体效果;如果对图形平移并且想要呈现立体效果,也需要设置投影方式。

灭点:在透视投影中,一束平行于投影面的平行线的投影可以保持平行,而不平行于投影面的平行线的投影会聚集到一个点,这个点称为灭点;灭点可以看作是无限远处的一点在投影面上的投影

灭点
案例四:两张图片都呈现透视投影的方式(同时可以引申为多张图片)

Main.storyboard文件中拖入一个UIView并命名为containerView,在containerView上分别拖入两个UIImageView并命名为layerView1layerView2 代码如下

#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

运行工程,两张图片都发生了旋转,效果图如下

多张图片旋转的效果
案例五:图片旋转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;
}
查看图片背面

运行工程,我们发现可以看到图片背面的效果,原因是图层默认开启正背面渲染
举例:如果想要呈现一个正方体的立体效果,默认情况下最多可以看到三个面,剩下看不到的三个面是不需要画出来的,OpenGL ES不会去画看不到的三个面,这样的话性能就会提高50%。所以这里我们可以根据业务场景关闭图层的正背面渲染属性,以提高渲染性能。

案例六:关闭图层的正背面渲染
- (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;
    //正背面渲染--> 渲染技术正背面剔除,判断用户可见/不可见
    self.layerView.layer.doubleSided = NO;
}

再次运行工程,我们就看不到图片的背面效果。

透视投影实现立体盒子

动画案例准备工作:新建空工程CoreAnimation5,在Main.storyboard文件中拖入两个UIView,其中一个view是另一个view的子视图;父视图view命名为outerView,背景色设置为红色,子视图view命名为innerView,背景色设置为蓝色。

案例七:父视图围绕Z轴顺时针旋转45度,子视图围绕Z轴逆时针旋转45度
预期效果
#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;
    //旋转变换,围绕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
运行工程实际效果

疑问:为什么没有达到我们预期的效果呢?
因为手机屏幕是平面的,红色view往内旋转,蓝色view往外旋转,旋转的轴就会相悖,这时候就需要一个立体空间来解决;如果要想实现预期效果,就要使用3D图层;即CALayer无法实现,需要专门的3D图层CATransformLayer来实现。

案例八:使用CATransformLayer图层实现立体效果

新建带xib文件的CCViewController页面,并在CCViewController页面的View上拖入一个UIView命名为containerView,背景色设置为黑色,然后再分别拖入6个UIView,分别命名为view0view1view2view3view4view5 如下图所示

xib文件创建的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;
    //父视图旋转之后查看立体效果,沿X轴、Y轴分别旋转一次就能看到正方体的三个面
    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并没有发生变化,只是一个平面,只是其子视图发生了透视投影,让其子视图发生位置与角度的变化。

CAShaperLayer

CoreAnimation专用图层
专用图层
专用图层
CAShaperLayer

CAShaperLayer是⼀个通过⽮量图形指定诸如颜⾊和线宽等属性,⽤CGPath来定义想要绘制的图形,最后CAShaperLayer就能渲染出现

  • 渲染快速CAShapeLayer使⽤了硬件加速器,绘制同⼀图形会⽐用Core Graphics快很多。
  • ⾼效使用内存。⼀个CAShapeLayer不需要像普通CALayer一样创建⼀个寄宿图形,所以⽆论有多大,都不会占⽤用太多的内存。
  • 不会被图层边界剪裁掉。⼀个CAShapeLayer可以在边界之外绘制。你的图层路径不会像在使用Core Graphics的普通CALayer一样被剪裁掉。
  • 不会出现像素化。当你给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绘制圆角,也可以实现部分圆角

- (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将内容写入图层;UILabel的原理是通过Core Graphics写入内容,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(设置text的属性)
    //字体颜色
    textLayer.foregroundColor = [UIColor blackColor].CGColor;
    //对齐方式
    textLayer.alignmentMode = kCAAlignmentCenter;
    //环绕在边界范围内
    textLayer.wrapped = YES;
    
    //choose a font (选择字体)
    UIFont *font = [UIFont systemFontOfSize:15];
    
    //set layer font (设置图层字体)
    //将font改成图层字体
    CFStringRef fontName = (__bridge CFStringRef)font.fontName;
    CGFontRef fontRef = CGFontCreateWithFontName(fontName);
    textLayer.font = fontRef;
    textLayer.fontSize = font.pointSize;
    //模糊的原因是,没有以Retina来渲染,contentsScale默认值为1,所以需要传合适的值
    textLayer.contentsScale = [UIScreen mainScreen].scale;
    //fontRef使用完要记着释放
    CGFontRelease(fontRef);
    
    //choose some text 文字信息
    NSString *text = @"Hello World";
    
    //set layer text 设置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方法中设置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是专⻔用来创建三维视图的,上面我们使用的layer.sublayerTransform实现的立体效果,下面我们使用CATransformLayer来实现;OpenGL ES也可以实现,只是会很麻烦。

#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(设置投影矩阵)
    //CATransformLayer的使用也是需要设置透视投影的
    //如果想要有一个立体的投影效果,必须要设置投影方式,否则没有立体效果
    CATransform3D pt = CATransform3DIdentity;
    pt.m34 = -1.0 / 500.0;
    //设置子图层是有透视效果的
    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实现立体效果

CAGradientLayer图层讲解

CAGradientLayer是⽤来⽣成两种或更多种颜⾊平滑渐变,下面使用CAGradientLayer来实现一个渐变色效果:

- (void)viewDidLoad {
    [super viewDidLoad];
    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    gradientLayer.frame = CGRectMake(10, 50, self.view.frame.size.width - 20, 100);
    // locations数量要与colors一致,设置颜色位置
    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 决定渐变方向,默认左上角(0, 0) 右下角坐标(1, 1)
    //左上角的位置
    gradientLayer.startPoint = CGPointMake(0, 0);
    //右下角的位置
    gradientLayer.endPoint = CGPointMake(1, 1);
    [self.view.layer addSublayer:gradientLayer];
}
渐变图层

课后练习:尝试实现一个环形的渐变效果?

CARelicatorLayer图层讲解

CAReplicatorLayer的目的就是为了高效⽣成许多相似的图层,他会绘制一个或者多个图层的子图层,并在每个复制体上应⽤不同的变换。

下面我们使用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;
    // 复制数量为2
    layer.instanceCount = 2;
    
    CATransform3D transform = CATransform3DIdentity;
    //间隔,创建的两个图层之间的间隔
    CGFloat veticalOffset = self.bounds.size.height + 2;
    //平移的距离为veticalOffset
    transform = CATransform3DTranslate(transform, 0, veticalOffset, 0);
    //翻转
    transform = CATransform3DScale(transform, -1, -1, 0);
    layer.instanceTransform = transform;
    
    //K-0.7= 0.3,让layer图层的透明度为0.3
    // 这里如果设置值为0.3,透明度就相当于是 1 + 0.3 = 1.3
    layer.instanceAlphaOffset = -0.7;
}
@end

Main.storyboard文件中拖入一个ReflectionView图层,并在ReflectionView上面添加一个UIImageView且设置好图片,运行工程查看效果如下

图层倒影效果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容