2017-07-12 9 views
1

私はSpriteKit(Mac OSのObjective C)で以下に示すような水平スライダーを作成しようとしています。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アンカーポイントは何ですか? ifが0.5の場合は、(x

+1

@SimonePistecchiaのコメントに_background.position.xがバックグラウンドの中心であると推測すると、 'position.xの代わりに' _background.frame.minX'と '_background.frame.maxX'を使うべきです'と' position.x + width'を使用します。ノブをあなたのバックグラウンドの子にした場合、ノブはその親に対して相対的であるため、 '[-width/2、 width/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 
関連する問題