user2014474
user2014474

Reputation: 1117

Limit UIPanGestureRecognizer movement in circle

I am using UIPanGesturerecogniser to move a UIButton on the screen.

I am adding the gesture to the button in this way:

panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(move:)];
[panRecognizer setMinimumNumberOfTouches:1];
[panRecognizer setMaximumNumberOfTouches:1];
[panRecognizer setDelegate:self];

[ButtonNote addGestureRecognizer:panRecognizer];

and the method is

- (void)move:(id)sender {

    [[[(UITapGestureRecognizer*)sender view] layer] removeAllAnimations];

CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.ViewA];

    if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {

        firstX = [[sender view] center].x;
        firstY = [[sender view] center].y;

        [self.view addSubview:[(UIPanGestureRecognizer*)sender view]];

        if (self.Button1.frame.size.height > 200) {

        }
        else {

       }
    }

    translatedPoint = CGPointMake(firstX+translatedPoint.x, firstY+translatedPoint.y);

    [[sender view] setCenter:translatedPoint];

    if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded||[(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateCancelled||[(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateFailed){

        CGPoint fingerPoint2 = [(UIPanGestureRecognizer*)sender locationInView:self.BallBin.superview];

        if (CGRectContainsPoint(self.BallBin.frame, fingerPoint2)) {
            if (self.Button3.frame.size.height > 200) {

                UIPanGestureRecognizer *gesture = (UIPanGestureRecognizer *)sender;
                UIButton *button = (UIButton *)gesture.view;
                [[(UIPanGestureRecognizer*)sender view] removeFromSuperview];
                NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
                NSString *documentsDirectoryPath = [paths objectAtIndex:0];
                NSString *myFilePath = [documentsDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@", button.titleLabel.text]];
                NSFileManager *fileManager = [NSFileManager defaultManager];
                [fileManager removeItemAtPath:myFilePath error:NULL];

                [self performSelector:@selector(DeleteBusinessCard:) withObject:nil afterDelay:0.5];

            }
            else {
                [self.ViewA addSubview:[(UIPanGestureRecognizer*)sender view]];
        }
    }

        if (self.Button1.frame.size.height > 200) {

        }
        else {

            [self.ViewB addSubview:self.BallBin];
        }

                         }];
        }

        CGFloat finalX = translatedPoint.x + (.35*[(UIPanGestureRecognizer*)sender velocityInView:self.ViewA].x);
        CGFloat finalY = translatedPoint.y + (.35*[(UIPanGestureRecognizer*)sender velocityInView:self.ViewA].y);

        if(UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation])) {

            if(finalX < 0) {

                finalX = 0;
            }

            else if(finalX > 768) {

                finalX = 768;
            }

            if(finalY < 0) {

                finalY = 0;
            }

            else if(finalY > 1024) {

                finalY = 1024;
            }
        }

        else {

            if(finalX < 0) {

                finalX = 0;
            }

            else if(finalX > 1024) {

                finalX = 768;
            }

            if(finalY < 0) {

                finalY = 0;
            }

            else if(finalY > 768) {

                finalY = 1024;
            }
       }
    }
 }

I want to limit the movement of the button in a certain circle area on screen, for e.g. of radius 80. Now the button is moving all over the screen. Anyway ViewA is a UIView covering the whole screen.

Upvotes: 0

Views: 819

Answers (2)

Dennies Chang
Dennies Chang

Reputation: 582

We can have a logic to calculate the coordination to a particular center.

When the Pan Gesture is happening, the function should modify the center of the panning object, with example in the following code, the pannig object named pin, which is a 50x50 pts image, will be set to get around a Large Circle image with 194x194 pts, located in 63, 141.

And this the PanGesture handler code:

- (void)pinPanPiece:(UIPanGestureRecognizer *)gestureRecognizer {
CGPoint center = CGPointMake(63.0 + 194.0/2, 141.0+ 194.0/2);

UIView *piece = [gestureRecognizer view];

if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ||
    [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
    if (piece == pin) {

        CGPoint translation = [gestureRecognizer translationInView:[piece superview]];
        float newX = piece.frame.origin.x + translation.x;
        CGRect newFrame = piece.frame;

        CGPoint pinCenter = CGPointMake(newFrame.origin.x + newFrame.size.width / 2.0, newFrame.origin.y + newFrame.size.height / 2.0);
        newFrame.origin.x = newX;

        CGPoint newPinCenter = CGPointMake(newFrame.origin.x + newFrame.size.width / 2.0, newFrame.origin.y + newFrame.size.height / 2.0);

        float detectY = pinCenter.y + translation.y;
        BOOL bUpCenter = detectY < center.y;

        float deltaX = center.x - newPinCenter.x;
        float deltaY = sqrtf((97.0 *97.0) - (deltaX * deltaX));
        float newY;

        if (bUpCenter) {
            newY = center.y - deltaY;
        }
        else {
            newY = center.y + deltaY;
        }

        newY -= newFrame.size.height / 2.0;
        newFrame.origin.y = newY;

        if ((newPinCenter.x >= 63.0) && (newPinCenter.x <= 63.0+194.0)) {
           [piece setFrame:newFrame];
        }
    }

    [gestureRecognizer setTranslation:CGPointZero inView:[piece superview]];
}

}

Upvotes: 0

Eli Ganem
Eli Ganem

Reputation: 1479

Use Pitagoras Formula to calculate the distance between the current location and the start point. In your case:

if (gesture.state == UIGestureRecognizerStateChanged)
{
    if (sqrt(deltaX*deltaX + deltaY*deltaY) < 80)
        move view to finger's position
    else
        stay where you are
}

Upvotes: 1

Related Questions