使用nsbezierpath(objective-c)使球/圆在可可中移动? [英] Making a ball/circle move in cocoa using nsbezierpath(objective -c))?

查看:131
本文介绍了使用nsbezierpath(objective-c)使球/圆在可可中移动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在应用程序运行时在图像上创建一个点,然后尝试将点缓慢移动到其他位置。
这里是我的代码。这个代码工作,但有两个问题。

I am trying to Create a point on an image when the application runs and then try to move the point slowly to a different location. here is my code.This code works but there are two problems.

首先,处理已经发生在窗口加载之前,所以我只看到完成(我想显示一点移动到图像中的另一点)

First, The processing has already happened before the window loads so I see only the finished result.(I want to show one point moving to another point in the image)

第二,当我创建一个新点时,上一点不会被删除。

Second,The previous point is not removed when I create a new point.So it doesn't look like the point is moving rather it looks like it is being duplicated.How do I remove a point.

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
    NSGraphicsContext* gc = [NSGraphicsContext currentContext];

    // Save the current graphics context settings
    [gc saveGraphicsState];

    // Set the color in the current graphics context for future draw operations
    [[NSColor blackColor] setStroke];
    [[NSColor redColor] setFill];


    for(int i=1;i<100;i++){

        NSRect rect = NSMakeRect(130+i, 130, 10, 10);
        NSBezierPath* circlePath = [NSBezierPath bezierPath];
        [circlePath appendBezierPathWithOvalInRect: rect];

        // Outline and fill the path
        [circlePath stroke];
        [circlePath fill];


        //    // Restore the context to what it was before we messed with it
        //    [gc restoreGraphicsState];
    }
}


推荐答案

这是一个正常的实现:

@interface AppDelegate ()
@property ( nonatomic, readonly ) CALayer * ballLayer ;
@end

@implementation AppDelegate
@synthesize ballLayer = _ballLayer ;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    [ ((NSView*)self.window.contentView) setWantsLayer:YES ] ;
    [ self performSelectorOnMainThread:@selector( doAnimation ) withObject:nil waitUntilDone:NO ] ;
}

-(void)doAnimation
{
    [ self.ballLayer addAnimation:[ self createBallLayerAnimation ] forKey:nil ] ;
}

-(CALayer*)ballLayer
{
    if ( !_ballLayer )
    {
        CALayer * layer = [ CALayer layer ] ;
        NSImage * image = [[ NSImage alloc ] initWithContentsOfURL:[ NSURL URLWithString:@"http://etc-mysitemyway.s3.amazonaws.com/icons/legacy-previews/icons/glossy-black-icons-sports-hobbies/044450-glossy-black-icon-sports-hobbies-ball-beach.png" ] ] ;
        layer.contents = image ;
        layer.bounds = (CGRect){ .size = { 100, 100 } } ;

        [((NSView*)self.window.contentView).layer addSublayer:layer ] ;

        _ballLayer = layer ;
    }

    return _ballLayer ;
}

-(CAAnimation*)createBallLayerAnimation
{
    CAKeyframeAnimation * anim = [ CAKeyframeAnimation animationWithKeyPath:@"position" ] ;
    {
        CGPathRef p = [ self createBallAnimationPath ] ;
        anim.path = p ;
        CGPathRelease( p ) ;
    }
    anim.duration = 3.0 ;
    anim.repeatCount = FLT_MAX ;

    return anim ;
}

-(CGPathRef)createBallAnimationPath
{
    CGRect bounds = ((NSView*)self.window.contentView).bounds ;
    CGPathRef p = CGPathCreateWithEllipseInRect( CGRectInset( bounds, bounds.size.width * 0.25, bounds.size.width * 0.25 ), NULL ) ;
    return p ;
}
@end






您想阅读 CGPath CALayer ...

像其他人说的,不要在你的 applicationDidFinishLaunching 方法中 - 你应该在窗口/视图出现后做。如果你有从nib加载的你自己的NSView子类,一个选项可能是重写 -awakeFromNib

As others have said, don't do this in your applicationDidFinishLaunching method--you should do it after your window/view appears. If you have your own NSView subclass loaded from a nib, one option might be to override -awakeFromNib:

-(void)awakeFromNib
{
    [ super awakeFromNib ] ;
    [ self performSelectorOnMainThread:@selector( doAnimation ) withObject:nil waitUntilDone:NO ] ; // when the main thread runs again, call `-doAnimation`
}

您的视图子类也有一个 -doAnimation 方法(从 -awakeFromNib 调用,上面)

Then in your view subclass also have a -doAnimation method (called from -awakeFromNib, above)

-(void)doAnimation:
{
    CAAnimation * animation = [ CAKeyframeAnimation animationForKeyPath:@"position" ] ;
    CGPathRef path = [ self createBallAnimationPath ] ; // method -createBallAnimationPath is defined below...
    animation.path = path ;
    CGPathRelease( path ) ;
    [ self.ballLayer addAnimation:animation forKey:nil ] ; // ballLayer is the property that contains a reference to layer that contains the image you want to animate along the path
}

有一个方法来创建你的路径:

Have a method to create your path:

-(CGPathRef)createBallAnimationPath
{
    CGMutablePathRef result = CGPathCreateMutable() ;
    CGPathMoveToPoint( result, 100, 100 ) ;
    CGPathAddLineToPoint( result, 1000, 1000 ) ;
    return result ;
}

这篇关于使用nsbezierpath(objective-c)使球/圆在可可中移动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