问题:
如果您查看我当前的代码,如果targetSeconds
高于~2-3秒,您会看到它正常工作。
但是,如果targetSeconds
为0.005秒,它将无效,因为它无法在0.005秒内完成100次方法调用。因此,有没有人对我能做些什么改进呢?我宁愿不包括第三方GitHub存储库。
当前代码:
// Target seconds means the seconds that it'll take to become 100.0f.
- (void)startAnimatingWithTargetSeconds:(NSTimeInterval)targetSeconds{
// Try to set timeInterval to 0.005f and you'll see that it won't finish in 0.005f
[NSTimer scheduledTimerWithTimeInterval:targetSeconds / 100.0f target:self selector:@selector(animateWithTimer:) userInfo:nil repeats:YES];
}
- (void)animateWithTimer:(NSTimer *)timer {
BOOL isFinished = self.currentProgress >= 100;
if (isFinished) {
// Invalidate timer
if (timer.isValid) {
[timer invalidate];
}
// Reset currentProgress
self.currentProgress = 0.0f;
}else{
if (timer.isValid) {
self.currentProgress += 1;
}
}
}
// Overriden setter
- (void)setCurrentProgress:(CGFloat)currentProgress {
if (_currentProgress == currentProgress) {
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
_currentProgress = currentProgress;
[self setNeedsDisplay];
});
}
然后在drawRect
中,我有UIBezierPath
基本上根据self.currentProgress
绘制圆圈。
这样的事情:CGFloat endAngle = (self.currentProgress / 100.0f) * 2 * M_PI + startAngle;
问题:
在我的情况下,是否有任何公式或任何可以帮助我的方法?因为如果我将self.currentProgress
设置为self.currentProgress += 5;
而不是1
,那么它的动画效果会更快,这正是我正在寻找的。 p>
答案 0 :(得分:1)
首先,你想什么时候每隔0.005秒重绘一次?那个200 FPS,比你需要的还要多。
不要重新发明轮子 - 利用核心动画! Core Animation已经知道如何以适当的速率调用状态更改函数,以及如何根据需要重绘视图,假设您告诉它该做什么。这个策略的要点如下:
actionForKey:
或将动画设置为actions
字典(或更多选项,详细here)来动画此属性。needsDisplayForKey:
重新绘制图层。display
方法,根据动态属性的表示层值重绘饼图。 完成!现在,您可以将动态属性从任何值设置为任何其他值,就像您的不透明度,位置等一样.Core Animation负责时间和回调,并且您可以获得平滑的60 FPS。
对于某些示例,请参阅以下资源,按有用性降低的顺序列出(在我看来):
答案 1 :(得分:0)
我更喜欢使用这样的东西,因为小间隔的计时器(和睡眠)工作非常不准确:
-(void)startAnimatingWithTargetSeconds:(NSTimeInterval)targetSeconds
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
float fps = 60;
float currentState = 0;
float frameStateChange = fps/targetSeconds;
NSDate *nextFrameDate = [NSDate date];
while (currentState < 1) {
currentState += frameStateChange;
self.currentProgress = roundf(currentState * 100.);
nextFrameDate = [nextFrameDate dateByAddingTimeInterval:1./fps];
while ([nextFrameDate timeIntervalSinceNow] > 0) {
usleep((useconds_t)(100000/fps));
}
}
self.currentProgress = 0;
});
}