2015-01-22 4 views
0

빌드하려는 도전 과제가 있습니다.iOS는 한 뷰의 중심점에서 다른 뷰의 중심점으로 점선으로 그립니다. CGAffineTransformMakeTranslationg를 사용하여 두 번째 뷰를 애니메이션화합니다.

기본적으로, 여기에이 시나리오를 가지고 :

나는이 유래 응답에 점선 감사를 그릴 수 있어요

scenario

: 점선 그리기가 완료

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라는 클래스가 있습니다.이 클래스는 UIBezierPath 인 라인이라는 하나의 속성을 가진 UIView 하위 클래스입니다 (동일한 작업을 수행하기 위해 UIImageView를 하위 클래스로 만들 수 있음). 타이머를 사용하여 노드를 이동하고 node의 center 속성을 관찰하여 drawRect를 호출하여 노드의 선을 획 렬할 수 있습니다. 이 버전은 노드를 하나씩 이동합니다. 나는 현재 내 프로젝트에 대한 링크를 찾을 수 있습니다

#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 실제 프레임을 얻으려면 presentation 레이어 프레임 원점 + 원 너비/2.0을 가리 키도록 drawRect 메서드를 수정했습니다. – Zhang

0

내가 나를 계몽을위한 rdelmar 감사드립니다,있는 UIView의 서브 클래스로 컨트롤러의보기를 설정하고, 여기에 서브 클래스의 코드입니다 물론이 링크에 대해 저를 알리는로보기의 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; 
    } 
}