可以在两个方向上制作动画的动画饼图 [英] Animated pie chart that can animate in both directions

查看:135
本文介绍了可以在两个方向上制作动画的动画饼图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个动画饼图,可以根据其 progress 的值是增加还是减少,在两个方向上为饼图设置动画。我开始使用此处提供的示例代码,并根据建议进行了一些调整这里

I am trying to build an animated pie chart that can animate the pie in both directions depending on whether the value of its progress increases or decreases. I've started with sample code provided here and made some adjustments as suggested here.

麻烦的是背景动画还没有完全奏效。它只是部分清除馅饼。我不太确定这是因为我错误地使用动画还是错误地计算坐标,因为如果我将 CGContextSetFillColorWithColor(context,UIColor.redColor.CGColor); 插入第一个如果分支并将混合模式更改为 kCGBlendModeNormal ,结果也同样关闭。

The trouble is that the back-animation is not yet quite working. It only partially clears the pie. I am not quite sure whether this is due to me using animations incorrectly or calculating coordinates incorrectly, for if I insert CGContextSetFillColorWithColor(context, UIColor.redColor.CGColor); into the first if branch and change blend mode to kCGBlendModeNormal also there the result is similarly off.

所以这是我当前的代码(摘自 PieLayer.m ) - 谁能提出改进建议?

So here is my current code (excerpt from PieLayer.m) -- who can suggest improvements?

- (void)drawInContext:(CGContextRef)context {
    PieView *pieView = self.delegate;
    NSAssert(pieView != nil, nil);

    CGRect rect = CGRectInset(self.bounds, 1, 1);

    CGFloat radius = MIN(CGRectGetMidX(rect), CGRectGetMidY(rect));
    CGPoint center = CGPointMake(radius, CGRectGetMidY(rect));

    CGContextSetFillColorWithColor(context, UIColor.clearColor.CGColor);
    CGContextSetStrokeColorWithColor(context, pieView.circumferenceTintColor.CGColor);
    CGContextSetLineWidth(context, 2.0f);

    CGContextFillEllipseInRect(context, rect);
    CGContextStrokeEllipseInRect(context, rect);

    CGFloat startAngle   = -M_PI / 2;
    CGFloat endAngle     = self.progress     * 2 * M_PI + startAngle;
    CGFloat lastEndAngle = self.lastProgress * 2 * M_PI + startAngle;

    if (self.lastProgress > self.progress) {
        NSLog(@"clear sector between progress=%f and lastProgress=%f", self.progress, self.lastProgress);

        CGContextMoveToPoint(context, center.x, center.y);
        CGContextAddArc(context, center.x, center.y, radius, endAngle, lastEndAngle, 0);
        CGContextClosePath(context);

        CGContextSetBlendMode(context, kCGBlendModeClear);
        CGContextFillPath(context);
    }

    if (self.progress > 0) {
        NSLog(@"draw sector to progress=%f (lastProgress=%f)", self.progress, self.lastProgress);

        CGContextSetFillColorWithColor(context, pieView.sectorTintColor.CGColor);

        CGContextMoveToPoint(context, center.x, center.y);
        CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0);
        CGContextClosePath(context);

        CGContextSetBlendMode(context, kCGBlendModeNormal);
        CGContextFillPath(context);
    }

    ((PieLayer *)self.modelLayer).lastProgress = self.progress;

    [super drawInContext:context];
}


推荐答案

答案中的代码发布(动画CAShapeLayer馅饼)对我来说两个方向都很好,即使使用 clearColor :请参阅此视频 。$
clearColor 唯一不会产生正确行为的情况是当背景颜色是实色且前景清晰时:在这种情况下a正如您在代码中指出的那样,需要更改混合模式。

The code in the answer you posted (animated CAShapeLayer pie) works fine in both directions for me, even using clearColor: see this video.
The only situation in which clearColor does not produce a correct behavior is when the background color is solid and the foreground is clear: in that case a change in the blending mode is required, as you pointed out in your code.

我尝试了这三种配置,并且在所有情况下,图层都正确响应 -setProgress:

I tried with these three configuration, and in all the cases the layer was responding correctly to -setProgress:.


  • DZRoundProgressView 作为主 UIView的子视图;

  • 设置为 DZRoundProgressVie的主视图类w ;

  • DZRoundProgressView 作为主 UIView ;

  • DZRoundProgressView as subview of the main UIView;
  • Class of main view set to DZRoundProgressView;
  • DZRoundProgressView as sublayer of the main UIView;

此外,在下一次抽奖调用中,前一帧中图层的内容不太可见:显然, -drawInContext:的默认行为是在执行前清除上下文,如这个问题说。

如果您不使用图层的内容属性,并且您没有破解图纸管道,那么 self.progress 的值可能有问题;也许是表示层和模型层的一些问题,或者属性的实现。

Moreover, it is unlikely that the content of a layer in the previous frame is still visible at the next draw call: apparently, the default behavior of -drawInContext: is to clear the context before execution, as this question says.
If you are not working with the contents property of the layer, and you are not hacking the drawing pipe, then there could be something wrong with the value of self.progress; perhaps some issue with presentation layer and model layer, or in the implementation of the property.

确实这不能解决你的问题,因为我无法重现它或隔离它,但应该让你解决它。

Indeed this doesn't solve your problem, since I couldn't reproduce it or isolate it, but should allow you to work around it.

这篇关于可以在两个方向上制作动画的动画饼图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