美文网首页
iOS卡牌动画 卡牌复用

iOS卡牌动画 卡牌复用

作者: coordinator | 来源:发表于2018-11-13 18:05 被阅读43次

卡牌动画实现效果,这里是仿照 积目App 发现陌生人卡牌动画写的动画实现效果,网上找过很多类似的例子,遗憾的是大多数demo都是反复的 new 一个对象,以及 removeFromSuperview。所以这里来写一个复用的两个View来回替换层次实现。

一、动画效果

卡牌动画效果

二、实现原理
原理很简单,在父View上加一个手势,根据手指移动改变在最上层的CardView的Frame。手抬起,最上层的CardView,从屏幕移出去,再放到第二张CardView之下,此时第二张CardView变成第一张,以此类推。

处理手势代码:

- (void)slideCardViewGesture:(UIPanGestureRecognizer *)sender {
    //当前点
    CGPoint touchPoint = [sender locationInView:self];
    //手指在视图上移动的速度(x,y), 正负代表方向,绝对值上|x| > |y| 水平移动, |y|>|x| 竖直移动。
    CGPoint velocity = [sender velocityInView:self];
    
    if (sender.state == UIGestureRecognizerStateBegan) {
        self.toucheUpPoint = touchPoint;
        self.distenceX = 0;
        self.currentFirstCardView = [self getCurrentFirstCardView];
        self.currentSecondCardView = [self getCurrentSecondCardView];
    }
    
    CGFloat percent = [self percentWithCurrent];
    CGRect firstFrame = [self firstCardViewFrame];
    CGRect secondFrame = [self secondCardViewFrame];
    
    //卡牌方向,1:向左 -1:向右
    CGFloat currentDirection = 0;
    if (velocity.x > 0) {
        currentDirection = 1;
    } else {
        currentDirection = -1;
    }
    
    CGFloat distenceX;
    if (self.toucheUpPoint.x > touchPoint.x) {
        distenceX = self.toucheUpPoint.x - touchPoint.x;
    } else {
        distenceX = touchPoint.x - self.toucheUpPoint.x;
    }
    
    CGFloat angle = percent * M_PI/5;

    // 第一个卡牌 随手势移动距离改变位移和旋转
    if (velocity.x > 0) {
        CGAffineTransform locationTransform = CGAffineTransformTranslate(CGAffineTransformIdentity, self.distenceX + distenceX, 0);
        CGAffineTransform rotateTransform = CGAffineTransformRotate(locationTransform, angle);
        self.currentFirstCardView.transform = rotateTransform;
        self.distenceX = self.distenceX + distenceX;
        
    } else {
        CGAffineTransform locationTransform = CGAffineTransformTranslate(CGAffineTransformIdentity, self.distenceX - distenceX, 0);
        CGAffineTransform rotateTransform = CGAffineTransformRotate(locationTransform, angle);
        self.currentFirstCardView.transform = rotateTransform;
        self.distenceX = self.distenceX - distenceX;
    }

    CGFloat xx1 = firstFrame.origin.x - secondFrame.origin.x;
    CGFloat yy1 = firstFrame.origin.y - secondFrame.origin.y;
    CGFloat width1 = firstFrame.size.width - secondFrame.size.width;
    CGFloat height1 = firstFrame.size.height - secondFrame.size.height;
    CGFloat scalePercent = fabs(percent);
    // 第二个卡牌动画
    self.currentSecondCardView.frame = CGRectMake(secondFrame.origin.x + (xx1 * scalePercent),
                                          secondFrame.origin.y + (yy1 * scalePercent),
                                          secondFrame.size.width + (width1 * scalePercent),
                                          secondFrame.size.height + (height1 * scalePercent));

    self.toucheUpPoint = touchPoint;
    
    //手势结束
    //注意:手势结束后,卡牌还在屏幕上,需要手离开屏幕后继续把动画执行完
    if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateCancelled) {
        //right
        if (velocity.x >= 80 || velocity.x < -80) {
            [self animationViewWithDirection:currentDirection cardAngle:angle timer:0.3];
        } else {
            [self animationViewWithDirection:0 cardAngle:angle timer:0.2];
        }
    }
}

