美文网首页疯狂iOS程序员
类似3D效果_CGAffineTransformScale

类似3D效果_CGAffineTransformScale

作者: Dwyane_Coding | 来源:发表于2017-10-23 19:18 被阅读98次
    图片来源于网络

    1️⃣CGAffineTransformMakeTranslation
    (相对平移)假设是一个视图,那么它的起始位置 x 会加上tx , y 会加上 ty
    2️⃣CGAffineTransformScale
    为一个Transformation再加上缩放
    3️⃣CGAffineTransformIdentity
    单位矩阵变换,一般用于仿射变换的初始化或者还原。

    本文将用以上方法做如下gif效果

    gif有点卡顿,坑

    这并不是一个真正的3D效果,但它看起来非常接近

    一、创建变换的label

    1、在storyboard创建一个label,text为"我是肥仔"。

    2、先创一个动画方向的枚举

    typedef enum _AnimationDirection {
        positive  = 1,
        negative = -1,
    } AnimationDirection;
    

    3、创建一个方法

    - (void)cubeTransitionWithLab:(UILabel *)label text:(NSString *)text direction:(AnimationDirection)direction
    

    方法中,先添加一下代码

        UILabel *auxLabel = [[UILabel alloc] initWithFrame:label.frame];
        auxLabel.text = text;
        auxLabel.font = label.font;
        auxLabel.textAlignment = label.textAlignment;
        auxLabel.textColor = label.textColor;
        auxLabel.backgroundColor = label.backgroundColor;
        auxLabel.backgroundColor = [UIColor redColor];
        //offset
        CGFloat auxLabelOffset = (CGFloat)direction *
        auxLabel.frame.size.height/2.0;
        auxLabel.transform = CGAffineTransformScale(CGAffineTransformMakeTranslation(0.0, auxLabelOffset), 1.0, 0.1);
        [label.superview addSubview:auxLabel]; //在label的所在view添加auxLabel,即auxLabel在label的上面覆盖着
    

    上面代码创建了auxLabel,以及设置一些常用属性,auxLabel.transform = CGAffineTransformScale(CGAffineTransformMakeTranslation(0.0, auxLabelOffset), 1.0, 0.1);这句代码是auxLabel在y轴上偏移auxLabelOffset,同时会高度缩小为原来的0.1倍。如图:

    image.png

    4、在cubeTransitionWithLab继续以下代码:

    [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
        auxLabel.transform = CGAffineTransformIdentity;
        label.transform =  CGAffineTransformScale(CGAffineTransformMakeTranslation(0.0, -auxLabelOffset), 1.0, 0.1);
    } completion:^(BOOL finished) {
        label.text = auxLabel.text;
        label.transform = CGAffineTransformIdentity;
        [auxLabel removeFromSuperview];
    }];
    

    把auxLabel还原成为变换之前的样子,过渡持续时间是1.5秒,延迟0秒,效果为UIViewAnimationOptionCurveEaseOut淡出,同时把故事版中的label在y轴与auxLabel反向平移相同的距离,从而造成很微妙的效果(有点像翻页效果)。如图:

    完成后,把label的文字设置与auxLabel一样,把label还原为刚开始的样子,并把auxLabel从Superview移除

    现在从上往下翻页的效果已经出来了,但是看起来怪怪的,我们要做的是一个类似的3D效果,所以得做循环,且一次从上往下,一次从下往上。

    二、设置循环

    1、在viewDidLoad中,声明属性_direction为positive,并调用即将创建的changeFlight方法

    - (void)viewDidLoad {
        [super viewDidLoad];
        _direction = positive;
        [self changeFlight];
    }
    

    创建changeFlight方法,并添加一下代码

    _direction = (CGFloat)(_direction != positive) ? positive : negative;
    CGFloat direction = _direction;
    NSString *str = @"我是靓仔";
    if (_direction != positive) {
        str = @"我不靓仔";
    }
    

    以上代码用了三木运算符,控制不同的_direction,并初始化str

    2、接着,调用cubeTransitionWithLab并传所需参数

    [self cubeTransitionWithLab:self.lab text:str direction: direction];
    

    3、最后,运用GCD方法,延迟标签(label和auxLabel)上下变换变换的时间,并调用自身

    double delayInSeconds = 3.0;
    __block ViewController* bself = self;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [bself changeFlight];
    });
    

    这样就搞定了!大伙可以试试。变换方法比较简单,难的主要是里面的逻辑

    10.27

    添加新功能:关键帧动画
    之前的文章说过UIView.animate这个方法,把多个动画链接在一起,可能你会想到在这方法里面嵌套多个这个方法,达到多个动画链接。但是这样复杂一点的动画,你会崩溃。。
    所以我们可以将整个动画分成几个不同的阶段,或者关键帧,然后将单个的关键帧组合成一个关键帧动画。

    关键帧动画
    - (void)planeDepart {
        
        CGPoint originalCenter = self.planeImage.center;
        [UIView animateKeyframesWithDuration:1.5 delay:0.0 options:UIViewKeyframeAnimationOptionLayoutSubviews animations:^{
            [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.25 animations:^{
                CGPoint center = self.planeImage.center;
                center.x -= 80;
                center.y += 10;
                self.planeImage.center = center;
    //            self.planeImage.center.x += 80;
            }];
            
            [UIView addKeyframeWithRelativeStartTime:0.1 relativeDuration:0.4 animations:^{
                self.planeImage.transform = CGAffineTransformMakeRotation(-M_PI / 8);
            }];
            
            [UIView addKeyframeWithRelativeStartTime:0.25 relativeDuration:0.25 animations:^{
                CGPoint center = self.planeImage.center;
                center.x -= 100;
                center.y -= 50;
                self.planeImage.center = center;
                self.planeImage.alpha = 0.0;
            }];
            
            [UIView addKeyframeWithRelativeStartTime:0.51 relativeDuration:0.01 animations:^{
                self.planeImage.transform = CGAffineTransformIdentity;
                
                CGPoint center = self.planeImage.center;
                center.x = 0.0;
                center.y = originalCenter.y;
                self.planeImage.center = center;
                
            }];
            
            
            [UIView addKeyframeWithRelativeStartTime:0.55 relativeDuration:0.45 animations:^{
                self.planeImage.alpha = 1.0;
                CGPoint center = self.planeImage.center;
                center = originalCenter;
                self.planeImage.center = center;
            }];
            
        } completion:nil];
        
    }
    

    代码解析:
    开始时间和持续时间是0.0和1.0之间的值,指定时间和持续时间是相对于关键帧动画的整个时间的,例如,0.1是10%,0.25是25%,而1.0是整个持续时间的100%。

    效果如下:

    相关文章

      网友评论

      • Dwyane_Coding:图片卡顿,如果想看真正效果,可以运行demo
        Dwyane_Coding:https://github.com/DWadeIsTheBest/advanced-iOS

      本文标题:类似3D效果_CGAffineTransformScale

      本文链接:https://www.haomeiwen.com/subject/uarauxtx.html