2010-10-12 1183 views
1

我在我的智慧结尾试图想出一个这种范例的设计模式。我在这个网站上没有多少运气,但在这个阶段我会尝试任何事情。UIView无限循环动画在每个重复循环后调用一个方法

我试图实现一个雷达类型的动画,因此我旋转的视图360度来表示半径周围的圆旋转。我已经在这个圆周上放置了点,并且能够使用标准的trig来计算圆心的角度。

作为围绕圆半径扫描,如果它与一个点相交(例如,点的角等于扫半径+公差的角度)的点上闪烁。

现在,我已经在很多的方式来实现这种模式,但都没有取得理想的解决方案。这是我尝试过的。

FIRST:iOS4动画块。我会一次旋转半径10度,持续时间为0.1秒,在完成方法中,检查与点的交点。这里的问题是,如果您将该选项设置为重复,则不会调用完成方法。调用完成方法的唯一时间是整个动画终止时,而不是每个重复循环之后,因此此解决方案不起作用。

SECOND:尝试使用CABasicAnimation显式动画。与上述方法相同,每0.1秒旋转10度,并将委托设置为自我并实现animationDidFinish方法。在animationDidFinish方法中,我检查了与点的交点。我将动画设置为累积并重复拍摄以获得巨大价值。该raduis旋转,但再次,animationDidFinish不会被调用,除非我将repeatCount设置为一个小数字,然后它只在repeatCount结束时被调用,而不是在每个重复循环之后。

第三:使用的NSTimer和这种方法确实有效,但动画可以根据是什么在屏幕周围发生的是生涩。我使用0.1秒的计时器刻度,并启动10度的单个动画以及每次刻度的交叉检查。这种方法的问题在于,由于处理器在后台执行其他动画,因此在启动每个动画时容易受到阻碍。请注意,我没有其他两种方法的问题!

第四:我尝试使用两者的组合。点上的CABasicAnimation和点上的NSTimer。这里的问题是,如果iDevice进入休眠状态,然后恢复,它们可能会不同步并发生。

FIFTH:使用iOS3.0风格动画块并用.1sec持续时间旋转10度。使用animationDidStop方法设置委托和animationDidStopSelector,再次调用动画方法以及检查与点的交集。这也起作用,但很像第三种解决方案,当滚动和其他动画发生时,它很干。这很可能是由动画的停止启动性质引起的。

基本上是有没有办法无限动画视图但要调用每一个重复周期后的方法?或者有没有办法让第三个解决方案更顺利?

请帮助,我已经用尽了设计模式。

+0

我认为你的应用程序是opengles的好选择,它会处理你想要做的很棒的性能。如果你想使用框架,你甚至不需要3D以便更容易看看cocos2D。 – Ben 2010-10-13 01:08:51

+0

是的,我听到你说,问题是我到目前为止已经学到了很多,我不知道我想重新开始。 – 2010-10-13 03:31:55

+0

我想我正在接近答案,使用第二种解决方案,我可以保留CABasicAnimation对象并在animationDidStop方法中重新应用它。它肯定不是生涩的,但我在累积部分遇到麻烦。 – 2010-10-13 06:15:53

回答

1

OK,我已经走过了漫长的道路,因为我张贴了这个问题。

接受的设计模式是实际生成的时钟滴答(通常使用CADisplayLink),其以每秒或60取决于任一30帧运行在要如何光滑和快动画是。在每一帧回调中,您都可以修改视图/图层上的变换并使用事务来显示它。

一些关键的注意事项: 构建以测试交叉线和点的方法:

-(BOOL)intersectWithAngle:(CGFloat)rad {   
    return (rad <= angle && rad >= angle - angleIncrement); 
} 

试图修改属性是动画,以防止层/浏览动画新时,必须使用交易价值本身。 (你不想动画它两次)

[CATransaction begin]; 
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; 

self.transform = rotationTransform; 

[CATransaction commit]; 

没有必要不断创建每一帧新的变换,这只是浪费和消耗资源。最好创建一个名为rotationTransform的实例变量/属性,并修改每一帧并将其重新应用到图层/视图。

-(void)displayFrame { 
    rotationTransform.a = cos(angle); 
    rotationTransform.b = sin(angle); 
    rotationTransform.c = -sin(angle); 
    rotationTransform.d = cos(angle); 

    [CATransaction begin]; 
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; 

    self.transform = rotationTransform; 

    [CATransaction commit]; 
} 

接下来,创建方法来实际设置的角度,使用一个实例变量/属性来存储角度并定义角度增量(I使用3度),还预定义2-π,使你并不总是重新计算它。

-(void)processFrame { 
    angle += angleIncrement; 
    if (angle >= M_2PI) { 
     angle -= M_2PI; 
    } 

    if ([self intersectWithAngle:point.angle]) { 
     [point animate]; 
    } 
} 

最后,构建由CADisplayLink调用的方法,该方法设置框架并在保持帧同步的同时显示框架。

-(void)displayLinkDidTick { 
    // get the time now 
    NSTimeInterval timeNow = [NSDate timeIntervalSinceReferenceDate]; 

    if (timeOfLastDraw == 0) { 
     numberOfTicks = 1; 
    } else { 
     NSTimeInterval timeSinceLastDraw = timeNow - timeOfLastDraw; 
     NSTimeInterval desiredTimeInterval = kFrameDuration; 

     numberOfTicks = (NSUInteger)(timeSinceLastDraw/desiredTimeInterval);  
    } 

    if (numberOfTicks > 4) { 
     numberOfTicks = 4; 
     timeOfLastDraw = timeNow; 
    } else { 
     timeOfLastDraw += numberOfTicks * kFrameDuration; 
    } 


    while(numberOfTicks--) { 

     [self processFrame]; 
     if (spriteState == SpriteStateIdle) 
      break; 
     } 

    [self displayFrame]; 

} 

此代码提取物已被大幅修改了这个帖子,其实在其实我做了扫描线的动画,并在同一CADisplayLink实例点的blipping。

0

我不知道这会工作:

UIView* yourView = ...; 
// preparing the callbacks: 
void(^)(void) animations = ...; // the animation would rotate 10 degrees 
void(^)(BOOL) completion = ^(BOOL finished) { 
    // do your radar stuff 
    [UIView animateWithDuration:0.1 animations:animations completion:completion]; 
} 

// the first call to start it all 
[UIView animateWithDuration:0.1 animations:animations completion:completion]; 

的想法是每一次再次调用动画序列整理你的雷达活动后,假设雷达检查是不是一个沉重一个它应该光滑。

+0

我认为保持动画平滑的问题是在它完成之前抓住它,这样你就不会删除动画层并且不得不重新创建它。但是,我会在去掉动画层之前先给它调用这个方法,并且有智慧重用对象而不是创建一个新对象。 – 2010-10-13 05:50:07

+0

其实我越想越多,我觉得这更像我的第五个解决方案,但你永远不知道。 – 2010-10-13 05:54:14

+0

我不确定。听起来很相似,但这是更多的iOS 4.0风格。 :-)无论如何,你应该检查你的其他动画属性,如果它太生涩 - 也许动画曲线是错误的,或者你应该设置“从当前位置开始动画”或什么的。 – 2010-10-13 19:36:41

2

让它完美地工作。

这里是我所做的:

1 /应用一个CABasicAnimation旋转对象到层旋转每2秒360度。 (不需要使其累计这种方式)

2 /设置一个计时器来调用每0.1秒层表示层。

3 /计算从3D角度变换存储在表示层。 Click here为我的答案如何做到这一点。

4 /检查相交角度。

完成:-)

观光注意:基于180名-180度和不为0到360度 使用ATAN2和不ATAN作为后只会给之间的角度 三维变换第一象限内的角度。