Rotate a UIImageView UITouch

Discussion in 'iOS Programming' started by larswik, Nov 2, 2011.

  1. larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #1
    I started to read Beginning iPhone Game Development by Apress. I decided to experiment a little to better understand so I created a Color wheel in Photoshop that was 250 x 250. I made the view background black and the edges of my wheel black.

    I used this code which I wrote to turn the wheel which it does just fine.
    Code:
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
        
        UITouch *touch = [[event allTouches] anyObject];
        CGPoint touchLocation = [touch locationInView:touch.view];
        
        tempF = atan2(touchLocation.y - theDisc.center.y, touchLocation.x - theDisc.center.x);
            
        theDisc.center = CGPointMake(theDisc.center.x, theDisc.center.y);
        theDisc.transform = CGAffineTransformMakeRotation(tempF);
        
        theValue.text = [NSString stringWithFormat:@"%f",tempF];
      
    }
    
    The problem is that when I take my finger off of the wheel and place it someplace else to turn the wheel the wheel's rotation snaps to the new CGPoint location. The interesting thing is that when it spans to the new location it is the right side of the disc (I know the right side of a circle)

    Since this is new territory for me I thought I would check to see if there is anything that I am unaware of to adjust for this offset? Or a different approach to spinning the wheel. I don't want to continue down the wrong path if I am.
     

    Attached Files:

  2. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #2
    transform is an animatable property. Change the transform inside an animation block.

    Actually I haven't tried this myself so I'm not sure of the details but that's the way you make a smooth change between states. You might want to alter the duration of the animation based on the angular change. Also, you might want to try different animation curves to see how they affect the rotation.
     
  3. North Bronson macrumors 6502

    Joined:
    Oct 31, 2007
    Location:
    San José
    #3
    I am not sure if this is exactly the problem, but one thing I noticed is that:

    Code:
     theDisc.transform = CGAffineTransformMakeRotation(tempF);
    is not aggregating changes to your transformation -- each time you set the property you are setting it without respect to where it was before. For example:

    Code:
    CGAffineTransform transform = theDisc.transform;
    
    CGAffineTransformRotate(transform, tempF);
    
    theDisc.transform = transform;
    will make your changes look like they are picking up from where the view was before. Is that one of the problems that you were having?

    I have done this sort of thing with gesture recognizers and it's super-easy. I haven't looked through the actual touch-handling in a while.
     
  4. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #4
    Thanks for the responses.

    North Bronson, PhoneyDeveloper - It sounds like you are understanding the problem.
    Yes. Now it will only continue where it left off if I place my finger in the exact place I removed my finger from. IF I place it some place else and then start to drag my finger the UIImageView wil' 'snap' the rotation to the new location first and then rotate smoothly, instead of just something continuing where it stopped the last place the finger was removed from. Let me break down the code so I better understand it.

    This code sets the CGPoint to where the finger is placed on the screen
    Code:
    CGPoint touchLocation = [touch locationInView:touch.view];
    This code finds the offset of my touch for y and x axis and finds the angle which I add to a float instance variable.
    Code:
     tempF = atan2(touchLocation.y - theDisc.center.y, touchLocation.x - theDisc.center.x);
    
    This code set the center of my disc that it the rotation point of my UIImageView
    Code:
    theDisc.center = CGPointMake(theDisc.center.x, theDisc.center.y);
    This code sets / updates the UIImageView transform property to rotate to the tempF float value as my finger drags on the screen.
    Code:
    theDisc.transform = CGAffineTransformMakeRotation(tempF);
    I hope I said all that correctly. So as you said here
    Code:
    each time you set the property you are setting it without respect to where it was before
    That would be an 'offset' from the last position of where the finger was removed from the screen to the new location.

    So now your 3 lines of code, so I understand them. First looks like you are setting the property of theDisc.transform to transform.
    Code:
    CGAffineTransform transform = theDisc.transform;
    The next part I don't get really? it takes 2 parameters the transform and the float value called tempF. Is this to calculate the offset from the last touch?

    Code:
    CGAffineTransformRotate(transform, tempF);
    Lastly you are assigning transform back to theDisc.transform property
    Code:
    theDisc.transform = transform;
     
  5. North Bronson macrumors 6502

    Joined:
    Oct 31, 2007
    Location:
    San José
    #5
    Now I understand what is happening.

    Code:
    theDisc.center = CGPointMake(theDisc.center.x, theDisc.center.y);
    Does the application work exactly the same if you remove this line? What exactly are you doing with this line?

    The issue seems to be that when you take the user's touch, you are finding the angle with which that point is displaced *from the origin*. The origin, in this case, is the positive X-axis.

    What it sounds like you want to do is that if the user touches in any arbitrary point, and then drags their finger, you want to find the angle with which that point is displaced *relative to where their finger initially landed*.

    Do you see how these two approaches are different? Do you see how you might design the second approach?
     
  6. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #6
    Thanks North for your continuing help on this.

    I did remove this code and it worked fine.
    Code:
    theDisc.center = CGPointMake(theDisc.center.x, theDisc.center.y);
    That code was to identify the center of the UIImageView which it would rotate around. It appears I do not need that.

    BINGO!
    Needless to say this test did not work as I thought. I think the answer is in making the new touch point be equal to the last touch point. But I am unsure as to how to calculate and implement that offset. You mentioned that I am working with the X-axis, but would it not be both the X and Y Axis?

    I kind of see what I need to do. But I was unsure since Objective - C is so large I was not sure if there was a method for the offset from the previous touch point to the new one.

    I did try this last night by getting the last touched location
    Code:
    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    
        lastNumber = tempF;
    }
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
        UITouch *touch = [[event allTouches] anyObject];
        CGPoint touchLocation = [touch locationInView:touch.view];
        
        tempF = atan2(touchLocation.y - theDisc.center.y, touchLocation.x - theDisc.center.x);
        
        newValue = tempF - lastNumber; // Attempt to use for offset
    
        theDisc.transform = CGAffineTransformMakeRotation (newValue);
    
        theValue.text = [NSString stringWithFormat:@"%f",newValue]; // displays the radian number
    }
    
     

Share This Page