繁体   English   中英

如何更改CALayer动画的方向

[英]How to change direction of CALayer animation

如何更改CALayer动画的方向和起始位置?

例如,如果我使用以下代码制作圆形动画:

-(void)drawCircle {
    CAShapeLayer *circleShapeLayer = [[CAShapeLayer alloc] init];
    circleShapeLayer.path          = [self circleBezierPath].CGPath;
    circleShapeLayer.strokeColor   = [UIColor lightGrayColor].CGColor;
    circleShapeLayer.fillColor     = [UIColor clearColor].CGColor;
    circleShapeLayer.lineWidth     = 2;
    [self.view.layer addSublayer:circleShapeLayer];

    CABasicAnimation *circleShapeAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    circleShapeAnimation.timingFunction    = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    circleShapeAnimation.duration          = 1.0f;
    circleShapeAnimation.fromValue         = @(0.0f);
    circleShapeAnimation.toValue           = @(1.0f);
    [circleShapeLayer addAnimation:circleShapeAnimation forKey:@"strokeEnd"];
}

-(UIBezierPath *)circleBezierPath {
    UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 100, 100, 100)];
    return circlePath;
}

动画总是从3点开始,并沿顺时针方向进行动画处理。

如何强制它从12点(或其他任何位置)开始并沿逆时针方向进行动画处理?

怎么了

当您在矩形中创建椭圆(使用CGPath函数的UIBezierPath一起)时,它将创建一个适合指定矩形的椭圆或椭圆。 这意味着椭圆形的中心与矩形的原点不同:

矩形中的椭圆形

动画始终从3点开始,并逆时针旋转,因为在默认坐标系中,这是从0到2π的圆的圆弧路径:

默认坐标系中的角度

这意味着您正在为笔画设置动画的路径如下所示:

在此处输入图片说明

解决问题的错误方法

查看路径,您可以通过旋转视图来移动起点。 不建议这样做,因为它有副作用。 如果有任何子层,这些子层也将被旋转。 可以通过翻转视图(沿一个轴缩放为负数)或通过将笔划的起点从1动画化为0而不是动画的终点来改变笔划方向。

所有这些解决方案都可以使用,但是有副作用,并且不清楚哪种方法更可取。

更好的解决方案

我喜欢看这样的问题:动画代码做正确的事,使笔触从无到有动画化,但是路径的起点和笔触方向并不是所期望的。 这意味着“问题”在于道路。

代替使用bezierPathWithOvalInRect:您可以使用圆弧创建自己的完整圆,该圆弧可以沿顺时针方向或逆时针方向从任意起始角度到任意终止角度。 所需要做的就是计算圆心(以及起始和终止角度)。 查看默认坐标系,我们可以看到起始角度为3π/ 2或-π/ 2。 然后,终止角度为起始角度的正负2π(取决于它是顺时针还是逆时针)。

创建这样的弧可能看起来像这样:

- (UIBezierPath *)circleBezierPath
{
    CGRect boundingRect = CGRectMake(100, 100, 100, 100);
    CGPoint center      = CGPointMake(CGRectGetMidX(boundingRect), CGRectGetMidY(boundingRect));
    CGFloat radius      = MIN(CGRectGetWidth(boundingRect), CGRectGetHeight(boundingRect));

    CGFloat twelveOClockAngle = -M_PI_2;
    BOOL clockwise = NO; // NO for counter clockwise

    CGFloat startAngle = twelveOClockAngle;
    CGFloat endAngle = startAngle + (2.0*M_PI * (clockwise ? 1.0 : -1.0));

    return [UIBezierPath bezierPathWithArcCenter:center
                                          radius:radius
                                      startAngle:startAngle
                                        endAngle:endAngle
                                       clockwise:clockwise];
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM