Kud*_*oCC 17 iphone animation core-animation calayer ios
我正在研究核心动画编程指南中的动画,我不得不理解暂停和恢复图层上的动画.
该文档告诉我如何在没有明确解释的情况下暂停和恢复动画.我认为关键是要了解什么是方法timeOffset和beginTime方法CAlayer.
这些代码是暂停和恢复动画.在resumeLayer方法中,layer.beginTime = timeSincePause;这条线真的让我感到困惑.
-(void)pauseLayer:(CALayer*)layer {
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
-(void)resumeLayer:(CALayer*)layer {
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
Run Code Online (Sandbox Code Playgroud)
任何帮助将不胜感激.
Kud*_*oCC 21
让我们对图层的两个属性进行测试:beginTime和timeOffset.
条件
我们使用了CALayer的时间空间 [layer convertTime:CACurrentMediaTime() fromLayer:nil]
1,将5.0分配给图层beginTime(beginTime之前为0):
NSLog(@"CACurrentMediaTime:%f", [t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
t1.layer.beginTime = 5.0 ;
NSLog(@"CACurrentMediaTime:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
Run Code Online (Sandbox Code Playgroud)
结果日志是:
2014-01-15 11:00:33.811 newUserInterface[1404:70b] CACurrentMediaTime:7206.884498
2014-01-15 11:00:33.811 newUserInterface[1404:70b] CACurrentMediaTime:7201.885088
Run Code Online (Sandbox Code Playgroud)
结果显示,如果我添加5.0 beginTime,则图层的时间将减去5.0.如果动画正在进行中,则添加5.0 beginTime将导致动画在5.0秒前重做动画.
2,将5.0分配给图层timeOffset(timeOffset之前为0):
NSLog(@"CACurrentMediaTime:%f", [t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
t1.layer.timeOffset = 5.0 ;
NSLog(@"CACurrentMediaTime:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
Run Code Online (Sandbox Code Playgroud)
结果是:
2014-01-15 11:09:07.757 newUserInterface[1449:70b] CACurrentMediaTime:7720.851464
2014-01-15 11:09:07.758 newUserInterface[1449:70b] CACurrentMediaTime:7725.852011
Run Code Online (Sandbox Code Playgroud)
结果显示,如果我添加5.0 timeOffset,则图层的时间将添加5.0.如果动画正在进行中,则在timeOffset上添加5.0将导致动画跳转到5.0秒后的动画.
理解暂停和恢复图层上的动画
这是一个例子,t1是UIViewController的根视图的子视图.我在t1上做了一个动画,动画的位置t1.layer.
如果将动画添加到图层,则图层将根据动画计算何时为动画设置动画beginTime,如果beginTime为0,则会立即为其设置动画.
CABasicAnimation * b1 = [CABasicAnimation animationWithKeyPath:@"position"] ;
b1.toValue = [NSValue valueWithCGPoint:CGPointMake(160.0, 320.0)] ;
b1.duration = 10.0f ;
[t1.layer addAnimation:b1 forKey:@"pos"] ;
NSLog(@"CACurrentMediaTime:%f", [t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
Run Code Online (Sandbox Code Playgroud)
日志显示2014-01-15 11:25:53.975 newUserInterface[1530:70b] CACurrentMediaTime:8727.108740,这意味着动画将从8727开始,并在t1.layer的时间空间中停在8727 + 10.
当动画在飞行中时,我使用- (void)pauseLayer:(CALayer*)layer方法暂停动画.
layer.speed = 0.0; 将导致图层停止,图层的时间将设置为0.(我知道,因为当将layer.speed设置为0时,我会立即获取图层的时间并记录它)
layer.timeOffset = pausedTime; 将pauseTime添加到图层的时间(假设layer.timeOffset为0),现在图层的时间为pausedTime.
- (void)pauseLayer:(CALayer *)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; // pauseTime is the time with respect to layer's time space
layer.speed = 0.0; // layer's local time is 0
layer.timeOffset = pausedTime; // layer's local time is pausedTime, so animation stop here
}
Run Code Online (Sandbox Code Playgroud)
然后我将使用- (void)resumeLayer:(CALayer*)layer方法恢复动画.
-(void)resumeLayer:(CALayer*)layer {
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
Run Code Online (Sandbox Code Playgroud)
如果我在8727 + 1处停止动画(意味着动画动画为1秒),在pauseLayer方法中,layer.speed = 0将图层的时间设置为0并layer.timeOffset = pausedTime;在图层的时间添加pausedTime,因此图层的时间为暂停时间.
等一下,我们现在有一个摘要.layer.speed是0.0,'layer.timeOffset'等于pausedTime8727 + 1,图层的时间也是pausedTime.请记住,我们会尽快使用它们.
让我们继续,我用resumeLayer方法恢复8727 + 11的动画,layer.speed = 1.0;它会在图层的时间上加8727 + 11,所以图层的时间是8727 + 1 + 8727 + 11,layer.timeOffset = 0.0;因为layer.timeOffset是8727 +1之前,图层的本地时间现在是8727 + 11.timeSincePause是(8727 + 11-8727-1)= 10.
layer.beginTime = timeSincePause; 它导致图层的时间减去10.现在图层的本地时间是8727 + 1,这是我暂停动画的时间.
我将向您展示代码和日志:
- (void)pauseLayer:(CALayer *)layer
{
NSLog(@"%f", CACurrentMediaTime()) ;
NSLog(@"pauseLayer begin:%f", [t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil] ;
layer.speed = 0.0 ;
NSLog(@"pauseLayer after set speed to 0:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
layer.timeOffset = pausedTime ;
NSLog(@"pauseLayer after set timeOffset:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
}
- (void)resumeLayer:(CALayer *)layer
{
NSLog(@"%f", CACurrentMediaTime()) ;
NSLog(@"resumeLayer begin:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
CFTimeInterval pausedTime = layer.timeOffset ;
layer.speed = 1.0 ;
NSLog(@"resumeLayer after set speed to 1:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
layer.timeOffset = 0.0;
NSLog(@"resumeLayer after set timeOffset to 0:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
layer.beginTime = 0.0 ;
NSLog(@"resumeLayer after set beginTime to 0:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime ;
layer.beginTime = timeSincePause ;
NSLog(@"resumeLayer after set beginTime to timeSincePause:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;
}
Run Code Online (Sandbox Code Playgroud)
日志:
2014-01-15 13:14:34.157 newUserInterface[1762:70b] 15247.550325
2014-01-15 13:14:34.158 newUserInterface[1762:70b] pauseLayer begin:15247.550826
2014-01-15 13:14:34.158 newUserInterface[1762:70b] pauseLayer after set speed to 0:0.000000
2014-01-15 13:14:34.159 newUserInterface[1762:70b] pauseLayer after set timeOffset:15247.551284
2014-01-15 13:14:40.557 newUserInterface[1762:70b] 15253.950505
2014-01-15 13:14:40.558 newUserInterface[1762:70b] resumeLayer begin:15247.551284
2014-01-15 13:14:40.558 newUserInterface[1762:70b] resumeLayer after set speed to 1:30501.502810
2014-01-15 13:14:40.559 newUserInterface[1762:70b] resumeLayer after set timeOffset to 0:15253.952031
2014-01-15 13:14:40.559 newUserInterface[1762:70b] resumeLayer after set beginTime to 0:15253.952523
2014-01-15 13:14:40.560 newUserInterface[1762:70b] resumeLayer after set beginTime to timeSincePause:15247.551294
Run Code Online (Sandbox Code Playgroud)
另一个问题是resumeLayer方法:为什么不将两个赋值行合并为一个layer.beginTime = timeSincePause;,原因在于[layer convertTime:CACurrentMediaTime() fromLayer:nil],结果值与layer.beginTime有关.
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
Run Code Online (Sandbox Code Playgroud)
说实话,我仍然不知道动画是如何工作的,我正在做的是分析结果,这不是一个好的解决方案.我很高兴任何有这方面想法的人都可以分享.谢谢!
Jef*_*.Lu 10
在CAMediaTiming的头文件中,我们可以看到这些代码:
/* The begin time of the object, in relation to its parent object, if
* applicable. Defaults to 0. */
@property CFTimeInterval beginTime;
/* The basic duration of the object. Defaults to 0. */
@property CFTimeInterval duration;
/* The rate of the layer. Used to scale parent time to local time, e.g.
* if rate is 2, local time progresses twice as fast as parent time.
* Defaults to 1. */
@property float speed;
/* Additional offset in active local time. i.e. to convert from parent
* time tp to active local time t: t = (tp - begin) * speed + offset.
* One use of this is to "pause" a layer by setting `speed' to zero and
* `offset' to a suitable value. Defaults to 0. */
@property CFTimeInterval timeOffset;
Run Code Online (Sandbox Code Playgroud)
公式有多重要:
t =(tp - 开始)*速度+偏移量
此公式定义全局时间(或父时间,tp)如何映射到图层的本地时间.这个公式可以解释列出的代码的所有内容:
| 归档时间: |
|
| 查看次数: |
4387 次 |
| 最近记录: |