CGAffineTransform與CABasicAnimation

- (id)translateAnimation:(NSDictionary *)translateInfo {

    CGFloat precent = translateInfo[@"percent"] == nil ? 1 : [translateInfo[@"percent"] floatValue];

    NSString *beginPointString = translateInfo[@"beginPoint"];

    CGPoint begin = beginPointString == nil ? lastPoint : [[NSValue valueWithCGPoint:CGPointFromString(beginPointString)] CGPointValue];

    NSString *endPointString = translateInfo[@"endPoint"];

    CGPoint endPoint = [[NSValue valueWithCGPoint:CGPointFromString(endPointString)] CGPointValue];

    

    //endPoint = beginPointString == nil ? endPoint : CGPointMake(begin.x + precent * (endPoint.x - begin.x), begin.y + precent * (endPoint.y - begin.y));

    

    float duration = [translateInfo[@"duration"] floatValue];

    NSString *curve = translateInfo[@"curve"];

    BOOL animated = [translateInfo[@"animated"] boolValue];

    

    CABasicAnimation *animationX = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];

    animationX.autoreverses = NO;

    animationX.removedOnCompletion = NO;

    animationX.repeatCount = 0;

    animationX.fromValue @(begin.x);

    animationX.toValue = @(endPoint.x);

    

    CABasicAnimation *animationY = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];

    animationY.autoreverses = NO;

    animationY.removedOnCompletion = NO;

    animationY.repeatCount = 0;

    animationY.fromValue = @(begin.y);

    animationY.toValue = @(endPoint.y);

    

    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];

    animationGroup.removedOnCompletion = NO;

    animationGroup.delegate = self;

    animationGroup.duration = duration;

    animationGroup.timingFunction = [MRPageAttachment curve:curve];

    animationGroup.repeatCount = 0;

    animationGroup.fillMode = kCAFillModeForwards;

    animationGroup.animations = @[ animationX, animationY ];

    

    if (translateInfo[@"percent"] != nil) {

        // 根據位移比例來計算transform

        CGAffineTransform newTransform1 = CGAffineTransformIdentity;

        newTransform1 = CGAffineTransformMakeTranslation((endPoint.x - begin.x) * precent + begin.x - (self.pageAttachment.frame.origin.x + self.pageAttachment.frame.size.width/2), (endPoint.y - begin.y) * precent + begin.y - (self.pageAttachment.frame.origin.y + self.pageAttachment.frame.size.height/2));

        self.transform = newTransform1;

        lastTransform = newTransform1;

        return nil;

    } else {

        lastPoint = endPoint;

        CGAffineTransform newTransform1 = CGAffineTransformIdentity;

        newTransform1 = CGAffineTransformMakeTranslation(endPoint.x - begin.x, endPoint.y - begin.y);


        newTransform = CGAffineTransformConcat(newTransform, newTransform1);

        if (!animated) {

            self.transform = newTransform;

            return nil;

        }


        return animationGroup;

    }

}


- (id)scaleAnimation:(NSDictionary *)scaleInfo {

    CGFloat precent = scaleInfo[@"percent"] == nil ? 1 : [scaleInfo[@"percent"] floatValue];

    NSString *beginScaleString = scaleInfo[@"beginScale"];

    CGPoint beginScale = beginScaleString == nil ? lastScale : [[NSValue valueWithCGPoint:CGPointFromString(beginScaleString)] CGPointValue];

    NSString *endScaleString = scaleInfo[@"endScale"];

    CGPoint endScale = [[NSValue valueWithCGPoint:CGPointFromString(endScaleString)] CGPointValue];

    endScale = beginScaleString == nil ? endScale : CGPointMake(beginScale.x + precent * (endScale.x - beginScale.x), beginScale.y + precent * (endScale.y - beginScale.y));

    float duration = [scaleInfo[@"duration"] floatValue];

    NSString *curve = scaleInfo[@"curve"];

    BOOL animated = [scaleInfo[@"animated"] boolValue];

   

    if (newTransform.b != 0 || newTransform.c != 0) {

        if (endScale.x != endScale.y) {

            return nil;

        }

    }


    CABasicAnimation *animationX = [CABasicAnimation animationWithKeyPath:@"transform.scale.x"];

    animationX.timingFunction = [MRPageAttachment curve:curve];

    animationX.fromValue = [NSNumber numberWithFloat:beginScale.x];

    animationX.toValue = [NSNumber numberWithFloat:endScale.x];

    animationX.autoreverses = NO;

    animationX.cumulative = YES;

 

    CABasicAnimation *animationY = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];

    animationY.timingFunction = [MRPageAttachment curve:curve];

    animationY.fromValue = [NSNumber numberWithFloat:beginScale.y];

    animationY.toValue = [NSNumber numberWithFloat:endScale.y];

    animationY.autoreverses = NO;

    animationY.cumulative = YES;


    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];

    animationGroup.removedOnCompletion = NO;

    animationGroup.delegate = self;

    animationGroup.duration = duration;

    animationGroup.timingFunction = [MRPageAttachment curve:curve];

    animationGroup.repeatCount = 0;

    animationGroup.fillMode = kCAFillModeForwards;

    animationGroup.animations = @[ animationX, animationY ];

    

    CGAffineTransform newTransform1 = CGAffineTransformIdentity;

    newTransform1 = CGAffineTransformMakeScale(endScale.x, endScale.y);

    

    CGAffineTransform newTransform2 = CGAffineTransformIdentity;

    newTransform2 = CGAffineTransformMakeScale(1 / lastScale.x, 1 / lastScale.y);

    

    // 恢復前一次放大狀態

    if (newTransform.ty != 0 || newTransform.tx != 0) {

        CGFloat tx = newTransform.tx;

        CGFloat ty = newTransform.ty;

        newTransform = CGAffineTransformMake(newTransform.a, newTransform.b, newTransform.c, newTransform.d, 0 * fabs(tx) , 0 * fabs(ty));

        newTransform = CGAffineTransformConcat(newTransform, newTransform2);

        newTransform = CGAffineTransformMake(newTransform.a, newTransform.b, newTransform.c, newTransform.d, tx, ty);

    } else {

        newTransform = CGAffineTransformConcat(newTransform, newTransform2);

    }


    if (newTransform.ty != 0 || newTransform.tx != 0) {

        CGFloat tx = newTransform.tx;

        CGFloat ty = newTransform.ty;

        newTransform = CGAffineTransformMake(newTransform.a, newTransform.b, newTransform.c, newTransform.d, 0 * fabs(tx) , 0 * fabs(ty));

        newTransform = CGAffineTransformConcat(newTransform, newTransform1);

        newTransform = CGAffineTransformMake(newTransform.a, newTransform.b, newTransform.c, newTransform.d, tx, ty);

    } else {

        newTransform = CGAffineTransformConcat(newTransform, newTransform1);

    }

    

    lastScale = endScale;

    lastPoint = CGPointMake(newTransform.tx, newTransform.ty);

    if (!animated) {

        self.transform = newTransform;

        return nil;

    }


    return animationGroup;

}


