ios - 如何改变CALayer动画的方向

标签 ios objective-c iphone animation core

如何改变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),它会创建适合指定矩形的椭圆或椭圆。这意味着椭圆的中心与矩形的原点不同:

An oval in a rectangle

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

Angles in the default coordinate system

这意味着您为笔画设置动画的路径看起来像这样:

enter image description here

解决问题的错误方法

查看路径,您可以通过旋转 View 来移动起点。不建议这样做,因为它有副作用。如果有任何子层,它们也会被旋转。可以通过翻转 View (沿一个轴缩放负数)或通过将笔画的起点从 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];
}

关于ios - 如何改变CALayer动画的方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29054725/

相关文章:

iphone - indexOfObject第一次返回0而不是NSNotFound

ios - prepareForSegue 函数不起作用

java - 跨平台实时数据

iphone - 在 Objective-C XCode 中将常量链接到 pch 时出错

objective-c - 将 UITable 中的 UITableViewCell 中的 subview 中的对象的 CGRect 转换为相对于 self.view 的 CGRect

objective-c - Mac 操作系统 : Injecting item to Finder's Context Menu

ios - 如何更改 Uipickerview 的位置?

ios - 如何使用 ImageSlideshow 和标签

iphone - self.view = someController.view 与 [self.view addSubview :someController. view]

ios - UITextView 中的纯文本