iOS从一个视图的中心绘制虚线到另一个视图的中心动画第二个视图使用CGAffineTransform进行翻译

Posted

技术标签:

【中文标题】iOS从一个视图的中心绘制虚线到另一个视图的中心动画第二个视图使用CGAffineTransform进行翻译【英文标题】:iOS draw dotted line from one view's center to another view's center animating second view using CGAffineTransformMakeTranslationg 【发布时间】:2015-01-22 16:06:00 【问题描述】:

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

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

感谢 *** 的回答,我可以画出虚线:

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

当我这样做时,虚线从大圆圈绘制到小圆圈的最终静止位置,虚线不会“跟随”小圆圈,因为它正在动画并下降。

所以你看到的是这样的:

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

【问题讨论】:

【参考方案1】:

我不久前制作了一个应用程序,该应用程序的功能与您想要的类似,因此我对其进行了修改,以实现您想要做的事情。我有一个名为 NodeView 的类,它只是一个 UIView 子类,它有一个名为 line 的属性,它是一个 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

【讨论】:

感谢您为我指明正确的方向。我使用 NSTimer 以我自己的方式解决了它并重绘了我的屏幕:D 我确实修改了 drawRect 方法以指向表示层框架原点 + 圆宽度 / 2.0 以获得实际原点。【参考方案2】:

我要感谢 rdelmar 对我的启发以及这个链接告诉我一个视图的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;
    

【讨论】:

以上是关于iOS从一个视图的中心绘制虚线到另一个视图的中心动画第二个视图使用CGAffineTransform进行翻译的主要内容,如果未能解决你的问题,请参考以下文章

如何在ios中从一个视图导航到另一个视图?

在 Swift iOS 中单击按钮时将视图移动到另一个视图

在 IOS 中从视图导航到另一个视图时的默认时间是多少

iOS:如何将内容从滚动视图复制到另一个滚动视图

将视图从一个控制器传递到另一个控制器 iOS

将数据从 didSelectRowAtIndexPath 传递到另一个视图控制器 ios7