Pergunta

Hi all you smart people out there! I want to create a touch interface to an iOS app, that allows the user to drag an object on the screen around. However, this object should be restricted to move along the perimeter of a circle, so that if the user is trying to drag the object outside that path, it would stick to the nearest point of that circle. I have done some iPhone programming, but my math is poor. Please help!

Foi útil?

Solução

All you have to do is set the frame of the view to follow the equation of a circle (of the form: (x-a)^2 + (y-b)^2 = r^2). Once you detect the touch point, you can restrict the view's frame according to the x or the y coordinate of the touch point (both ways are the same).

#define circleRadius 60.0 // r in the above eqtn
#define circlesCenter_X 160.0 // a in the above eqtn
#define circlesCenter_Y 200.0 // b in the above eqtn
#define circleCenter_y(x) sqrtf(circleRadius*circleRadius - (x-circlesCenter_X)*(x-circlesCenter_X))

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [[event touchesForView:firstPieceView] anyObject];
    CGPoint previousLocation = [touch previousLocationInView:self.view];
    CGPoint location = [touch locationInView:self.view];
    CGFloat delta_x = previousLocation.x - location.x; // constrained by x in this eg.
    CGFloat newX = firstPieceView.center.x-delta_x;
    // do limit the view's x-coordinate for possible solutions
    if(newX<circlesCenter_X - circleRadius)
        newX = circlesCenter_X - circleRadius;
    if(newX>circlesCenter_X + circleRadius)
        newX = circlesCenter_X + circleRadius;
    firstPieceView.center = CGPointMake(newX, circleCenter_y(newX)*(location.y>=circlesCenter_Y?1:-1) + circlesCenter_Y);
}

EDIT- Better solution:

#define circleRadius 60.0 // r in the above eqtn
#define circlesCenter_X 160.0 // a in the above eqtn
#define circlesCenter_Y 200.0 // b in the above eqtn
#define slope(x,y) (y-circlesCenter_Y)/(x-circlesCenter_X)
#define pointOnCircle_X(m) circleRadius/(sqrtf(m*m + 1))

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [[event touchesForView:self.view] anyObject];
    CGPoint location = [touch locationInView:self.view];
    CGFloat slope;
    CGPoint pointOnCircle;
    if(location.x==circlesCenter_X){// case for infinite slope
        pointOnCircle.x = circlesCenter_X;
        if(location.x<circlesCenter_X){
            pointOnCircle.y = circlesCenter_Y - circleRadius;
        }else{
            pointOnCircle.y = circlesCenter_Y + circleRadius;
        }
    }else{
        slope = slope(location.x,location.y);
        if(location.x<circlesCenter_X){
            pointOnCircle.x = circlesCenter_X - pointOnCircle_X(slope);
        }else{
            pointOnCircle.x = circlesCenter_X + pointOnCircle_X(slope);
        }
        pointOnCircle.y = slope * (pointOnCircle.x - circlesCenter_X) + circlesCenter_Y;
    }
    firstPieceView.center = pointOnCircle;
}

This can be applied similarly for Android, Blackberry, etc too!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top