【问题标题】:iOS "erase" drawing with CAShapeLayer animatediOS“擦除”绘图与 CAShapeLayer 动画
【发布时间】:2014-11-05 16:30:36
【问题描述】:

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

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

任何想法如何擦除部分可以实现?关于类似问题,这里有一些解决方案,但不涉及动画。

我用这段代码来画:

- (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"];

}

【问题讨论】:

    标签: ios animation drawing cashapelayer


    【解决方案1】:

    我能够以与您正在做的方式略有不同的方式做到这一点。我没有画一条一定长度的弧线,而是把我的路径画了一个完整的圆,但只是动画它的一部分。你会注意到我使用表现层的 strokeEnd 来获取 toValue,这样如果动画正在进行中,当你需要改变最终 strokeEnd 的值时,它会从当前绘制路径的位置开始。这是我的视图控制器中的代码;轮廓层绘制灰色圆圈,类似于您在图像中的内容。我在视图中添加了 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;
    }
    

    【讨论】:

    • 这是一个很棒的解决方案,非常感谢!与表示层的接触非常好!你救了我几个小时的头痛。如此干净且易于实施:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 2011-08-18
    • 1970-01-01
    相关资源
    最近更新 更多