iOS "erase"使用 CAShapeLayer 动画绘图

标签 ios animation drawing cashapelayer

我正在尝试实现一个圆形指示器,它会在值发生变化时用动画绘制自己。

我使用 CAShapeLayer 来绘制动画。到目前为止,我每次都让它从头开始绘制,它按预期工作。现在我想让它更圆滑,并根据新值是大于还是小于以前的值来向前绘制和“删除”。我不确定如何实现删除部分。有一个背景,所以我不能只在上面画白色。这是一张图片,可以更好地理解它的外观。

Circular indicator

关于如何实现删除部分的任何想法? SO 上有一些针对类似问题的解决方案,但这些解决方案不涉及动画。

我用这段代码来画:

- (void)drawCircleAnimatedWithStartAngle:(CGFloat)startAngle
                            endAngle:(CGFloat)endAngle
                               color:(UIColor *)color
                              radius:(int)radius
                           lineWidth:(int)lineWidth {


CAShapeLayer *circle = [CAShapeLayer layer];
circle.name = @"circleLayer";

    circle.path = ([UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius-1 startAngle:startAngle endAngle:endAngle clockwise:YES].CGPath);

// Configure the apperence of the circle
circle.fillColor = [UIColor clearColor].CGColor;
circle.strokeColor = [UIColor colorWithRed:19.0/255 green:167.0/255 blue:191.0/255 alpha:1].CGColor;
circle.lineWidth = lineWidth;

// Add to parent layer
for (CALayer *layer in self.circleView.layer.sublayers) {
    if ([layer.name isEqualToString:@"circleLayer"]) {
        [layer removeFromSuperlayer];
        break;
    }
}

[self.circleView.layer addSublayer:circle];
circle.zPosition = 1;


// Configure animation
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
drawAnimation.duration            = 0.5; 
drawAnimation.repeatCount         = 1.0;  // Animate only once..

// Animate from no part of the stroke being drawn to the entire stroke being drawn
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawAnimation.toValue   = [NSNumber numberWithFloat:1.0f];

drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

// Add the animation to the circle
[circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];

}

最佳答案

我能够以与您正在做的略有不同的方式来做到这一点。我没有绘制一定长度的弧线,而是将我的路径设为一个完整的圆圈,但只在其中部分设置动画。您会注意到我使用表示层的 strokeEnd 来获取 toValue,这样如果您需要更改最终 strokeEnd 的值时动画正在进行中,它将从当前绘制路径的位置开始。这是我的 View Controller 中的代码;轮廓层绘制灰色圆圈,类似于图像中的圆圈。我在我的 View 中添加了 5 个按钮(用于测试),它们的标签用于更改动画的最终行程值,

@implementation ViewController {
    UIView *circleView;
    RDShapeLayer *circle;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    circleView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
    CALayer *outlineLayer = [CALayer new];
    outlineLayer.frame = circleView.bounds;
    outlineLayer.borderWidth = 2;
    outlineLayer.borderColor = [UIColor lightGrayColor].CGColor;
    outlineLayer.cornerRadius = circleView.frame.size.width/2.0;
    [circleView.layer addSublayer:outlineLayer];
    [self.view addSubview:circleView];

    circle = [[RDShapeLayer alloc] initWithFrame:circleView.bounds color:[UIColor blueColor].CGColor lineWidth:4];
    [circleView.layer addSublayer:circle];
}


-(void)animateToPercentWayAround:(CGFloat) percent {

    circle.strokeEnd = percent/100.0;
    CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    drawAnimation.duration = 1.0;
    drawAnimation.fromValue = @([circle.presentationLayer strokeEnd]);
    drawAnimation.toValue   = @(percent/100.0);

    drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];
}


- (IBAction)changeStroke:(UIButton *)sender {
    [self animateToPercentWayAround:sender.tag];
}

这是子类 CAShapeLayer 的代码,

-(instancetype)initWithFrame:(CGRect) frame color:(CGColorRef) color lineWidth:(CGFloat) lineWidth {
    if (self = [super init]) {

        self.path = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(frame, 1, 1)].CGPath;
        self.fillColor = [UIColor clearColor].CGColor;
        self.strokeColor = color;
        self.lineWidth = lineWidth;
        self.strokeStart = 0;
        self.strokeEnd = 0;
    }
    return self;
}

关于iOS "erase"使用 CAShapeLayer 动画绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26762228/

相关文章:

android - Canvas.clipPath(Path) 未按预期剪切

ios - objective-C 。多个匿名类别?

ios - 错误_BSMachError : (os/kern) invalid capability (20) after receiving remote notification on CloudKit record addition

ios - 弹出 View Controller 显示为拉伸(stretch)且未调整大小

ios - 如何检查我的代码是否侵犯版权

animation - QML 定时器与转换相结合

ios - 为什么我的 Core Graphics 绘图代码运行缓慢?

android 矢量可绘制动画不起作用

ios - 在自定义动画过渡期间淡入背景 View

ios - Swift - 通过定义的点/区域检测用户绘图。