- (id)rotateAnimation:(NSDictionary *)rotateInfo {

    CGFloat precent = rotateInfo[@"percent"] == nil ? 1 : [rotateInfo[@"percent"] floatValue];

    float beginAngle = rotateInfo[@"beginAngle"] == nil ? lastAngle : [rotateInfo[@"beginAngle"] floatValue];

    float endAngle = [rotateInfo[@"endAngle"] floatValue];

    endAngle = rotateInfo[@"beginAngle"] == nil ? endAngle : beginAngle + precent * (endAngle - beginAngle);

    float duration = [rotateInfo[@"duration"] floatValue];

    NSString *curve = rotateInfo[@"curve"];

    BOOL animated = [rotateInfo[@"animated"] boolValue];

    

    

    CABasicAnimation* animation;

    animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

    animation.timingFunction = [MRPageAttachment curve:curve];

    animation.fromValue @(beginAngle / 180 * M_PI);

    animation.toValue = @(endAngle / 180 * M_PI);

    animation.duration = duration;

    animation.autoreverses = NO;

    animation.delegate = self;

    animation.removedOnCompletion = NO;

    animation.fillMode = kCAFillModeForwards;

   

    if (rotateInfo[@"percent"] != nil) {

        // 換算出相對於初始0角度時的旋轉的角度

        CGFloat angleOffset = (precent - (0 - beginAngle) / (endAngle - beginAngle)) * (endAngle - beginAngle);

        CGFloat rotateOffset = angleOffset * M_PI / 180;

        CGFloat newOffset = rotateOffset - self.transformBeginFloat;

        

        lastTransform = CGAffineTransformRotate(self.transform, newOffset);

        self.transform = lastTransform;

        self.transformBeginFloat = rotateOffset;

        self.transformFloat = rotateOffset;

        return nil;

    } else {

        

        CGAffineTransform newTransform1 = CGAffineTransformIdentity;

        newTransform1 = CGAffineTransformMakeRotation((endAngle - beginAngle) / 180 * M_PI);

        

        if (newTransform.ty != 0 || newTransform.tx != 0) {

            CGFloat tx = newTransform.tx;

            CGFloat ty = newTransform.ty;

            newTransform = CGAffineTransformMake(newTransform.a, newTransform.b, newTransform.c, newTransform.d, 0 * fabs(tx) , 0 * fabs(ty));

            newTransform = CGAffineTransformConcat(newTransform, newTransform1);

            newTransform = CGAffineTransformMake(newTransform.a, newTransform.b, newTransform.c, newTransform.d, tx, ty);

        } else {

            newTransform = CGAffineTransformConcat(newTransform, newTransform1);

        }

        

        lastAngle = endAngle;

        lastPoint = CGPointMake(newTransform.tx, newTransform.ty);

        if (!animated) {

            self.transform = newTransform;

            return nil;

        }

        

        return animation;

    }

}


#pragma mark - CAAnimation委託

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {

    self.finishedAnimation = YES;

    if ([theAnimation isKindOfClass:[CATransition class]]) {

        if (flag) {

            [self.pageView removePageAttachmentView:self];

        }

    } else {

        if (!CGAffineTransformEqualToTransform(newTransform, CGAffineTransformIdentity)) {

            self.transform = newTransform;

            [self.layer removeAllAnimations];

        }

        [self.delegate pageAttachmentView:self finishedEventAnimation:animationKey];

    }

}

重點,在動畫結束後,設置transform的時候,要去掉之前存在的animation,否則會影響到下次變幻時的顯示狀態

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章