- (void)animationViewWithDirection:(CGFloat)currentDirection cardAngle:(CGFloat)angle timer:(NSTimeInterval)time {
    
    [UIView animateWithDuration:time animations:^{
        if (currentDirection == 0) {
            self.currentFirstCardView.transform = CGAffineTransformIdentity;
            self.currentFirstCardView.frame = [self firstCardViewFrame];
            self.currentSecondCardView.frame = [self secondCardViewFrame];
        } else {
            self.currentSecondCardView.frame = [self firstCardViewFrame];
            self.currentFirstCardView.center = CGPointMake(self.currentFirstCardView.center.x + currentDirection * SCREEN_WIDTH, self.secondCardView.center.y);
        }
    } completion:^(BOOL finished) {
        if (currentDirection != 0) {
            [self sendSubviewToBack:self.currentFirstCardView];
            self.currentFirstCardView.hidden = YES;
            self.currentFirstCardView.transform = CGAffineTransformIdentity;
            [self.currentFirstCardView updateImage];
            
            self.currentFirstCardView.frame = [self secondCardViewFrame];
            self.currentFirstCardView.hidden = NO;
            self.currentFirstCardView.isFront = NO;
            self.currentSecondCardView.isFront = YES;
        } else {
        }
    }];
}

此处说明下注意事项:
第二个卡牌放大到第一个位置,放大过程中图片到frame需要同步适配,使用下面方法解决适配问题。

// 保证图片随着cardView 的 frame 改变而改变
        _cardImgView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

demo地址:https://github.com/jiaohaili/CardsViewAnimation

相关文章

  • iOS卡牌动画 卡牌复用

    卡牌动画实现效果,这里是仿照 积目App 发现陌生人卡牌动画写的动画实现效果,网上找过很多类似的例子,遗憾的是大...

  • <塔罗牌>初步了解78张塔牌

    塔罗牌包含大阿卡那牌和小阿卡那牌,塔罗牌的组成卡牌如下: 1、大阿卡那牌 【0】愚者(The Fool,0) 正位...

  • 活动分享|用卡牌带你玩转潜意识

    写在前面:心理卡牌知识普及 1、什么是心理卡牌? 心理卡牌分很多种,如OH卡、珍爱卡、只言片语卡、职业卡、爱情卡....

  • android program learn 1.3

    ViewPage 一种卡牌式样的页面滚动类 原理是以3个卡牌为基础,当前活动卡牌页向左滑动,于是第二卡牌活动,第一...

  • 内心放下对自己的评判

    昨天的牌卡是美好,内心的美好是引子,今天的牌卡是“引子”,相比昨天的牌卡,今天的牌卡更加鼓励我们进行散发性思考,不...

  • OH卡牌—亲密关系2

    前面展示了一张卡牌,这个卡牌组工共有五张卡牌。同样的步骤,选择一张卡牌,然后描述,说明感受,继续想象问题。 我选择...

  • OH牌运用及问句

    常见19套牌卡:一套基础卡(字卡+图卡),任意搭配其他牌卡。用得比较多的是搭配年轻人像牌卡。 应用场景1——引导词...

  • “珍爱卡”体验分享

    坐标:华师 自我卡牌分享 1.抽取一张卡牌时,我抽到“礼物”这张卡牌。 当时第一眼看到这张卡牌,内心顿时很温暖,...

  • 在卡牌中看见成长轨迹——深圳卡牌课感受与收获

    我还记得二零一七年在上海卡牌课的情形,那时我抱着深深的好奇,听学过卡牌的同学说给别人测卡牌时会把别人整哭,说卡牌可...

  • OH卡牌

    扑克牌游戏相信是家喻户晓,老幼皆知的。 今天给大家分享的是OH卡牌游戏,不知道大家是不是了解卡牌? 什么是OH卡牌...

网友评论

      本文标题:iOS卡牌动画 卡牌复用

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