CoreGraphics Circle动画错误的持续时间

时间:2017-06-30 18:12:23

标签: ios animation core-graphics duration

编辑:我认为最好将代码转换为CoreAnimation。如何将此代码转换为该方法?我认为问题在于设备FPS存在差异。

我一直在搜索iOS的自定义进度圈,并且遇到了这个库:https://github.com/Eclair/CircleProgressBar

但是我注意到,每当动画大约5秒钟时就会出现错误。圆的动画比它应该慢。例如:我在30秒内将圆圈设置为100%完成动画,但在该时间段内仅达到78%(在NSTimer为30秒后,“完成”标签可见)。看看这张图片我参加了一个我制作的演示项目: enter image description here

这是制作圈子的代码:

- (void)drawProgressBar:(CGContextRef)context progressAngle:(CGFloat)progressAngle center:(CGPoint)center radius:(CGFloat)radius {
    CGFloat barWidth = self.progressBarWidthForDrawing;
    if (barWidth > radius) {
        barWidth = radius;
    }

    CGContextSetFillColorWithColor(context, self.progressBarProgressColorForDrawing.CGColor);
    CGContextBeginPath(context);
    CGContextAddArc(context, center.x, center.y, radius, DEGREES_TO_RADIANS(_startAngle), DEGREES_TO_RADIANS(progressAngle), 0);
    CGContextAddArc(context, center.x, center.y, radius - barWidth, DEGREES_TO_RADIANS(progressAngle), DEGREES_TO_RADIANS(_startAngle), 1);
    CGContextClosePath(context);
    CGContextFillPath(context);

    CGContextSetFillColorWithColor(context, self.progressBarTrackColorForDrawing.CGColor);
    CGContextBeginPath(context);
    CGContextAddArc(context, center.x, center.y, radius, DEGREES_TO_RADIANS(progressAngle), DEGREES_TO_RADIANS(_startAngle + 360), 0);
    CGContextAddArc(context, center.x, center.y, radius - barWidth, DEGREES_TO_RADIANS(_startAngle + 360), DEGREES_TO_RADIANS(progressAngle), 1);
    CGContextClosePath(context);
    CGContextFillPath(context);
}

这是为圆圈设置动画的代码:

- (void)animateProgressBarChangeFrom:(CGFloat)startProgress to:(CGFloat)endProgress duration:(CGFloat)duration {
    _currentAnimationProgress = _startProgress = startProgress;
    _endProgress = endProgress;

    _animationProgressStep = (_endProgress - _startProgress) * AnimationChangeTimeStep / duration;

    _animationTimer = [NSTimer scheduledTimerWithTimeInterval:AnimationChangeTimeStep target:self selector:@selector(updateProgressBarForAnimation) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_animationTimer forMode:NSRunLoopCommonModes];
}

- (void)updateProgressBarForAnimation {
    _currentAnimationProgress += _animationProgressStep;
    _progress = _currentAnimationProgress;
    if ((_animationProgressStep > 0 && _currentAnimationProgress >= _endProgress) || (_animationProgressStep < 0 && _currentAnimationProgress <= _endProgress)) {
        [_animationTimer invalidate];
        _animationTimer = nil;
        _progress = _endProgress;
    }
    [self setNeedsDisplay];
}

这里有什么东西看起来不对吗?有没有更好的方法来制作圈子?理想情况下,我希望它以正确的持续时间制作动画,而我对如何解决这个问题并不熟悉。

演示项目以展示问题: https://ufile.io/8pkt5

1 个答案:

答案 0 :(得分:1)

基本上drawRect方法适用于主线程,因为你使用的AnimationChangeTimeStep太小了:

const CGFloat AnimationChangeTimeStep = 0.01f;

它是每秒100帧,这太多了,drawRect会阻塞附加到该线程的主线程和动画计时器,因此重复的动画计时器不会立即触发,而是在所有当前drawRect调用完成后触发。 所以要解决你的问题,只需减少AnimationChangeTimeStep并使其等于帧速率30 fps:

const CGFloat AnimationChangeTimeStep = 1/30.0f;