UIPinchGestureRecognizer проблема

Хорошо, я прочитал несколько сообщений об этом (например, Жесты UIImageView (масштабирование, поворот) Вопрос), но я не могу решить свою проблему.

У меня есть следующая настройка: SKScene, SKNode _backgroundLayer и 9 SKSpriteNodes, которые представляют собой плитки, составляющие фон и прикрепленные к _backgroundLayer. Поскольку эти 9 плиток образуют квадрат 3x3 и они довольно большие, мне нужно увеличить масштаб и посмотреть на другие узлы SKSpriteNode, которые будут поверх этих 9 фоновых изображений.

Есть две проблемы: 1) Когда я зажимаю, чтобы увеличить или уменьшить масштаб, кажется, что он увеличивается/уменьшается из местоположения (0,0) _backgroundLayer, а не из положения касания.

2) Я добавил некоторые ограничения, чтобы пользователь не мог прокручивать 9 фоновых изображений. В целом это работает. Однако, если я увеличу масштаб, затем перейду к верхней части 9 фоновых изображений, а затем уменьшу масштаб, граничные условия сойдут с ума, и пользователь сможет увидеть черное пространство за пределами фоновых изображений. Мне нужен способ ограничить степень уменьшения масштаба, которую может сделать пользователь, в зависимости от того, где он находится.

Любые идеи? Спасибо!

Я включаю свой код ниже:

 #import "LevelSelectScene.h"
    #import "TurtleWorldSubScene.h"

    @interface LevelSelectScene ()
    @property (nonatomic, strong) SKNode *selectedNode;
    @end

    @implementation LevelSelectScene
    {
     SKNode *_backgroundLayer;
    }

    -(id)initWithSize:(CGSize)size {
    if (self = [super initWithSize:size]) {
        /* Setup your scene here */

        _backgroundLayer = [SKNode node];
        _backgroundLayer.name = @"backgroundLayer";

        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {

            [_backgroundLayer setScale:0.76];

        } else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && IS_WIDESCREEN) {

        } else {
            [_backgroundLayer setScale:0.36];
        }


        [self addChild:_backgroundLayer];

        SKTexture *backgroundTexture = [SKTexture textureWithImageNamed:@"levelSelect"];
        int textureID = 0;

        for (int i = 0; i<3; i++) {
            for (int j = 0; j<3; j++) {

                SKSpriteNode *background = [SKSpriteNode spriteNodeWithTexture:backgroundTexture];

                background.anchorPoint = CGPointZero;
                background.position = CGPointMake((background.size.width)*i, (background.size.height)*j);
                background.zPosition = 0;
                background.name = [NSString stringWithFormat:@"background%d", textureID];

                textureID++;

                [_backgroundLayer addChild:background];
            }
        }

        [TurtleWorldSubScene displayTurtleWorld:self];

    }
    return self;
}

- (void)didMoveToView:(SKView *)view {
    UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanFrom:)];
    [[self view] addGestureRecognizer:panGestureRecognizer];

    //UITapGestureRecognizer * tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    //  [self.view addGestureRecognizer:tapRecognizer];
    UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
    [[self view] addGestureRecognizer:pinchGestureRecognizer];
}

- (void)handlePanFrom:(UIPanGestureRecognizer *)recognizer {

    if (recognizer.state == UIGestureRecognizerStateBegan) {

        CGPoint touchLocation = [recognizer locationInView:recognizer.view];

        touchLocation = [self convertPointFromView:touchLocation];

        SKNode *node = [self nodeAtPoint:touchLocation];

        _selectedNode = node;

    } else if (recognizer.state == UIGestureRecognizerStateChanged) {

        CGPoint translation = [recognizer translationInView:recognizer.view];
        translation = CGPointMake(translation.x, -translation.y);

        CGPoint initialPosition = CGPointAdd(_backgroundLayer.position, translation);

        _backgroundLayer.position = [self boundLayerPos:initialPosition];
        [recognizer setTranslation:CGPointZero inView:recognizer.view];

    } else if (recognizer.state == UIGestureRecognizerStateEnded) {

        float scrollDuration = 0.2;
        CGPoint velocity = [recognizer velocityInView:recognizer.view];
        CGPoint pos = [_backgroundLayer position];
        CGPoint p = CGPointMultiplyScalar(velocity, scrollDuration);

        CGPoint newPos = CGPointMake(pos.x + p.x, pos.y - p.y);
        newPos = [self boundLayerPos:newPos];

        [_backgroundLayer removeAllActions];
        SKAction *moveTo = [SKAction moveTo:newPos duration:scrollDuration];
        [moveTo setTimingMode:SKActionTimingEaseOut];
        [_backgroundLayer runAction:moveTo];

    }
}

- (void)handlePinch:(UIPinchGestureRecognizer *) recognizer
{

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {


        if(_backgroundLayer.xScale*recognizer.scale < 0.76) {

            //SKSpriteNode *backgroundTile = (SKSpriteNode *)[_backgroundLayer childNodeWithName:@"background0"];

            [_backgroundLayer setScale:0.76];
        } else if(_backgroundLayer.xScale*recognizer.scale > 2) {
            [_backgroundLayer setScale:2.0];
        } else {
            [_backgroundLayer runAction:[SKAction scaleBy:recognizer.scale duration:0]];
        }

    } else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && IS_WIDESCREEN) {

    } else {
        if(_backgroundLayer.xScale*recognizer.scale < 0.36) {
            [_backgroundLayer setScale:0.36];
        } else if(_backgroundLayer.xScale*recognizer.scale > 2) {
            [_backgroundLayer setScale:2.0];
        } else {
            [_backgroundLayer runAction:[SKAction scaleBy:recognizer.scale duration:0]];
        }
    }

    recognizer.scale = 1;
}

- (CGPoint)boundLayerPos:(CGPoint)newPos {
    SKSpriteNode *backgroundTile = (SKSpriteNode *)[_backgroundLayer childNodeWithName:@"background0"];

    CGPoint retval = newPos;
    retval.x = MIN(retval.x, 0);
    retval.x = MAX(retval.x, -(backgroundTile.size.width*_backgroundLayer.xScale*3)+self.size.width);
    retval.y = MIN(retval.y, 0);
    retval.y = MAX(retval.y, -(backgroundTile.size.height*_backgroundLayer.xScale*3)+self.size.height);

    return retval;
}

person μ4ρκ05    schedule 25.01.2014    source источник