gpt4 book ai didi

iphone - 动画 CAShapeLayer 饼图

转载 作者:可可西里 更新时间:2023-11-01 03:22:26 25 4
gpt4 key购买 nike

我正在尝试使用 CAShapeLayer 创建一个简单的动画饼图。我希望它从 0 到提供的百分比进行动画处理。

要创建我使用的形状图层:

CGMutablePathRef piePath = CGPathCreateMutable();
CGPathMoveToPoint(piePath, NULL, self.frame.size.width/2, self.frame.size.height/2);
CGPathAddLineToPoint(piePath, NULL, self.frame.size.width/2, 0);
CGPathAddArc(piePath, NULL, self.frame.size.width/2, self.frame.size.height/2, radius, DEGREES_TO_RADIANS(-90), DEGREES_TO_RADIANS(-90), 0);
CGPathAddLineToPoint(piePath, NULL, self.frame.size.width/2 + radius * cos(DEGREES_TO_RADIANS(-90)), self.frame.size.height/2 + radius * sin(DEGREES_TO_RADIANS(-90)));

pie = [CAShapeLayer layer];
pie.fillColor = [UIColor redColor].CGColor;
pie.path = piePath;

[self.layer addSublayer:pie];

然后我使用动画:

CGMutablePathRef newPiePath = CGPathCreateMutable();
CGPathAddLineToPoint(newPiePath, NULL, self.frame.size.width/2, 0);
CGPathMoveToPoint(newPiePath, NULL, self.frame.size.width/2, self.frame.size.height/2);
CGPathAddArc(newPiePath, NULL, self.frame.size.width/2, self.frame.size.height/2, radius, DEGREES_TO_RADIANS(-90), DEGREES_TO_RADIANS(125), 0);
CGPathAddLineToPoint(newPiePath, NULL, self.frame.size.width/2 + radius * cos(DEGREES_TO_RADIANS(125)), self.frame.size.height/2 + radius * sin(DEGREES_TO_RADIANS(125)));

CABasicAnimation *pieAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
pieAnimation.duration = 1.0;
pieAnimation.removedOnCompletion = NO;
pieAnimation.fillMode = kCAFillModeForwards;
pieAnimation.fromValue = pie.path;
pieAnimation.toValue = newPiePath;

[pie addAnimation:pieAnimation forKey:@"animatePath"];

显然,这是一种非常奇怪的动画方式。形状有点长成它的最终状态。有没有一种简单的方法可以让这个动画跟随圆圈的方向?或者这是 CAShapeLayer 动画的限制?

最佳答案

我知道这个问题早就有人回答了,但我不太认为这对 CAShapeLayerCAKeyframeAnimation 来说是个好案例。 Core Animation 有能力为我们做补间动画。这是我用来很好地实现效果的类(带有包装 UIView,如果您愿意的话)。

图层子类为进度属性启用隐式动画,但 View 类将其 setter 包装在 UIView 动画方法中。将 0.0 长度的动画与 UIViewAnimationOptionBeginFromCurrentState 一起使用的有趣(且最终有用)的副作用是每个动画都会抵消前一个动画,从而导致平滑、快速、高帧率的饼图,如 this (动画)和 this (不是动画,而是递增的)。

DZRoundProgressView.h

@interface DZRoundProgressLayer : CALayer

@property (nonatomic) CGFloat progress;

@end

@interface DZRoundProgressView : UIView

@property (nonatomic) CGFloat progress;

@end

DZRoundProgressView.m

#import "DZRoundProgressView.h"
#import <QuartzCore/QuartzCore.h>

@implementation DZRoundProgressLayer

// Using Core Animation's generated properties allows
// it to do tweening for us.
@dynamic progress;

// This is the core of what does animation for us. It
// tells CoreAnimation that it needs to redisplay on
// each new value of progress, including tweened ones.
+ (BOOL)needsDisplayForKey:(NSString *)key {
return [key isEqualToString:@"progress"] || [super needsDisplayForKey:key];
}

// This is the other crucial half to tweening.
// The animation we return is compatible with that
// used by UIView, but it also enables implicit
// filling-up-the-pie animations.
- (id)actionForKey:(NSString *) aKey {
if ([aKey isEqualToString:@"progress"]) {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:aKey];
animation.fromValue = [self.presentationLayer valueForKey:aKey];
return animation;
}
return [super actionForKey:aKey];
}

// This is the gold; the drawing of the pie itself.
// In this code, it draws in a "HUD"-y style, using
// the same color to fill as the border.
- (void)drawInContext:(CGContextRef)context {
CGRect circleRect = CGRectInset(self.bounds, 1, 1);

CGColorRef borderColor = [[UIColor whiteColor] CGColor];
CGColorRef backgroundColor = [[UIColor colorWithWhite: 1.0 alpha: 0.15] CGColor];

CGContextSetFillColorWithColor(context, backgroundColor);
CGContextSetStrokeColorWithColor(context, borderColor);
CGContextSetLineWidth(context, 2.0f);

CGContextFillEllipseInRect(context, circleRect);
CGContextStrokeEllipseInRect(context, circleRect);

CGFloat radius = MIN(CGRectGetMidX(circleRect), CGRectGetMidY(circleRect));
CGPoint center = CGPointMake(radius, CGRectGetMidY(circleRect));
CGFloat startAngle = -M_PI / 2;
CGFloat endAngle = self.progress * 2 * M_PI + startAngle;
CGContextSetFillColorWithColor(context, borderColor);
CGContextMoveToPoint(context, center.x, center.y);
CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0);
CGContextClosePath(context);
CGContextFillPath(context);

[super drawInContext:context];
}

@end

@implementation DZRoundProgressView
+ (Class)layerClass {
return [DZRoundProgressLayer class];
}

- (id)init {
return [self initWithFrame:CGRectMake(0.0f, 0.0f, 37.0f, 37.0f)];
}

- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
self.opaque = NO;
self.layer.contentsScale = [[UIScreen mainScreen] scale];
[self.layer setNeedsDisplay];
}
return self;
}

- (void)setProgress:(CGFloat)progress {
[(id)self.layer setProgress:progress];
}

- (CGFloat)progress {
return [(id)self.layer progress];
}

@end

关于iphone - 动画 CAShapeLayer 饼图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8197239/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com