2012-03-02 57 views
13

我已经使用CAKeyframeAnimations为图层的transform.rotationtransform.translation.x属性设置动画效果,但我无法隐式动画设置transform属性。我有一个必须在两个状态之间动画的图层,而CABasicAnimation的默认插值完全不正确,并且不遵循我想要的路径。 CAKeyframeAnimation来拯救,或者我想。任何使用CAKeyframeAnimation动画transform的尝试都会导致该视图在其他动画运行时立即捕捉到最终变换。如果我删除了以下函数的前半部分,并让我的“变形”事件在底部使用了CABasicAnimation,则它的动画效果非常好 - 尽管沿途有不正确的插值变换。如何使用CAKeyframeAnimation为CATransform3D设置动画效果?

我的层代表已经实现了以下内容:

- (id <CAAction>) actionForLayer:(CALayer *)layer forKey:(NSString *)event 
{  
    if ([event isEqualToString:@"transform"]) 
    { 
     CGSize startSize = ((CALayer *)self.layer.presentationLayer).bounds.size; 
     CGSize endSize = self.layer.bounds.size; 

     CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:event]; 
     animation.duration = 0.25; 

     NSMutableArray *values = [NSMutableArray array]; 

     int stepCount = 10; 
     for (int i = 0; i < stepCount; i++) 
     { 
      CGFloat p = i/(float)(stepCount - 1); 
      CGSize size = [self interpolateBetweenSize:startSize andSize:endSize percentage:p]; 
      CATransform3D transform = [self transformForSize:size]; 
      [values addObject:[NSValue valueWithCATransform3D:transform]]; 
     } 

     animation.values = values; 
     return animation; 
    } 

    // All other animations use this basic animation 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event]; 
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    animation.removedOnCompletion = YES; 
    animation.fillMode = kCAFillModeForwards; 
    animation.duration = 0.25; 
    return animation; 
} 

我的变换是平移再旋转,但我认为有独立的关键帧动画,动画通过平移和旋转会导致疯狂的一组动画镇。我已经确认,&变换的大小对于我通过的所有p值都是正确的,并且p的严格范围从0到1.

我试过设置非默认定时功能,我试过设置一组定时函数,我省略了关键时间,我设置了一个0的重复计数,removedOnCompletion = YES,以及一个fillMode的转发并且没有任何效果。我没有正确创建变换关键帧动画?

+1

你能否澄清你试图达到的确切效果?你将它描述为一个翻译后跟一个旋转,但是从你的代码看,它的边界也是动画 - 这是否正确?您希望图层移动,然后旋转,边界在移动/旋转动画的两个阶段中不断增大或缩小? – GSnyder 2012-03-11 01:01:41

+0

它为什么需要隐含?这段代码看起来很拙劣。如果你想细粒度的控制,为什么不创建动画并直接将其添加到图层,你说你已经工作了?如果你想要使用默认动画,只需从该委托方法返回'nil'即可。 – 2012-03-12 01:08:48

回答

0

这种技术可以在iOS 3中工作,但似乎在iOS 5.0中被破坏了。

5.1'神奇地'修复了这个问题,它似乎是iOS 5.0中的一个bug。我会提交一个雷达,但它现在在5.1中工作。

@Gsnyder:一些背景:我正在尝试使用Clear-like UI(与Clear完全无关),并且提出了这个问题:http://blog.massivehealth.com/post/18563684407/clear。这应该解释需要旋转&翻译。

我从此创建了一个快门过渡,将视图细分为N层(而不是仅仅2个),从侧面看时看起来像这样://///。

我的代码不是动画边界,它使用每一步的大小来确定必要的变换。

@ Paul.s:隐式允许我在层类本身中保留这种抽象,而不污染拥有它的视图控制器。视图控制器应该只是改变周围的边界,并且图层应该适当地移动。当视图本身可以处理它时,我不是拥有许多自定义动画的视图控制器的粉丝。

我需要使用关键帧动画,因为层之间的默认动画通过不正确的角度转换/和_动画,所以/// \层在整个转换中不排队。关键帧动画确保边缘在所有动画都正确排列。

我在考虑这封闭,这似乎是iOS 5.0中的一个错误,并已被修复。感谢大家。

0
(void)animateViewWith3DCurrentView:(UIView *)currentView withPoing:(CGPoint)movePoint 
{ 
    //flip the view by 180 degrees in its place first. 
    currentView.layer.transform =   CATransform3DRotate(currentView.layer.transform,myRotationAngle(180), 0, 1, 0); 

    //set the anchor point so that the view rotates on one of its sides. 
    currentView.layer.anchorPoint = CGPointMake(0.5, 0.5); 

    //Set up scaling 

    CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:kResizeKey]; 

    //we are going to fill the screen here. So 423,337 
    [resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(423, 337)]]; 
    resizeAnimation.fillMode   = kCAFillModeForwards; 
    resizeAnimation.removedOnCompletion = NO; 

    // Set up path movement 

    UIBezierPath *movePath = [UIBezierPath bezierPath]; 

    //the control point is now set to centre of the filled screen. Change this to make the path different. 
    // CGPoint ctlPoint  = CGPointMake(0.0, 0.5); 
    CGPoint ctlPoint  = CGPointMake(1024/2, 768/2); 

    //This is the starting point of the animation. This should ideally be a function of the frame of the view to be animated. Hardcoded here. 

    // Set here to get the accurate point.. 
    [movePath moveToPoint:movePoint]; 

    //The anchor point is going to end up here at the end of the animation. 
    [movePath addQuadCurveToPoint:CGPointMake(1024/2, 768/2) controlPoint:ctlPoint]; 

    CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:kPathMovement]; 

    moveAnim.path    = movePath.CGPath; 
    moveAnim.removedOnCompletion = YES; 

    // Setup rotation animation 

    CABasicAnimation* rotateAnimation = [CABasicAnimation animationWithKeyPath:kRotation]; 
    //start from 180 degrees (done in 1st line) 
    CATransform3D fromTransform  = CATransform3DMakeRotation(myRotationAngle(180), 0, 1, 0); 
    //come back to 0 degrees 
    CATransform3D toTransform   = CATransform3DMakeRotation(myRotationAngle(0), 0, 1, 0); 

    //This is done to get some perspective. 
    CATransform3D persp1 = CATransform3DIdentity; 
    persp1.m34 = 1.0/-3000; 

    fromTransform = CATransform3DConcat(fromTransform, persp1); 
    toTransform = CATransform3DConcat(toTransform,persp1); 

    rotateAnimation.toValue    = [NSValue valueWithCATransform3D:toTransform]; 
    rotateAnimation.fromValue   = [NSValue valueWithCATransform3D:fromTransform]; 
    //rotateAnimation.duration   = 2; 
    rotateAnimation.fillMode   = kCAFillModeForwards; 
    rotateAnimation.removedOnCompletion = NO; 


    // Setup and add all animations to the group 

    CAAnimationGroup *group = [CAAnimationGroup animation]; 

    [group setAnimations:[NSArray arrayWithObjects:moveAnim,rotateAnimation, resizeAnimation, nil]]; 

    group.fillMode   = kCAFillModeForwards; 
    group.removedOnCompletion = NO; 
    group.duration   = 0.7f; 
    group.delegate   = self; 

    [group setValue:currentView forKey:kGroupAnimation]; 

    [currentView.layer addAnimation:group forKey:kLayerAnimation]; 
} 
相关问题