2017-07-12 61 views
1

我試圖在SpriteKit(Objective C for Mac OS)中創建一個如下所示的水平滑塊。SpriteKit中的自定義滑塊

enter image description here

我肯定做錯了什麼,因爲滑塊的「旋鈕」永不移至左側,只向右移動,我不知道是什麼問題。我正在使用mouseDragged:方法來處理所有事情。這裏的代碼如下:

Slider.m

#import "Slider.h" 

@interface Slider() 

@property CGSize dimensions; 
@property SKSpriteNode *background, *foreground, *knob; 

@end 

@implementation Slider 

-(instancetype) initWithDimensions:(CGSize)dimensions Percentage:(double)percentage { 
    if (self = [super init]) { 
     _dimensions = dimensions; 
     _percentage = percentage; 
     [self initBackgroundSprite]; 
     [self initForegroundSprite]; 
     [self initKnob]; 
     self.userInteractionEnabled = YES; 
    } 
    return self; 
} 

-(void) initBackgroundSprite { 
    _background = [SKSpriteNode spriteNodeWithImageNamed:@"sliderBG"]; 
    _background.centerRect = CGRectMake(6.0/13.0, 5.0/11.0, 1.0/13.0, 1.0/11.0); 
    [_background setAnchorPoint:CGPointMake(0, 0.5)]; 
    double xScale = _dimensions.width/_background.frame.size.width; 
    double yScale = _dimensions.height/_background.frame.size.height; 
    [_background setXScale:xScale]; 
    [_background setYScale:yScale]; 
    [self addChild:_background]; 
} 

-(void) initForegroundSprite { 
    _foreground = [SKSpriteNode spriteNodeWithImageNamed:@"sliderFG"]; 
    _foreground.centerRect = CGRectMake(6.0/13.0, 5.0/11.0, 1.0/13.0, 1.0/11.0); 
    [_foreground setAnchorPoint:CGPointMake(0, 0.5)]; 
    double xScale = _dimensions.width*_percentage/_foreground.frame.size.width; 
    double yScale = _dimensions.height/_foreground.frame.size.height; 
    [_foreground setXScale:xScale]; 
    [_foreground setYScale:yScale]; 
    [self addChild:_foreground]; 
} 

-(void) initKnob { 
    _knob = [SKSpriteNode spriteNodeWithImageNamed:@"sliderKnob"]; 
    _knob.centerRect = CGRectMake(6.0/13.0, 5.0/11.0, 1.0/13.0, 1.0/11.0); 
    [_knob setAnchorPoint:CGPointMake(0, 0.5)]; 
    double scaleFactor = 2/(_knob.frame.size.height/_background.frame.size.height); 
    NSLog(@"%f, %f", _knob.frame.size.height, _background.frame.size.height); 
    [_knob setScale:scaleFactor]; 
    [_knob setZPosition:2]; 
    [_knob setName:@"knob"]; 
    [self addChild:_knob]; 
} 

-(void) mouseDragged:(NSEvent *)event { 
    CGPoint location = [event locationInNode:self]; 
    NSArray *nodes = [self nodesAtPoint:location]; 

    for (SKNode *node in nodes) { 
     if ([node isKindOfClass:[SKSpriteNode class]]) { 
      SKSpriteNode *sprite = (SKSpriteNode*)node; 

      if ([sprite.name isEqualToString:@"knob"]) { 
       [self updateKnobPositionWithLocation:location]; 
      } 

     } 
    } 
} 

-(void) updateKnobPositionWithLocation:(CGPoint)location { 
    double x = location.x; 
    double y = _knob.position.y; //don't want the y-pos to change 

    double bgX = _background.position.x; //x pos of slider 
    double width = _background.frame.size.width; //width of slider 
    if (x > bgX + width)//if knob goes beyond width of slider, restrict to width 
     x = bgX + width; 
    else if (x < bgX) 
     x = bgX; 

    [_knob setPosition:CGPointMake(x, y)]; 
} 

下面就來說明行爲的視頻:

https://drive.google.com/open?id=0B8Zfr1yQCdf-OG5kZFRWNFgxd1k

+1

