可以在两个方向上制作动画的动画饼图 [英] Animated pie chart that can animate in both directions
问题描述
我正在尝试构建一个动画饼图,可以根据其 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 $ c的子图层$ c>;
DZRoundProgressView
as subview of the mainUIView
;- Class of main view set to
DZRoundProgressView
; DZRoundProgressView
as sublayer of the mainUIView
;
此外,在下一次抽奖调用中,前一帧中图层的内容不太可见:显然, -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屋!