- (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,否则会影响到下次变幻时的显示状态