Question

I am currently having a map(tilemap) within a layer that i would like to pan/zoom using the following code:

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

    if([recognizer state] == UIGestureRecognizerStateBegan) {

            _lastScale = [recognizer scale];

            CGPoint touchLocation1 = [recognizer locationOfTouch:0 inView:recognizer.view];
            CGPoint touchLocation2 = [recognizer locationOfTouch:1 inView:recognizer.view];

            CGPoint centerGL = [[CCDirector sharedDirector] convertToGL: ccpMidpoint(touchLocation1, touchLocation2)];
            _pinchCenter = [self convertToNodeSpace:centerGL];
    }

    else if ([recognizer state] == UIGestureRecognizerStateChanged) {

//        NSLog(@"%d", recognizer.scale);

        CGFloat newDeltaScale = 1 -  (_lastScale - [recognizer scale]);
        newDeltaScale = MIN(newDeltaScale, kMaxScale / self.scale);
        newDeltaScale = MAX(newDeltaScale, kMinScale / self.scale);

        CGFloat newScale = self.scale * newDeltaScale;

        //self.scale = newScale;
        [self scale: newScale atCenter:_pinchCenter];

        _lastScale = [recognizer scale];
    }
}

- (void) scale: (CGFloat) newScale atCenter: (CGPoint) center {

    CGPoint oldCenterPoint = ccp(center.x * self.scale, center.y * self.scale);

    // Set the scale.
    self.scale = newScale;

    // Get the new center point.
    CGPoint newCenterPoint = ccp(center.x * self.scale, center.y * self.scale);

    // Then calculate the delta.
    CGPoint centerPointDelta  = ccpSub(oldCenterPoint, newCenterPoint);

    // Now adjust your layer by the delta.
    self.position = ccpAdd(self.position, centerPointDelta);
}

my issue is that the zoom is not taking in effect at the center of the pinch even though i am trying to change it at the same time i am zooming in through this method: (void) scale: (CGFloat) newScale atCenter: (CGPoint) center. Is there any reason this might not happening properly? Also how do i convert to the center location of the pinch into the coordinates system for my scene/layer?

Was it helpful?

Solution

Everything was actually fine in my approach. The problem i was having though is that the layer anchor point was different from the map one i defined, which was introducing an offset during scaling. I had to set both anchor to ccp(0,0).

The concersion from the screen coordinates of the pinch gesture's center to the layer is correct and can be achived by the following instructions when using UIKIt gesture recognizers:

CGPoint centerGL = [[CCDirector sharedDirector] convertToGL: ccpMidpoint(touchLocation1, touchLocation2)];
_pinchCenter = [self convertToNodeSpace:centerGL];

OTHER TIPS

First of all, you cannot do ([recognizer state] == UIGestureRecognizerStateBegan) because state is a bitfield! So you have to do:

([recognizer state] & UIGestureRecognizerStateBegan)

The center location of your pinch is going to be in coordinates on the screen basically. As far as how you convert that into your own coordinate system, you need to figure out what the bounds on the device's screen are of the part of your scene/layer that is shown at the time the gesture starts. That's going to be coordinates like 10,10 x 200,200 or something, representing the pixel grid of the screen. Then you will have to figure out, in the coordinate system of your own app's scene/layer, what 10,10 maps to, and what 200,200 maps to. From there, you can derive a factor to apply to the screen coordinates of the pinch gesture's center, that would translate the pinch gesture's screen coordinates into the scene/layer coordinates.

What you're trying to do is tricky because as you scale the scene/layer, your centering that scaling around a point that's not in the center of the view. I'm sure if you look through some of Apple's sample code in one of the map-related apps, you can probably find some examples of methods that have this kind of pinch zooming.

I hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top