iOS 使用 CGAffineTransform Make Translation 从一个视图的中心到另一个视图的中心绘制虚线动画第二个视图

iOS draw dotted line from one view's center to another view's center animating second view using CGAffineTransformMakeTranslationg

我正在尝试构建一些具有挑战性的东西。

基本上,我在这里得到了这个场景:

由于这个 Whosebug 的回答,我能够画出虚线:

Draw dotted (not dashed!) line, with IBDesignable in 2017

虚线画在里面:

-(void)drawRect:(CGRect)rect
{
    [self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo1.center];

    [self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo2.center];

    [self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo3.center];

    [self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo4.center];

    [self drawDottedLineFromStartingPoint:self.mainPhoto.center ToEndPoint:self.photo5.center];
}

-(void)drawDottedLineFromStartingPoint:(CGPoint)startPoint ToEndPoint:(CGPoint)endPoint
{
    UIBezierPath *path = [[UIBezierPath alloc] init];

    [path moveToPoint:startPoint];
    [path addLineToPoint:endPoint];
    path.lineWidth = 4;

    CGFloat dashes[] = {path.lineWidth * 0, path.lineWidth * 2};

    [path setLineDash:dashes count:2 phase:0];
    path.lineCapStyle = kCGLineCapRound;

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSetStrokeColorWithColor(ctx, [ThemeManager mediumTextColor].CGColor);

    [path stroke];
}

我面临的问题是每个较小的圆圈都通过落入到位而动画化。

我制作小圆圈动画的方法是使用类似的东西:

CGAffineTransformMakeTranslation(0, 50);

当我这样做时,虚线是从大圆圈到小圆圈的最终静止位置绘制的,虚线不会 "follow" 小圆圈正在动画并掉落.

所以你看到的是这样的:

对于我想要实现的目标,有什么简单的解决方案吗?我试过考虑使用 NSTimer 并计算斜边长度,除以持续时间,但我没有走得太远:D

我前一段时间做了一个应用程序,它做了一些类似于你想要的事情,所以我修改了它来做你想做的事情。我有一个名为 NodeView 的 class,它只是一个 UIView subclass 和一个名为 line 的 属性,它是一个 UIBezierPath(你可以用 subclass UIImageView 做同样的事情事物)。我使用计时器来移动节点,并观察节点的中心 属性,这样我就可以调用 drawRect 来描边节点的线。这个版本一个一个地移动节点。我将控制器的视图设置为 UIView 的子 class,这是该子class、

中的代码
#import "RDView.h"
#import "NodeView.h"

@interface RDView ()
@property (weak, nonatomic) IBOutlet UIView *bigView; // this is equivalent to your large image view from which the other image views drop
@property (strong,nonatomic) NSMutableArray *paths;
@end

@implementation RDView


-(void)didMoveToWindow {
    self.bigView.layer.cornerRadius = self.bigView.frame.size.width/2.0;
    self.paths = [NSMutableArray new];
    self.nodes = [NSMutableArray new];
    for (int i = 0; i<5; i++) {
        NodeView *aNode = [NodeView new];
        CGFloat hue = arc4random_uniform(1000)/1000.0;
        aNode.backgroundColor = [UIColor colorWithHue:hue saturation:1 brightness:1 alpha:1.0];
        aNode.frame = CGRectMake(0, 0, 40, 40);
        [self.bigView layoutIfNeeded];
        aNode.center = self.bigView.center;
        [self addSubview:aNode];
        [self.nodes addObject:aNode];

        aNode.line = [UIBezierPath bezierPath];
        CGFloat dashes[] = {0, aNode.line.lineWidth * 4};
        [aNode.line setLineDash:dashes count:2 phase:0];
        aNode.line.lineCapStyle = kCGLineCapRound;
        [aNode.line moveToPoint:[self.bigView center]];
    }
    [self bringSubviewToFront:self.bigView];
    for (NodeView *aNode in self.nodes) {
        [aNode addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:nil];
    }

    [self performSelector:@selector(dropNodes) withObject:nil afterDelay:1];
}

-(void)dropNodes {
    static int i = 0;
    [NSTimer scheduledTimerWithTimeInterval:.005 target:self selector:@selector(dropNode:) userInfo:@{@"nodeIndex":@(i)} repeats:YES];
    i++;
}

-(void)dropNode:(NSTimer *) timer {
    NSInteger i = [timer.userInfo[@"nodeIndex"] integerValue];
    NodeView *node = self.nodes[i];
    [node setCenter: CGPointMake(node.center.x + (i-2)*.25, node.center.y + 1)]; // spread the nodes out horizontally and move down
    [node.line addLineToPoint:node.center];
    if (node.center.y > 400) {
        [timer invalidate];
        if (i < self.nodes.count-1) {
            [self dropNodes];
        }
    }
}


-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"center"] ) {
        [self setNeedsDisplay];
    }
}


- (void)drawRect:(CGRect)rect {
    for (NodeView *aNode in self.nodes) {
        [aNode.line stroke];
    }
}

你可以在这里找到我的项目 link,http://jmp.sh/lIl5MXp

我要感谢 rdelmar 启发了我以及这个 link 告诉我一个视图的 presentationLayer frame

ios observing change in frame of a UIView during animation

在这种情况下我没有使用 KVO,但我确实使用 NSTimer 和重绘屏幕解决了我的问题。

基本上我在为圆圈掉落的动画开始后,我还安排了一个每 0.01 秒触发一次的 NSTimer,回调方法检查最后的圆圈照片是否已完成动画,如果是,则使计时器无效:

-(void)showIntroAnimations
{
    self.hasBegunAnimating = YES;

    // start animating circle photos falling down

    [self setupObservers];
}

-(void)setupObservers
{
    [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(redrawLines:) userInfo:nil repeats:YES];
}

-(void)redrawLines:(NSTimer *)timer
{
    if([self.photo5.layer animationKeys].count > 0)
    {
        [self setNeedsDisplay];
    }
    else
    {
        [timer invalidate];
        timer = nil;
    }
}