你有什麼x錨點?如果是0.5,則必須更改爲else if(x

+1

添加到@SimonePistecchia的評論我會猜測_background.position.x是你的背景的中心,你應該使用'_background.frame.minX'和'_background.frame.maxX'而不是'position.x '和'position.x + width'。如果你把旋鈕做成你的背景的一個孩子,那麼你只需要擔心'[寬度/ 2, 寬度/ 2]',因爲旋鈕是相對於其父母。 (我會建議像這樣格式化)另外,我會預測你的下一個問題將會隨着旋鈕移動到那個欄,我會建議尋找SKCropNode來達到這個效果。 – Knight0fDragon

+0

謝謝你們的回覆。我的所有節點的定位點(0,0.5),所以我認爲我的計算很好@SimonePistecchia對不對? '_knob'不是'_background'的孩子。我會更新代碼,以便看到整個班級。 – 02fentym

回答

0

我已經解決了所有的問題與滑塊類。感謝大家的幫助。如果有人有興趣,這裏是全碼:

Slider.h

#import <SpriteKit/SpriteKit.h> 

@interface Slider : SKSpriteNode 

@property double percentage; 

-(instancetype) initWithDimensions:(CGSize)dimensions Percentage:(double)percentage; 

@end 

Slider.m

#import "Slider.h" 

@interface Slider() 

@property CGSize dimensions; 
@property SKSpriteNode *background, *foreground, *knob; 
@property double backgroundWidth, foregroundWidth; 
@property bool isBeingUsed; 
@property SKLabelNode *percentageLabel; 

@end 

@implementation Slider 

//creates a slider with certain dimensions and at a specific starting percentage clamped [0, 1] 
-(instancetype) initWithDimensions:(CGSize)dimensions Percentage:(double)percentage { 
    if (self = [super init]) { 
     _dimensions = dimensions; 
     _percentage = percentage; 
     _isBeingUsed = NO; 
     [self initBackgroundSprite]; 
     [self initForegroundSprite]; 
     [self initKnob]; 
     [self initPercentageLabel]; 
     self.userInteractionEnabled = YES; 
    } 
    return self; 
} 

//sprite initialization 
-(void) initBackgroundSprite { 
    _background = [SKSpriteNode spriteNodeWithImageNamed:@"sliderBG"]; 
    _background.centerRect = CGRectMake(6.0/13.0, 5.0/11.0, 1.0/13.0, 1.0/11.0); 
    _backgroundWidth = _background.frame.size.width; 
    [_background setAnchorPoint:CGPointMake(0, 0.5)]; 
    double xScale = _dimensions.width/_backgroundWidth; 
    double yScale = _dimensions.height/_background.frame.size.height; 
    [_background setXScale:xScale]; 
    [_background setYScale:yScale]; 
    [self addChild:_background]; 
} 

-(void) initForegroundSprite { 
    _foreground = [SKSpriteNode spriteNodeWithImageNamed:@"sliderFG"]; 
    _foreground.centerRect = CGRectMake(6.0/13.0, 5.0/11.0, 1.0/13.0, 1.0/11.0); 
    [_foreground setAnchorPoint:CGPointMake(0, 0.5)]; 
    _foregroundWidth = _foreground.frame.size.width; 
    double xScale = _dimensions.width*_percentage/_foregroundWidth; 
    double yScale = _dimensions.height/_foreground.frame.size.height; 
    [_foreground setXScale:xScale]; 
    [_foreground setYScale:yScale]; 
    [self addChild:_foreground]; 
} 

-(void) initKnob { 
    _knob = [SKSpriteNode spriteNodeWithImageNamed:@"sliderKnob"]; 
    _knob.centerRect = CGRectMake(6.0/13.0, 5.0/11.0, 1.0/13.0, 1.0/11.0); 
    [_knob setAnchorPoint:CGPointMake(0.5, 0.5)]; 
    double scaleFactor = 2/(_knob.frame.size.height/_background.frame.size.height); 
    [_knob setScale:scaleFactor]; 
    [_knob setPosition:CGPointMake(_foreground.frame.size.width, -_knob.frame.size.height*0.05)]; 
    [_knob setZPosition:2]; 
    [_knob setName:@"knob"]; 
    [self addChild:_knob]; 
} 

-(void) initPercentageLabel { 
    _percentageLabel = [SKLabelNode labelNodeWithFontNamed:@"Hiragino Kaku Gothic Std"]; 
    [_percentageLabel setText:[NSString stringWithFormat:@"%.0f%%", _percentage*100]]; 
    [_percentageLabel setFontSize:15]; 
    double x = _dimensions.width * 1.05; 
    double y = _knob.frame.size.height*0.05; 
    [_percentageLabel setPosition:CGPointMake(x, y)]; 
    [_percentageLabel setHorizontalAlignmentMode:SKLabelHorizontalAlignmentModeLeft]; 
    [_percentageLabel setVerticalAlignmentMode:SKLabelVerticalAlignmentModeCenter]; 
    [self addChild:_percentageLabel]; 
} 

-(void) mouseDragged:(NSEvent *)event { 
    CGPoint location = [event locationInNode:self]; 
    _isBeingUsed = YES; 
    [self updateKnobPositionWithLocation:location]; 
} 

-(void) mouseDown:(NSEvent *)event { 
    [super mouseDown:event]; 
    CGPoint location = [event locationInNode:self]; 
    _isBeingUsed = YES; 
    [self updateKnobPositionWithLocation:location]; 
} 

-(void) mouseUp:(NSEvent *)event { 
    [super mouseUp:event]; 
    _isBeingUsed = NO; 
} 


-(void) updateKnobPositionWithLocation:(CGPoint)location { 
    if (_isBeingUsed) { 
     double x = location.x; 
     double y = _knob.position.y; //don't want the y-pos to change 

     double bgX = _background.position.x; //x pos of slider 
     double width = _background.frame.size.width; //width of slider 
     if (x > bgX + width)//if knob goes beyond width of slider, restrict to width 
      x = bgX + width; 
     else if (x < bgX) 
      x = bgX; 

     [_knob setPosition:CGPointMake(x, y)]; 
     [self updateForegroundPercentage]; 
     //NSLog(@"(%f, %f)", _knob.position.x, _knob.position.y); 
    } 
} 

-(void) updateForegroundPercentage { 
    _percentage = _knob.position.x/_background.frame.size.width; 
    double xScale = _dimensions.width*_percentage/_foregroundWidth; 
    [_foreground setXScale:xScale]; 

    [_percentageLabel setText:[NSString stringWithFormat:@"%.0f%%", _percentage*100]]; 
} 

@end