ios - CAShapeLayer渲染问题

标签 ios objective-c cashapelayer

我正在尝试通过添加具有不同笔触颜色的CAShapeLayer来创建圆形动画:

    UIView *view = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
    [self.view addSubview:view];
    view.backgroundColor = [UIColor redColor];
    [self addCircleAnimationTo:view direction:YES];

- (void)addCircleAnimationTo:(UIView *)view direction:(BOOL)direction {
    CGFloat animationTime = 3;

    // Set up the shape of the circle
    int radius = view.frame.size.width/2;
    CAShapeLayer *circle = [CAShapeLayer layer];

    // Make a circular shape
    circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius)
                                             cornerRadius:radius].CGPath;

    // Center the shape in view
    circle.position = CGPointMake(radius,
                                  radius);

    circle.bounds = view.bounds;
    // Configure the apperence of the circle
    circle.fillColor = [UIColor clearColor].CGColor;

    // switch color
    circle.strokeColor = (direction) ? [UIColor blueColor].CGColor : [UIColor whiteColor].CGColor;
    circle.lineWidth = 5;
    circle.lineJoin = kCALineJoinBevel;
    circle.strokeStart = .0;
    circle.strokeEnd = 1.;

    // Configure animation
    CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    drawAnimation.duration            = animationTime;
    drawAnimation.repeatCount         = 1;

    // 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.];

    // Experiment with timing to get the appearence to look the way you want
    drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

    // Add to parent layer
    [view.layer addSublayer:circle];
    // Add the animation to the circle
    [circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((animationTime-0.1) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self addCircleAnimationTo:view direction:!direction];
    });
}

enter image description here

我想知道为什么在设置白色动画时为什么能看到蓝色,以及如何摆脱这种奇怪的蓝色边框:

enter image description here

最佳答案

抗锯齿是导致问题的原因

当白色CAShapeLayer在蓝色上绘制时,边缘将与抗锯齿创建的先前边缘融合在一起。

唯一真正的解决方案是在设置动画时从白色下面清除蓝色。 可以通过使上一层从strokeStart0.0的上一层的1.0属性动画来实现。通过更改drawAnimation,您应该能够为此重新使用keyPath。例如,将dispatch_after更改为:

- (void)addCircleAnimationTo:(UIView *)view direction:(BOOL)direction {

    // Insert your previous animation code, where drawAnimation is defined and added to the circle layer.    


    drawAnimation.keyPath = @"strokeStart"; // Re-use the draw animation object, setting it to animate strokeStart now.

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((animationTime-0.1) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self addCircleAnimationTo:view direction:!direction];
        [circle addAnimation:drawAnimation forKey:@"(un)drawCircleAnimation"]; // Sets the previous layer to animate out
    });

}

这样,可以从蓝色层清除抗锯齿边缘融合,使白色层获得漂亮而干净的抗锯齿。 动画制作完成后,别忘了删除图层!

另一个可能的解决方案是增加白色层的笔触宽度,以便在蓝色层的边缘融合上笔触,但是我想这会产生不希望的效果。您也可以禁用抗锯齿功能,但这在圈子中看起来会很可怕。

关于ios - CAShapeLayer渲染问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34943808/

相关文章:

iphone - iOS iPhone 5 选择正确的 Storyboard

ios - 如果响应返回 200 以外的状态代码,是否停止我的 NSURLSession?在环球银行金融电信协会

iphone - 在 iOS 中以编程方式进行自动调用

iphone - 在CAShapelayer中获取接触点

ios - 为什么在 Xamarin IOS customrenderer 中没有准确检测到长按开始/结束?

IOS 自定义键盘。如何在自定义键盘中设置特殊字符

objective-c - 快速滚动时未调用 UIScrollView scrollViewDidEndDragging

ios 取消注册观察者

ios - 无法删除 CAShapeLayer

ios - 如何在中心点旋转 CAShapeLayer