简体   繁体   English

如何制作线迹动画CALayer?

[英]How to make line track animating CALayer?

I have many animating CALayers, and I want to line some pair of them while animating. 我有许多动画CALayers,并且我想在动画时排成一行。

Let's say, there are two animation circle CALayers. 假设有两个动画圈CALayers。 I want to make a line tracking the center of CALayers. 我想用一条线跟踪CALayers的中心。 There are two possible solution came up with me. 我想出了两种可能的解决方案。

1 Whenever what animation add to circle layer, calculate the corresponding animation of the line. 1每当将什么动画添加到圆形图层时,就计算直线的相应动画。

2 Control the whole animation using time calculation, inspired by objc.io . 2使用受objc.io启发的时间计算来控制整个动画。 In each step calculate how the circle move from and move to, as well as the line. 在每个步骤中,计算圆如何移动以及如何移动以及直线。

There is the problem, in solution one, there will be poor code to control too many circle layers, and for different circle animation, there should be different corresponding. 有一个问题,在解决方案一中,将有不良的代码来控制太多的圆圈层,并且对于不同的圆圈动画,应该有不同的对应关系。 If there are many circles and many kinds of animation, thing will be worse, which is my situation exactly. 如果有很多圈子和各种各样的动画,情况将会变得更糟,这正是我的情况。

In solution two, I must drop Core Animation and do it from scratch, it will increase the complexity and it will be hard to make some adjustment in the future. 在解决方案二中,我必须放弃Core Animation并从头开始做,这会增加复杂性,并且将来很难进行调整。

Is there a simpler and more elegant way to do this, maybe some tricks behind core animation. 有没有一种更简单,更优雅的方法来执行此操作,也许是核心动画背后的一些技巧。 Thanks a lot. 非常感谢。

UPDATE: According to what @Duncan C point out, I am trying use 3 layer with same time function. 更新:根据@Duncan C指出的,我正在尝试使用具有相同时间功能的3层。

I created the line animation according to the circles. 我根据圆圈创建了线条动画。 The animation need to be additive, in order to handle multiple animation. 为了处理多个动画,需要添加动画。 But the animation add to the line CAShaperLayer makes the whole view goes black. 但是添加到CAShaperLayer行的动画使整个视图变黑。 Anything wrong? 哪里不对了?

Here is some code. 这是一些代码。 TIA. TIA。

- (void)startHorizontalAnimation:(int)duplicateNum {
    // circle animation
    const double distance = 30;
    int totalTime = 600;
    int timeEachDirection = 5;
    double zInterpolation = self.zPosition / duplicateNum;
    double position = distance * 2 * zInterpolation - distance;

    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"position.x";

    NSMutableArray *valueArr = [[NSMutableArray alloc] initWithObjects:@0, nil];
    for (int i = 0; i < totalTime / (timeEachDirection * 2); ++i) {
        [valueArr addObject:[NSNumber numberWithDouble:position]];
        [valueArr addObject:[NSNumber numberWithDouble:-position]];
    }
    [valueArr addObject:@0];
    animation.values = valueArr;


    animation.additive = YES;
    animation.duration = totalTime;

    NSMutableArray *animationArr = [[NSMutableArray alloc] init];
    for (int i = 0; i < [valueArr count] - 1; ++i) {
        [animationArr addObject:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    }

    animation.timingFunctions = animationArr;

    animation.delegate = self.delegate;

    [self addAnimation:animation forKey:ANIMI_HORIZONTALD_DISPERSE];

    // line animation
    CAAnimation *startAnimation = [self copyPositionFrom:animation modifyStart:YES onDirectionX:YES];
    CAAnimation *endAnimation = [self copyPositionFrom:animation modifyStart:NO onDirectionX:YES];

    [self.lineFrom addAnimation:startAnimation forKey:nil];
    [self.lineTo addAnimation:endAnimation forKey:nil];

}

// create line animation according to the circle animation, changing the start point or end point on direction x or y.
- (CAAnimation *)copyPositionFrom:(CAKeyframeAnimation *)animation modifyStart:(BOOL)modifyStart onDirectionX:(BOOL)directionX {
    CAKeyframeAnimation *newAnimation = [CAKeyframeAnimation animationWithKeyPath:@"path"];
    newAnimation.additive = animation.additive;
    newAnimation.duration = animation.duration;
    newAnimation.timingFunction = animation.timingFunction;
    newAnimation.delegate = animation.delegate;


    CGPathRef lineCGPath = ((CAShapeLayer *)self.lineFrom).path;
    NSMutableArray *bezierPoints = [NSMutableArray array];
    // MyCGPathApplierFunc is according to http://stackoverflow.com/a/5714872/531966
    CGPathApply(lineCGPath, (__bridge void *)(bezierPoints), MyCGPathApplierFunc);

    __block NSMutableArray *pathArray = [NSMutableArray array];
    [animation.values enumerateObjectsUsingBlock:^(NSNumber *value, NSUInteger idx, BOOL *stop) {

        CGPoint startPoint = [[bezierPoints objectAtIndex:0] CGPointValue];
        CGPoint endPoint = [[bezierPoints objectAtIndex:1] CGPointValue];

        // modify the position additively
        if (modifyStart) {
            if (directionX) {
                startPoint.x += [value floatValue];
            } else {
                startPoint.y += [value floatValue];
            }
        } else {
            if (directionX) {
                endPoint.x += [value floatValue];
            } else {
                endPoint.y += [value floatValue];
            }
        }

        UIBezierPath *linePath = [UIBezierPath bezierPath];
        [linePath moveToPoint:startPoint];
        [linePath addLineToPoint:endPoint];

        [pathArray addObject:linePath];
    }];

    newAnimation.values = pathArray;
    return newAnimation;
}

@interface CircleShapeLayer : CAShapeLayer

@property (nonatomic, weak) CAShapeLayer *lineFrom; // the line goes from the circle
@property (nonatomic, weak) CAShapeLayer *lineTo; // the line goes to the circle

@end

I would suggest creating your animations in sets, with the same timing. 我建议您以相同的时间在集合中创建动画。

To animate 2 circles and a line between them, animate each circle layer's position property as a separate CABasicAnimation, and a third CABasicAnimation to animate the line (You'd do this with a CAShapeLayer where you animate the start and endpoints of the path that's in the shape layer.) 要为2个圆及其间的线设置动画,请为每个圆层的position属性设置为单独的CABasicAnimation动画,并为第三个CABasicAnimation设置线动画(您可以使用CAShapeLayer进行动画处理,在该动画中设置路径的起点和终点形状层。)

Alternately, you could use a single shape layer for both circles and the connecting line and animate all the changes to the path at once (have the path contain 2 circles and the line, and create an animation that changes the control points of 3 at once.) 或者,您可以对圆形和连接线使用单个形状图层,并同时对路径进行所有动画处理(路径包含2个圆形和线,并创建一个动画,以同时更改控制点3个。)

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

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