我正在尝试构建一个动画饼图,可以根据其progress
的值是否增加或减少在两个方向上动画饼。我从这里提供的示例代码开始,并根据这里的建议进行了一些调整。
问题是,反向动画还没有完全工作。它只能部分清理掉馅饼。我不太确定这是否是由于我不正确地使用动画或计算坐标不正确,因为如果我将CGContextSetFillColorWithColor(context, UIColor.redColor.CGColor);
插入第一个if
分支并将混合模式更改为kCGBlendModeNormal
,结果也同样关闭。
这是我当前的代码(摘自PieLayer.m
)——谁能提出改进建议?
- (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
不产生正确行为的唯一情况是当背景颜色是纯色而前景是清晰的:在这种情况下,需要更改混合模式,正如您在代码中指出的那样。
我尝试了这三种配置,在所有情况下,层都正确响应-setProgress:
。
-
DZRoundProgressView
作为主UIView
的子视图; - 主视图类设置为
DZRoundProgressView
; -
DZRoundProgressView
作为主UIView
的子层;
此外,在下一个绘制调用中,前一帧中的层的内容不太可能仍然可见:显然,-drawInContext:
的默认行为是在执行之前清除上下文,正如这个问题所说的。
如果你没有使用层的contents
属性,并且你没有破解绘图管道,那么self.progress
的值可能有问题;可能是表示层和模型层的问题,或者是属性的实现问题。
事实上,这并不能解决你的问题,因为我无法复制它或隔离它,但应该允许你绕过它。