2015-01-22 3 views
0

У меня есть немного сложная вещь, которую я пытаюсь построить.iOS рисовать пунктирную линию от центра одного взгляда к другому центру зрения, оживляя второй вид, используя CGAffineTransformMakeTranslationg

В принципе, я получил этот сценарий здесь:

scenario

Я могу нарисовать пунктирную линию благодаря этому StackOverflow ответ:

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); 

Когда я делаю это, пунктирные линии черпается из большого круга в конечное положение покоя меньшего круга, пунктирные линии не «следуют» по меньшему кругу, так как он анимируется и падает.

Так что вы видите, это:

wrong result

Есть ли простое решение, что я пытаюсь достичь? Я пробовал думать об использовании NSTimer и вычислять длину гипотенузы, делить на длительность, но я не очень далеко: D

ответ

2

Я сделал приложение некоторое время назад, что сделал что-то похожее на то, что вы хотите, поэтому Я изменил его, сделав то, что вы пытаетесь сделать. У меня есть класс под названием NodeView, это просто подкласс UIView с одним свойством, называемым линией, который является UIBezierPath (вы можете подклассифицировать UIImageView на то же самое). Я использую таймер для перемещения узлов и наблюдаю за свойством центра узла, поэтому я могу вызвать drawRect, чтобы погладить линию узла. Эта версия перемещает узлы один за другим. Я поставил точку зрения контроллера к подклассу UIView, и вот код в этом подклассе

#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]; 
    } 
} 

Вы можете найти ссылку на мой проект здесь, http://jmp.sh/lIl5MXp

+0

Спасибо, что указал мне в правильном направлении. Я решил это по-своему, используя NSTimer и перерисуя свой экран: D Я действительно модифицировал метод drawRect, чтобы указать на начало представления Layer frame + circle width/2.0, чтобы получить фактическое происхождение. – Zhang

0

Я хочу поблагодарить rdelmar за просветить меня а также ссылка информируя меня о виде-х presentationLayer frame

ios observing change in frame of a UIView during animation

Я не использовал КВО в этом случае, но я решил свою проблему с помощью NSTimer и перерисовок моего экрана.

В принципе, после начала анимации для кругов, падающих вниз, я также планирую NSTimer, который запускает каждые 0,01 секунды, и метод обратного вызова проверяет, завершила ли окончательная анимация круга, если да, то недействительность таймера:

-(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; 
    } 
}